Skip to content

Commit 359580b

Browse files
hunterstichpaulfthomas
authored andcommittedMar 8, 2023
[Carousel] Changed Maskable.add/removeOnMaskChangedListener to Maskable.setOnMaskChangedListener.
This change is to prevent the case of items in a RecyclerView.Adapter being recycled and re-bound and having more and more listeners added to a MaskableFrameLayout. PiperOrigin-RevId: 515048125
1 parent c22eb0d commit 359580b

File tree

4 files changed

+16
-22
lines changed

4 files changed

+16
-22
lines changed
 

‎docs/components/Carousel.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ The main means of changing the look of carousel is by setting the height of your
8888
If your `RecyclerView`'s item layout contains text or other content that needs to react to changes in the item's mask, you can listen for changes in mask size by setting an `onMaskChangedListener` on your `MaskableFrameLayout` inside your `RecyclerView.ViewHolder`.
8989

9090
```kotlin
91-
(viewHolder.itemView as MaskableFrameLayout).addOnMaskChangedListener(
91+
(viewHolder.itemView as MaskableFrameLayout).setOnMaskChangedListener(
9292
maskRect ->
9393
// Any custom motion to run when mask size changes
9494
viewHolder.title.setTranslationX(maskRect.left);

‎lib/java/com/google/android/material/carousel/Maskable.java

+9-8
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,9 @@
2020
import android.view.View;
2121
import androidx.annotation.FloatRange;
2222
import androidx.annotation.NonNull;
23+
import androidx.annotation.Nullable;
2324

24-
/**
25-
* Interface for any view that can clip itself and all children to a percentage of its size.
26-
*/
25+
/** Interface for any view that can clip itself and all children to a percentage of its size. */
2726
interface Maskable {
2827

2928
/**
@@ -45,9 +44,11 @@ interface Maskable {
4544
@NonNull
4645
RectF getMaskRectF();
4746

48-
/** Adds an {@link OnMaskChangedListener}. */
49-
void addOnMaskChangedListener(@NonNull OnMaskChangedListener listener);
50-
51-
/** Removes an {@link OnMaskChangedListener}. */
52-
void removeOnMaskChangedListener(@NonNull OnMaskChangedListener listener);
47+
/**
48+
* Sets an {@link OnMaskChangedListener}.
49+
*
50+
* @param listener a listener to receive callbacks for changes in the mask or null to clear the
51+
* listener.
52+
*/
53+
void setOnMaskChangedListener(@Nullable OnMaskChangedListener listener);
5354
}

‎lib/java/com/google/android/material/carousel/MaskableFrameLayout.java

+5-12
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,6 @@
3636
import androidx.core.math.MathUtils;
3737
import com.google.android.material.animation.AnimationUtils;
3838
import com.google.android.material.shape.ShapeAppearanceModel;
39-
import java.util.ArrayList;
40-
import java.util.List;
4139

4240
/** A {@link FrameLayout} than is able to mask itself and all children. */
4341
public class MaskableFrameLayout extends FrameLayout implements Maskable {
@@ -46,7 +44,7 @@ public class MaskableFrameLayout extends FrameLayout implements Maskable {
4644
private final RectF maskRect = new RectF();
4745
private final Path maskPath = new Path();
4846

49-
private final List<OnMaskChangedListener> onMaskChangedListeners = new ArrayList<>();
47+
@Nullable private OnMaskChangedListener onMaskChangedListener;
5048

5149
private final ShapeAppearanceModel shapeAppearanceModel;
5250

@@ -105,13 +103,8 @@ public RectF getMaskRectF() {
105103
}
106104

107105
@Override
108-
public void addOnMaskChangedListener(@NonNull OnMaskChangedListener listener) {
109-
onMaskChangedListeners.add(listener);
110-
}
111-
112-
@Override
113-
public void removeOnMaskChangedListener(@NonNull OnMaskChangedListener listener) {
114-
onMaskChangedListeners.remove(listener);
106+
public void setOnMaskChangedListener(@Nullable OnMaskChangedListener onMaskChangedListener) {
107+
this.onMaskChangedListener = onMaskChangedListener;
115108
}
116109

117110
private void onMaskChanged() {
@@ -122,8 +115,8 @@ private void onMaskChanged() {
122115
// masked away.
123116
float maskWidth = AnimationUtils.lerp(0f, getWidth() / 2F, 0f, 1f, maskXPercentage);
124117
maskRect.set(maskWidth, 0F, (getWidth() - maskWidth), getHeight());
125-
for (OnMaskChangedListener listener : onMaskChangedListeners) {
126-
listener.onMaskChanged(maskRect);
118+
if (onMaskChangedListener != null) {
119+
onMaskChangedListener.onMaskChanged(maskRect);
127120
}
128121
refreshMaskPath();
129122
}

‎lib/javatests/com/google/android/material/carousel/MaskableFrameLayoutTest.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ public class MaskableFrameLayoutTest {
4343
@Test
4444
public void testSetMaskXPercentage_shouldTriggerMaskChangedListeners() {
4545
MaskableFrameLayout maskableFrameLayout = createMaskableFrameLayoutWithSize(100, 100);
46-
maskableFrameLayout.addOnMaskChangedListener(listener);
46+
maskableFrameLayout.setOnMaskChangedListener(listener);
4747

4848
maskableFrameLayout.setMaskXPercentage(.5F);
4949

0 commit comments

Comments
 (0)
Please sign in to comment.