Fixed divider rendering in RTL languages
In horizontal layouts, when elements are rendered from LTR, the definition of "before" and "after" gets flipped, causing the divider spacing to be allocated to the wrong locations. By flipping the check in RTL layouts, the dividers can be placed correctly. Additionally, it is necessary to add divider measurements to all layout width measurements to allow for dividers in right gravity to layout properly. Bug: 208927871 Test: atest android.widget.cts.LinearLayoutTest Change-Id: If6e917873571484a6fb1dfc28b356289e2cc1ffa
This commit is contained in:
@@ -732,6 +732,10 @@ public class LinearLayout extends ViewGroup {
|
||||
* @hide Pending API consideration. Currently only used internally by the system.
|
||||
*/
|
||||
protected boolean hasDividerBeforeChildAt(int childIndex) {
|
||||
if (mShowDividers == SHOW_DIVIDER_NONE) {
|
||||
// Short-circuit to save iteration over child views.
|
||||
return false;
|
||||
}
|
||||
if (childIndex == getVirtualChildCount()) {
|
||||
// Check whether the end divider should draw.
|
||||
return (mShowDividers & SHOW_DIVIDER_END) != 0;
|
||||
@@ -745,6 +749,24 @@ public class LinearLayout extends ViewGroup {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether or not there's a divider after a specified child index.
|
||||
*
|
||||
* @param childIndex Index of child to check for following divider
|
||||
* @return true if there should be a divider after the child at childIndex
|
||||
*/
|
||||
private boolean hasDividerAfterChildAt(int childIndex) {
|
||||
if (mShowDividers == SHOW_DIVIDER_NONE) {
|
||||
// Short-circuit to save iteration over child views.
|
||||
return false;
|
||||
}
|
||||
if (allViewsAreGoneAfter(childIndex)) {
|
||||
// This is the last view that's not gone, check if end divider is enabled.
|
||||
return (mShowDividers & SHOW_DIVIDER_END) != 0;
|
||||
}
|
||||
return (mShowDividers & SHOW_DIVIDER_MIDDLE) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether all (virtual) child views before the given index are gone.
|
||||
*/
|
||||
@@ -758,6 +780,20 @@ public class LinearLayout extends ViewGroup {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether all (virtual) child views after the given index are gone.
|
||||
*/
|
||||
private boolean allViewsAreGoneAfter(int childIndex) {
|
||||
final int count = getVirtualChildCount();
|
||||
for (int i = childIndex + 1; i < count; i++) {
|
||||
final View child = getVirtualChildAt(i);
|
||||
if (child != null && child.getVisibility() != GONE) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Measures the children when the orientation of this LinearLayout is set
|
||||
* to {@link #VERTICAL}.
|
||||
@@ -1295,6 +1331,7 @@ public class LinearLayout extends ViewGroup {
|
||||
if (useLargestChild &&
|
||||
(widthMode == MeasureSpec.AT_MOST || widthMode == MeasureSpec.UNSPECIFIED)) {
|
||||
mTotalLength = 0;
|
||||
nonSkippedChildCount = 0;
|
||||
|
||||
for (int i = 0; i < count; ++i) {
|
||||
final View child = getVirtualChildAt(i);
|
||||
@@ -1308,6 +1345,11 @@ public class LinearLayout extends ViewGroup {
|
||||
continue;
|
||||
}
|
||||
|
||||
nonSkippedChildCount++;
|
||||
if (hasDividerBeforeChildAt(i)) {
|
||||
mTotalLength += mDividerWidth;
|
||||
}
|
||||
|
||||
final LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)
|
||||
child.getLayoutParams();
|
||||
if (isExactly) {
|
||||
@@ -1319,6 +1361,10 @@ public class LinearLayout extends ViewGroup {
|
||||
lp.leftMargin + lp.rightMargin + getNextLocationOffset(child));
|
||||
}
|
||||
}
|
||||
|
||||
if (nonSkippedChildCount > 0 && hasDividerBeforeChildAt(count)) {
|
||||
mTotalLength += mDividerWidth;
|
||||
}
|
||||
}
|
||||
|
||||
// Add in our padding
|
||||
@@ -1347,6 +1393,7 @@ public class LinearLayout extends ViewGroup {
|
||||
maxHeight = -1;
|
||||
|
||||
mTotalLength = 0;
|
||||
nonSkippedChildCount = 0;
|
||||
|
||||
for (int i = 0; i < count; ++i) {
|
||||
final View child = getVirtualChildAt(i);
|
||||
@@ -1354,6 +1401,11 @@ public class LinearLayout extends ViewGroup {
|
||||
continue;
|
||||
}
|
||||
|
||||
nonSkippedChildCount++;
|
||||
if (hasDividerBeforeChildAt(i)) {
|
||||
mTotalLength += mDividerWidth;
|
||||
}
|
||||
|
||||
final LayoutParams lp = (LayoutParams) child.getLayoutParams();
|
||||
final float childWeight = lp.weight;
|
||||
if (childWeight > 0) {
|
||||
@@ -1423,6 +1475,10 @@ public class LinearLayout extends ViewGroup {
|
||||
}
|
||||
}
|
||||
|
||||
if (nonSkippedChildCount > 0 && hasDividerBeforeChildAt(count)) {
|
||||
mTotalLength += mDividerWidth;
|
||||
}
|
||||
|
||||
// Add in our padding
|
||||
mTotalLength += mPaddingLeft + mPaddingRight;
|
||||
// TODO: Should we update widthSize with the new total length?
|
||||
@@ -1810,7 +1866,13 @@ public class LinearLayout extends ViewGroup {
|
||||
break;
|
||||
}
|
||||
|
||||
if (hasDividerBeforeChildAt(childIndex)) {
|
||||
if (isLayoutRtl) {
|
||||
// Because rtl rendering occurs in the reverse direction, we need to check
|
||||
// after the child rather than before (since after=left in this context)
|
||||
if (hasDividerAfterChildAt(childIndex)) {
|
||||
childLeft += mDividerWidth;
|
||||
}
|
||||
} else if (hasDividerBeforeChildAt(childIndex)) {
|
||||
childLeft += mDividerWidth;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user