Skip to content

Commit 176e92d

Browse files
imhappidrchen
authored andcommitted
[Lists] Support RTL swiping
PiperOrigin-RevId: 833469324
1 parent 3e5a7fd commit 176e92d

File tree

2 files changed

+68
-37
lines changed

2 files changed

+68
-37
lines changed

catalog/java/io/material/catalog/listitem/res/layout/cat_list_item_segmented_viewholder.xml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959
style="@style/Widget.Material3.TextView.ListItem.SupportingText"
6060
android:layout_height="wrap_content"
6161
android:layout_width="wrap_content"
62+
android:textAlignment="viewStart"
6263
android:text="@string/cat_list_item_supporting_text"/>
6364
</LinearLayout>
6465
<com.google.android.material.radiobutton.MaterialRadioButton
@@ -90,7 +91,7 @@
9091
android:layout_height="match_parent"
9192
android:layout_width="64dp"
9293
android:layout_marginEnd="2dp"
93-
app:icon="@drawable/ic_add_24px"
94+
app:icon="@drawable/ic_star_icon_checkable_24px"
9495
app:iconGravity="textStart" />
9596
</com.google.android.material.listitem.ListItemRevealLayout>
9697
</com.google.android.material.listitem.ListItemLayout>

lib/java/com/google/android/material/listitem/ListItemLayout.java

Lines changed: 66 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@
2323
import static com.google.android.material.listitem.SwipeableListItem.STATE_SETTLING;
2424
import static com.google.android.material.listitem.SwipeableListItem.STATE_SWIPE_PRIMARY_ACTION;
2525
import static com.google.android.material.theme.overlay.MaterialThemeOverlay.wrap;
26+
import static java.lang.Math.abs;
2627
import static java.lang.Math.max;
27-
import static java.lang.Math.min;
2828

2929
import android.animation.TimeInterpolator;
3030
import android.content.Context;
@@ -273,23 +273,34 @@ public int clampViewPositionHorizontal(@NonNull View child, int left, int dx) {
273273
&& swipeToRevealLayout instanceof RevealableListItem)) {
274274
return 0;
275275
}
276-
// TODO:b/443153708 - Support RTL
277-
MarginLayoutParams revealViewLp =
278-
(LayoutParams) swipeToRevealLayout.getLayoutParams();
279-
MarginLayoutParams contentViewLp = (LayoutParams) contentView.getLayoutParams();
280-
int leftPositionClamp =
281-
((SwipeableListItem) contentView).isSwipeToPrimaryActionEnabled()
282-
? originalContentViewLeft
283-
- contentView.getMeasuredWidth()
284-
- contentViewLp.rightMargin
285-
: // left margin is accounted for in originalContentViewLeft
286-
originalContentViewLeft
287-
- ((RevealableListItem) swipeToRevealLayout).getIntrinsicWidth()
288-
- revealViewLp.leftMargin
289-
- revealViewLp.rightMargin;
290-
return max(
291-
min(left, originalContentViewLeft),
292-
leftPositionClamp - ((SwipeableListItem) contentView).getSwipeMaxOvershoot());
276+
boolean isRtl = getLayoutDirection() == LAYOUT_DIRECTION_RTL;
277+
RevealableListItem revealableItem = (RevealableListItem) swipeToRevealLayout;
278+
SwipeableListItem swipeableItem = (SwipeableListItem) contentView;
279+
280+
int maxSwipeDistance;
281+
if (swipeableItem.isSwipeToPrimaryActionEnabled()) {
282+
MarginLayoutParams contentViewLp =
283+
(MarginLayoutParams) contentView.getLayoutParams();
284+
maxSwipeDistance =
285+
contentView.getMeasuredWidth() + contentViewLp.getMarginEnd();
286+
} else {
287+
MarginLayoutParams revealViewLp =
288+
(MarginLayoutParams) swipeToRevealLayout.getLayoutParams();
289+
maxSwipeDistance =
290+
revealableItem.getIntrinsicWidth()
291+
+ revealViewLp.getMarginStart()
292+
+ revealViewLp.getMarginEnd();
293+
}
294+
295+
int maxSwipeBoundary =
296+
originalContentViewLeft
297+
+ ((isRtl ? 1 : -1)
298+
* (maxSwipeDistance + swipeableItem.getSwipeMaxOvershoot()));
299+
300+
final int startBound = isRtl ? originalContentViewLeft : maxSwipeBoundary;
301+
final int endBound = isRtl ? maxSwipeBoundary : originalContentViewLeft;
302+
303+
return Math.max(startBound, Math.min(left, endBound));
293304
}
294305

295306
@Override
@@ -310,7 +321,6 @@ public void onViewPositionChanged(
310321
return;
311322
}
312323
super.onViewPositionChanged(changedView, left, top, dx, dy);
313-
// TODO:b/443153708 - Support RTL
314324
revealViewOffset = left - originalContentViewLeft;
315325

