Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0ee3b273 authored by Alex Stetson's avatar Alex Stetson
Browse files

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
parent a745ebf3
Loading
Loading
Loading
Loading
+63 −1
Original line number Diff line number Diff line
@@ -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;
                }