2323import static com .google .android .material .listitem .SwipeableListItem .STATE_SETTLING ;
2424import static com .google .android .material .listitem .SwipeableListItem .STATE_SWIPE_PRIMARY_ACTION ;
2525import static com .google .android .material .theme .overlay .MaterialThemeOverlay .wrap ;
26+ import static java .lang .Math .abs ;
2627import static java .lang .Math .max ;
27- import static java .lang .Math .min ;
2828
2929import android .animation .TimeInterpolator ;
3030import 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