316326
LayoutParams revealViewLp = (LayoutParams) swipeToRevealLayout.getLayoutParams();
@@ -320,19 +330,23 @@ public void onViewPositionChanged(
320330
int revealViewDesiredWidth =
321331
max(
322332
0,
323-
originalContentViewLeft
324-
- contentView.getLeft()
325-
- contentViewLp.rightMargin // only end margin matters here
326-
- revealViewLp.leftMargin
327-
- revealViewLp.rightMargin);
333+
abs(originalContentViewLeft - contentView.getLeft())
334+
- contentViewLp.getMarginEnd() // only end margin matters here
335+
- revealViewLp.getMarginStart()
336+
- revealViewLp.getMarginEnd());
337+
328338
((RevealableListItem) swipeToRevealLayout)
329339
.setRevealedWidth(revealViewDesiredWidth);
330340

341+
boolean isRtl = getLayoutDirection() == LAYOUT_DIRECTION_RTL;
331342
int fullSwipedOffset = getSwipeToActionOffset();
332343
int disappearingOffset =
333344
(fullSwipedOffset + getSwipeRevealViewRevealedOffset()) / 2;
345+
334346
// If we're past the reveal view offset, we should start disappearing.
335-
if (revealViewOffset <= disappearingOffset) {
347+
if (isRtl
348+
? revealViewOffset >= disappearingOffset
349+
: revealViewOffset <= disappearingOffset) {
336350
contentView.setAlpha(
337351
(float) (revealViewOffset - fullSwipedOffset)
338352
/ (disappearingOffset - fullSwipedOffset));
@@ -348,6 +362,9 @@ public void onViewReleased(@NonNull View releasedChild, float xvel, float yvel)
348362
}
349363

350364
private int calculateTargetSwipeState(float xvel, View swipeView) {
365+
if (getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
366+
xvel *= -1;
367+
}
351368
if (!((SwipeableListItem) swipeView).isSwipeToPrimaryActionEnabled()) {
352369
if (xvel > DEFAULT_SIGNIFICANT_VEL_THRESHOLD) { // A fast fling to the right
353370
return STATE_CLOSED;
@@ -422,10 +439,15 @@ private int getSwipeRevealViewRevealedOffset() {
422439
return 0;
423440
}
424441
LayoutParams lp = (LayoutParams) swipeToRevealLayout.getLayoutParams();
442+
int revealViewTotalWidth =
443+
((RevealableListItem) swipeToRevealLayout).getIntrinsicWidth()
444+
+ lp.leftMargin
445+
+ lp.rightMargin;
446+
425447
return originalContentViewLeft
426-
- ((RevealableListItem) swipeToRevealLayout).getIntrinsicWidth()
427-
- lp.leftMargin
428-
- lp.rightMargin;
448+
+ (getLayoutDirection() == LAYOUT_DIRECTION_RTL
449+
? revealViewTotalWidth
450+
: -revealViewTotalWidth);
429451
}
430452

431453
private int getSwipeViewClosedOffset() {
@@ -438,9 +460,8 @@ private int getSwipeToActionOffset() {
438460
}
439461
LayoutParams lp = (LayoutParams) contentView.getLayoutParams();
440462
return originalContentViewLeft
441-
- contentView.getMeasuredWidth()
442-
- lp.leftMargin
443-
- lp.rightMargin;
463+
+ (getLayoutDirection() == LAYOUT_DIRECTION_RTL ? 1 : -1)
464+
* (contentView.getMeasuredWidth() + lp.leftMargin + lp.rightMargin);
444465
}
445466

446467
private int getOffsetForSwipeState(@StableSwipeState int swipeState) {
@@ -512,15 +533,24 @@ protected void onLayout(boolean changed, int left, int top, int right, int botto
512533
originalContentViewLeft = contentView.getLeft();
513534
int originalContentViewRight = contentView.getRight();
514535
contentView.offsetLeftAndRight(revealViewOffset);
515-
// We always lay out swipeToRevealLayout such that the right is aligned to where the original
516-
// content view's right was. Note that if the content view had a right margin, it will
536+
537+
// We always lay out swipeToRevealLayout such that the end is aligned to where the original
538+
// content view's end was. Note that if the content view had an end margin, it will
517539
// effectively be passed onto the reveal view.
518540
LayoutParams lp = (LayoutParams) swipeToRevealLayout.getLayoutParams();
519-
// TODO:b/443153708 - Support RTL
541+
int swipeToRevealLeft;
542+
int swipeToRevealRight;
543+
if (getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
544+
swipeToRevealLeft = originalContentViewLeft + lp.leftMargin;
545+
swipeToRevealRight = swipeToRevealLeft + swipeToRevealLayout.getMeasuredWidth();
546+
} else {
547+
swipeToRevealRight = originalContentViewRight - lp.rightMargin;
548+
swipeToRevealLeft = swipeToRevealRight - swipeToRevealLayout.getMeasuredWidth();
549+
}
520550
swipeToRevealLayout.layout(
521-
originalContentViewRight - lp.rightMargin - swipeToRevealLayout.getMeasuredWidth(),
551+
swipeToRevealLeft,
522552
swipeToRevealLayout.getTop(),
523-
originalContentViewRight - lp.rightMargin,
553+
swipeToRevealRight,
524554
swipeToRevealLayout.getBottom());
525555
}
526556
}

0 commit comments

Comments
 (0)