6464 * Base drawable class for Material Shapes that handles shadows, elevation, scale and color for a
6565 * generated path.
6666 */
67- public class MaterialShapeDrawable extends Drawable implements TintAwareDrawable {
67+ public class MaterialShapeDrawable extends Drawable
68+ implements TintAwareDrawable , ShapeAppearanceModel .OnChangedListener {
6869
6970 private static final float SHADOW_RADIUS_MULTIPLIER = .75f ;
7071
@@ -163,6 +164,10 @@ public void onEdgePathCreated(ShapePath edgePath, Matrix transform, int count) {
163164 edgeShadowOperation [count ] = edgePath .createShadowCompatOperation (transform );
164165 }
165166 };
167+
168+ // Listens for modifications made in the ShapeAppearanceModel, and requests a redraw if the
169+ // ShapeAppearanceModel has changed.
170+ drawableState .shapeAppearanceModel .addOnChangedListener (this );
166171 }
167172
168173 @ Nullable
@@ -190,8 +195,10 @@ private static int modulateAlpha(int paintAlpha, int alpha) {
190195 *
191196 * @param shapeAppearanceModel the desired model.
192197 */
193- public void setShapeAppearanceModel (ShapeAppearanceModel shapeAppearanceModel ) {
198+ public void setShapeAppearanceModel (@ NonNull ShapeAppearanceModel shapeAppearanceModel ) {
199+ drawableState .shapeAppearanceModel .removeOnChangedListener (this );
194200 drawableState .shapeAppearanceModel = shapeAppearanceModel ;
201+ shapeAppearanceModel .addOnChangedListener (this );
195202 invalidateSelf ();
196203 }
197204
@@ -201,6 +208,7 @@ public void setShapeAppearanceModel(ShapeAppearanceModel shapeAppearanceModel) {
201208 *
202209 * @return the current model.
203210 */
211+ @ NonNull
204212 public ShapeAppearanceModel getShapeAppearanceModel () {
205213 return drawableState .shapeAppearanceModel ;
206214 }
@@ -524,6 +532,7 @@ public float getInterpolation() {
524532 public void setInterpolation (float interpolation ) {
525533 if (drawableState .interpolation != interpolation ) {
526534 drawableState .interpolation = interpolation ;
535+ pathDirty = true ;
527536 invalidateSelf ();
528537 }
529538 }
@@ -573,6 +582,30 @@ public void setShadowElevation(int shadowElevation) {
573582 setElevation (shadowElevation );
574583 }
575584
585+ /**
586+ * Returns the shadow vertical offset rendered for shadows when {@link #requiresCompatShadow()} is
587+ * true.
588+ */
589+ @ RestrictTo (LIBRARY_GROUP )
590+ public int getShadowVerticalOffset () {
591+ return drawableState .shadowCompatOffset ;
592+ }
593+
594+ /**
595+ * Sets the shadow offset rendered by the fake shadow when {@link #requiresCompatShadow()} is
596+ * true. This can make the shadow appear more on the bottom or top of the view to make a more
597+ * realistic looking shadow depending on the placement of the view on the screen. Normally, if the
598+ * View is positioned further down on the screen, less shadow appears above the View, and more
599+ * shadow appears below it.
600+ */
601+ @ RestrictTo (LIBRARY_GROUP )
602+ public void setShadowVerticalOffset (int shadowOffset ) {
603+ if (drawableState .shadowCompatOffset != shadowOffset ) {
604+ drawableState .shadowCompatOffset = shadowOffset ;
605+ invalidateSelfIgnoreShape ();
606+ }
607+ }
608+
576609 /**
577610 * Returns the rotation offset applied to the fake shadow which is drawn when {@link
578611 * #requiresCompatShadow()} is true.
@@ -648,10 +681,15 @@ public void setScale(float scale) {
648681 }
649682 }
650683
684+ @ Override
685+ public void onShapeAppearanceModelChanged () {
686+ invalidateSelf ();
687+ }
688+
651689 @ Override
652690 public void invalidateSelf () {
653691 pathDirty = true ;
654- invalidateSelfIgnoreShape ();
692+ super . invalidateSelf ();
655693 }
656694
657695 /**
@@ -1128,7 +1166,7 @@ public MaterialShapeDrawableState(
11281166 }
11291167
11301168 public MaterialShapeDrawableState (MaterialShapeDrawableState orig ) {
1131- shapeAppearanceModel = new ShapeAppearanceModel ( orig .shapeAppearanceModel ) ;
1169+ shapeAppearanceModel = orig .shapeAppearanceModel ;
11321170 elevationOverlayProvider = orig .elevationOverlayProvider ;
11331171 strokeWidth = orig .strokeWidth ;
11341172 colorFilter = orig .colorFilter ;
0 commit comments