Skip to content

Commit 163c0ed

Browse files
gsajithwcshi
authored andcommitted
Update ExtendedFAB to support setting corner radius via shape appearance
PiperOrigin-RevId: 243677036
1 parent ed4260f commit 163c0ed

4 files changed

Lines changed: 52 additions & 34 deletions

File tree

lib/java/com/google/android/material/floatingactionbutton/ExtendedFloatingActionButton.java

Lines changed: 41 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import com.google.android.material.button.MaterialButton;
3838
import com.google.android.material.internal.DescendantOffsetUtils;
3939
import com.google.android.material.internal.ThemeEnforcement;
40+
import com.google.android.material.shape.ShapeAppearanceModel;
4041
import androidx.coordinatorlayout.widget.CoordinatorLayout;
4142
import androidx.coordinatorlayout.widget.CoordinatorLayout.AttachedBehavior;
4243
import androidx.coordinatorlayout.widget.CoordinatorLayout.Behavior;
@@ -70,6 +71,9 @@
7071
*/
7172
public class ExtendedFloatingActionButton extends MaterialButton implements AttachedBehavior {
7273

74+
private static final int DEF_STYLE_RES =
75+
R.style.Widget_MaterialComponents_ExtendedFloatingActionButton_Icon;
76+
7377
private static final int ANIM_STATE_NONE = 0;
7478
private static final int ANIM_STATE_HIDING = 1;
7579
private static final int ANIM_STATE_SHOWING = 2;
@@ -96,6 +100,7 @@ public class ExtendedFloatingActionButton extends MaterialButton implements Atta
96100
@Nullable private ArrayList<AnimatorListener> extendListeners;
97101

98102
private boolean isExtended = true;
103+
private boolean isUsingPillCorner = true;
99104

100105
/**
101106
* Callback to be invoked when the visibility or the state of an ExtendedFloatingActionButton
@@ -147,20 +152,14 @@ public ExtendedFloatingActionButton(Context context, @Nullable AttributeSet attr
147152

148153
@SuppressWarnings("initialization")
149154
public ExtendedFloatingActionButton(
150-
Context context,
151-
@Nullable AttributeSet attrs,
152-
int defStyleAttr) {
155+
Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
153156
super(context, attrs, defStyleAttr);
154157
behavior = new ExtendedFloatingActionButtonBehavior<>(context, attrs);
155158
userSetVisibility = getVisibility();
156159

157160
TypedArray a =
158161
ThemeEnforcement.obtainStyledAttributes(
159-
context,
160-
attrs,
161-
R.styleable.ExtendedFloatingActionButton,
162-
defStyleAttr,
163-
R.style.Widget_MaterialComponents_ExtendedFloatingActionButton_Icon);
162+
context, attrs, R.styleable.ExtendedFloatingActionButton, defStyleAttr, DEF_STYLE_RES);
164163

165164
showMotionSpec =
166165
MotionSpec.createFromAttribute(
@@ -176,6 +175,11 @@ public ExtendedFloatingActionButton(
176175
context, a, R.styleable.ExtendedFloatingActionButton_shrinkMotionSpec);
177176

178177
a.recycle();
178+
179+
ShapeAppearanceModel shapeAppearanceModel =
180+
new ShapeAppearanceModel(
181+
context, attrs, defStyleAttr, DEF_STYLE_RES, ShapeAppearanceModel.PILL);
182+
setShapeAppearanceModel(shapeAppearanceModel);
179183
}
180184

181185
@Override
@@ -191,9 +195,10 @@ protected void onAttachedToWindow() {
191195
@Override
192196
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
193197
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
194-
// TODO: This must be removed if we want cornerRadius values to be controlled by MotionSpec
195-
// Override any corner radius set by the user
196-
setCornerRadius(getAdjustedRadius(getMeasuredHeight()));
198+
199+
if (isUsingPillCorner) {
200+
getShapeAppearanceModel().setCornerRadius(getAdjustedRadius(getMeasuredHeight()));
201+
}
197202
}
198203

199204
@NonNull
@@ -202,6 +207,23 @@ public Behavior<ExtendedFloatingActionButton> getBehavior() {
202207
return behavior;
203208
}
204209

210+
@Override
211+
public void setShapeAppearanceModel(@NonNull ShapeAppearanceModel shapeAppearanceModel) {
212+
isUsingPillCorner = shapeAppearanceModel.isUsingPillCorner();
213+
super.setShapeAppearanceModel(shapeAppearanceModel);
214+
}
215+
216+
@Override
217+
public void setCornerRadius(int cornerRadius) {
218+
isUsingPillCorner = cornerRadius == ShapeAppearanceModel.PILL;
219+
if (isUsingPillCorner) {
220+
cornerRadius = getAdjustedRadius(getMeasuredHeight());
221+
} else if (cornerRadius < 0) {
222+
cornerRadius = 0;
223+
}
224+
super.setCornerRadius(cornerRadius);
225+
}
226+
205227
@Override
206228
public void setVisibility(int visibility) {
207229
internalSetVisibility(visibility, true);
@@ -721,7 +743,7 @@ private AnimatorSet createAnimator(@NonNull MotionSpec spec) {
721743
animators.add(spec.getAnimator("height", this, HEIGHT));
722744
}
723745

724-
if (spec.hasPropertyValues("cornerRadius")) {
746+
if (spec.hasPropertyValues("cornerRadius") && !isUsingPillCorner) {
725747
animators.add(spec.getAnimator("cornerRadius", this, CORNER_RADIUS));
726748
}
727749

@@ -757,16 +779,6 @@ private AnimatorSet createShrinkExtendAnimator(@NonNull MotionSpec spec, boolean
757779
spec.setPropertyValues("height", heightValues);
758780
}
759781

760-
if (spec.hasPropertyValues("cornerRadius")) {
761-
PropertyValuesHolder[] cornerRadiusValues = spec.getPropertyValues("cornerRadius");
762-
if (shrinking) {
763-
cornerRadiusValues[0].setFloatValues(getCornerRadius(), getAdjustedRadius(collapsedSize));
764-
} else {
765-
cornerRadiusValues[0].setFloatValues(getCornerRadius(), getAdjustedRadius(getHeight()));
766-
}
767-
spec.setPropertyValues("cornerRadius", cornerRadiusValues);
768-
}
769-
770782
return createAnimator(spec);
771783
}
772784

@@ -915,12 +927,17 @@ public Float get(View object) {
915927
new Property<View, Float>(Float.class, "cornerRadius") {
916928
@Override
917929
public void set(View object, Float value) {
918-
((ExtendedFloatingActionButton) object).setCornerRadius(value.intValue());
930+
((ExtendedFloatingActionButton) object)
931+
.getShapeAppearanceModel()
932+
.setCornerRadius(value.intValue());
919933
}
920934

921935
@Override
922936
public Float get(View object) {
923-
return (float) ((ExtendedFloatingActionButton) object).getCornerRadius();
937+
return ((ExtendedFloatingActionButton) object)
938+
.getShapeAppearanceModel()
939+
.getTopRightCorner()
940+
.getCornerSize();
924941
}
925942
};
926943

lib/java/com/google/android/material/floatingactionbutton/res/animator/mtrl_extended_fab_extend_motion_spec.xml

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,4 @@
2626
android:startOffset="0"
2727
android:duration="200"
2828
android:interpolator="@interpolator/mtrl_fast_out_slow_in"/>
29-
<objectAnimator
30-
android:propertyName="cornerRadius"
31-
android:startOffset="0"
32-
android:duration="200"
33-
android:interpolator="@interpolator/mtrl_fast_out_slow_in"/>
3429
</set>

lib/java/com/google/android/material/floatingactionbutton/res/animator/mtrl_extended_fab_shrink_motion_spec.xml

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,4 @@
2626
android:startOffset="0"
2727
android:duration="200"
2828
android:interpolator="@interpolator/mtrl_fast_out_slow_in"/>
29-
<objectAnimator
30-
android:propertyName="cornerRadius"
31-
android:startOffset="0"
32-
android:duration="200"
33-
android:interpolator="@interpolator/mtrl_fast_out_slow_in"/>
3429
</set>

lib/java/com/google/android/material/shape/ShapeAppearanceModel.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,9 @@ public interface OnChangedListener {
5353
void onShapeAppearanceModelChanged();
5454
}
5555

56+
// Constant corner radius value to indicate that shape should use 50% height corner radii
57+
public static final int PILL = -1;
58+
5659
private CornerTreatment topLeftCorner;
5760
private CornerTreatment topRightCorner;
5861
private CornerTreatment bottomRightCorner;
@@ -599,6 +602,14 @@ void removeOnChangedListener(@Nullable OnChangedListener onChangedListener) {
599602
onChangedListeners.remove(onChangedListener);
600603
}
601604

605+
/** Checks if all four corners of this ShapeAppearanceModel are of size {@link #PILL}. */
606+
public boolean isUsingPillCorner() {
607+
return getTopRightCorner().getCornerSize() == PILL
608+
&& getTopLeftCorner().getCornerSize() == PILL
609+
&& getBottomLeftCorner().getCornerSize() == PILL
610+
&& getBottomRightCorner().getCornerSize() == PILL;
611+
}
612+
602613
private void onShapeAppearanceModelChanged() {
603614
for (OnChangedListener onChangedListener : onChangedListeners) {
604615
if (onChangedListener != null) {

0 commit comments

Comments
 (0)