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

Commit 23c89fd1 authored by Fabrice Di Meglio's avatar Fabrice Di Meglio
Browse files

Improve resolution of RTL related properties

- fix bug #6887370 ListPreference shows misaligned radio drawables (in CheckedTextView?)
- fix bug #6938146 "Show more cards..." text on bottom button is not centered

- also defer scrollbar initialization as we need resolved padding values for them

Change-Id: Ife651ffe6bbcc228ff6724f3d9b91079fac3a740
parent 38cc2a5a
Loading
Loading
Loading
Loading
+143 −65
Original line number Diff line number Diff line
@@ -2789,6 +2789,20 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
    @ViewDebug.ExportedProperty(category = "padding")
    int mUserPaddingEnd;
    /**
     * Whether a left padding has been defined during layout inflation.
     *
     * @hide
     */
    boolean mUserPaddingLeftDefined = false;
    /**
     * Whether a right padding has been defined during layout inflation.
     *
     * @hide
     */
    boolean mUserPaddingRightDefined = false;
    /**
     * Default undefined padding
     */
@@ -3195,8 +3209,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
        boolean transformSet = false;
        int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY;
        int overScrollMode = mOverScrollMode;
        boolean initializeScrollbars = false;
        final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
        final int N = a.getIndexCount();
        for (int i = 0; i < N; i++) {
            int attr = a.getIndex(i);
@@ -3206,15 +3223,19 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
                    break;
                case com.android.internal.R.styleable.View_padding:
                    padding = a.getDimensionPixelSize(attr, -1);
                    mUserPaddingLeftDefined = true;
                    mUserPaddingRightDefined = true;
                    break;
                 case com.android.internal.R.styleable.View_paddingLeft:
                    leftPadding = a.getDimensionPixelSize(attr, -1);
                    mUserPaddingLeftDefined = true;
                    break;
                case com.android.internal.R.styleable.View_paddingTop:
                    topPadding = a.getDimensionPixelSize(attr, -1);
                    break;
                case com.android.internal.R.styleable.View_paddingRight:
                    rightPadding = a.getDimensionPixelSize(attr, -1);
                    mUserPaddingRightDefined = true;
                    break;
                case com.android.internal.R.styleable.View_paddingBottom:
                    bottomPadding = a.getDimensionPixelSize(attr, -1);
@@ -3359,12 +3380,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
                    if (scrollbars != SCROLLBARS_NONE) {
                        viewFlagValues |= scrollbars;
                        viewFlagMasks |= SCROLLBARS_MASK;
                        initializeScrollbars(a);
                        initializeScrollbars = true;
                    }
                    break;
                //noinspection deprecation
                case R.styleable.View_fadingEdge:
                    if (context.getApplicationInfo().targetSdkVersion >= ICE_CREAM_SANDWICH) {
                    if (targetSdkVersion >= ICE_CREAM_SANDWICH) {
                        // Ignore the attribute starting with ICS
                        break;
                    }
@@ -3496,12 +3517,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
            }
        }
        a.recycle();
        setOverScrollMode(overScrollMode);
        // Cache user padding as we cannot fully resolve padding here (we dont have yet the resolved
        // layout direction). Those cached values will be used later during padding resolution.
        // Cache start/end user padding as we cannot fully resolve padding here (we dont have yet
        // the resolved layout direction). Those cached values will be used later during padding
        // resolution.
        mUserPaddingStart = startPadding;
        mUserPaddingEnd = endPadding;
@@ -3529,6 +3549,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
            setFlags(viewFlagValues, viewFlagMasks);
        }
        if (initializeScrollbars) {
            initializeScrollbars(a);
        }
        a.recycle();
        // Needs to be called after mViewFlags is set
        if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
            recomputePadding();
@@ -5533,10 +5559,13 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
            // Reset the current layout direction and the resolved one
            mPrivateFlags2 &= ~LAYOUT_DIRECTION_MASK;
            resetResolvedLayoutDirection();
            // Set the new layout direction (filtered) and ask for a layout pass
            // Reset padding resolution
            mPrivateFlags2 &= ~PADDING_RESOLVED;
            // Set the new layout direction (filtered)
            mPrivateFlags2 |=
                    ((layoutDirection << LAYOUT_DIRECTION_MASK_SHIFT) & LAYOUT_DIRECTION_MASK);
            resolvePadding();
            resolveRtlProperties();
            // ... and ask for a layout pass
            requestLayout();
        }
    }
@@ -5552,6 +5581,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL, to = "RESOLVED_DIRECTION_RTL")
    })
    public int getResolvedLayoutDirection() {
        final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
        if (targetSdkVersion < JELLY_BEAN_MR1) {
            mPrivateFlags2 |= LAYOUT_DIRECTION_RESOLVED;
            return LAYOUT_DIRECTION_LTR;
        }
        // The layout direction will be resolved only if needed
        if ((mPrivateFlags2 & LAYOUT_DIRECTION_RESOLVED) != LAYOUT_DIRECTION_RESOLVED) {
            resolveLayoutDirection();
@@ -9657,12 +9691,22 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
            throw new NullPointerException("Layout parameters cannot be null");
        }
        mLayoutParams = params;
        resolveLayoutParams();
        if (mParent instanceof ViewGroup) {
            ((ViewGroup) mParent).onSetLayoutParams(this, params);
        }
        requestLayout();
    }
    /**
     * Resolve the layout parameters depending on the resolved layout direction
     */
    private void resolveLayoutParams() {
        if (mLayoutParams != null) {
            mLayoutParams.onResolveLayoutDirection(getResolvedLayoutDirection());
        }
    }
    /**
     * Set the scrolled position of your view. This will cause a call to
     * {@link #onScrollChanged(int, int, int, int)} and the view will be
@@ -11197,12 +11241,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
        jumpDrawablesToCurrentState();
        // Order is important here: LayoutDirection MUST be resolved before Padding
        // and TextDirection
        resolveLayoutDirection();
        resolvePadding();
        resolveTextDirection();
        resolveTextAlignment();
        resolveRtlProperties();
        clearAccessibilityFocus();
        if (isFocused()) {
@@ -11215,6 +11254,16 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
        }
    }
    void resolveRtlProperties() {
        // Order is important here: LayoutDirection MUST be resolved first...
        resolveLayoutDirection();
        // ... then we can resolve the others properties depending on the resolved LayoutDirection.
        resolvePadding();
        resolveLayoutParams();
        resolveTextDirection();
        resolveTextAlignment();
    }
    /**
     * @see #onScreenStateChanged(int)
     */
@@ -11294,56 +11343,66 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
    public void onResolvedLayoutDirectionChanged() {
    }
    /**
     * Return if padding has been resolved
     */
    boolean isPaddingResolved() {
        return (mPrivateFlags2 & PADDING_RESOLVED) != 0;
    }
    /**
     * Resolve padding depending on layout direction.
     */
    public void resolvePadding() {
        // If the user specified the absolute padding (either with android:padding or
        // android:paddingLeft/Top/Right/Bottom), use this padding, otherwise
        // use the default padding or the padding from the background drawable
        // (stored at this point in mPadding*)
        final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
        if (targetSdkVersion < JELLY_BEAN_MR1 || !hasRtlSupport()) {
            // Pre Jelly Bean MR1 case (compatibility mode) OR no RTL support case:
            // left / right padding are used if defined. If they are not defined and start / end
            // padding are defined (e.g. in Frameworks resources), then we use start / end and
            // resolve them as left / right (layout direction is not taken into account).
            if (!mUserPaddingLeftDefined && mUserPaddingStart != UNDEFINED_PADDING) {
                mUserPaddingLeft = mUserPaddingStart;
            }
            if (!mUserPaddingRightDefined && mUserPaddingEnd != UNDEFINED_PADDING) {
                mUserPaddingRight = mUserPaddingEnd;
            }
            mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom;
            internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight,
                    mUserPaddingBottom);
        } else {
            // Post Jelly Bean MR1 case: we need to take the resolved layout direction into account.
            // If start / end padding are defined, they will be resolved (hence overriding) to
            // left / right or right / left depending on the resolved layout direction.
            // If start / end padding are not defined, use the left / right ones.
            int resolvedLayoutDirection = getResolvedLayoutDirection();
            switch (resolvedLayoutDirection) {
                case LAYOUT_DIRECTION_RTL:
                // Start user padding override Right user padding. Otherwise, if Right user
                // padding is not defined, use the default Right padding. If Right user padding
                // is defined, just use it.
                    if (mUserPaddingStart != UNDEFINED_PADDING) {
                        mUserPaddingRight = mUserPaddingStart;
                    }
                if (mUserPaddingRight == UNDEFINED_PADDING) {
                    mUserPaddingRight = mPaddingRight;
                }
                    if (mUserPaddingEnd != UNDEFINED_PADDING) {
                        mUserPaddingLeft = mUserPaddingEnd;
                    }
                if (mUserPaddingLeft == UNDEFINED_PADDING) {
                    mUserPaddingLeft = mPaddingLeft;
                }
                    break;
                case LAYOUT_DIRECTION_LTR:
                default:
                // Start user padding override Left user padding. Otherwise, if Left user
                // padding is not defined, use the default left padding. If Left user padding
                // is defined, just use it.
                    if (mUserPaddingStart != UNDEFINED_PADDING) {
                        mUserPaddingLeft = mUserPaddingStart;
                    }
                if (mUserPaddingLeft == UNDEFINED_PADDING) {
                    mUserPaddingLeft = mPaddingLeft;
                }
                    if (mUserPaddingEnd != UNDEFINED_PADDING) {
                        mUserPaddingRight = mUserPaddingEnd;
                    }
                if (mUserPaddingRight == UNDEFINED_PADDING) {
                    mUserPaddingRight = mPaddingRight;
                }
            }
            mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom;
        internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
            internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight,
                    mUserPaddingBottom);
            onPaddingChanged(resolvedLayoutDirection);
        }
        mPrivateFlags2 |= PADDING_RESOLVED;
    }
@@ -14016,6 +14075,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
            }
            background.setLayoutDirection(getResolvedLayoutDirection());
            if (background.getPadding(padding)) {
                // Reset padding resolution
                mPrivateFlags2 &= ~PADDING_RESOLVED;
                switch (background.getLayoutDirection()) {
                    case LAYOUT_DIRECTION_RTL:
                        internalSetPadding(padding.right, padding.top, padding.left, padding.bottom);
@@ -14112,13 +14173,19 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
     * @param bottom the bottom padding in pixels
     */
    public void setPadding(int left, int top, int right, int bottom) {
        // Reset padding resolution
        mPrivateFlags2 &= ~PADDING_RESOLVED;
        mUserPaddingStart = UNDEFINED_PADDING;
        mUserPaddingEnd = UNDEFINED_PADDING;
        internalSetPadding(left, top, right, bottom);
    }
    void internalSetPadding(int left, int top, int right, int bottom) {
    /**
     * @hide
     */
    protected void internalSetPadding(int left, int top, int right, int bottom) {
        mUserPaddingLeft = left;
        mUserPaddingRight = right;
        mUserPaddingBottom = bottom;
@@ -14193,6 +14260,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
     * @param bottom the bottom padding in pixels
     */
    public void setPaddingRelative(int start, int top, int end, int bottom) {
        // Reset padding resolution
        mPrivateFlags2 &= ~PADDING_RESOLVED;
        mUserPaddingStart = start;
        mUserPaddingEnd = end;
@@ -14234,6 +14304,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
     * @return the left padding in pixels
     */
    public int getPaddingLeft() {
        if (!isPaddingResolved()) {
            resolvePadding();
        }
        return mPaddingLeft;
    }
@@ -14245,6 +14318,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
     * @return the start padding in pixels
     */
    public int getPaddingStart() {
        if (!isPaddingResolved()) {
            resolvePadding();
        }
        return (getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
                mPaddingRight : mPaddingLeft;
    }
@@ -14257,6 +14333,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
     * @return the right padding in pixels
     */
    public int getPaddingRight() {
        if (!isPaddingResolved()) {
            resolvePadding();
        }
        return mPaddingRight;
    }
@@ -14268,6 +14347,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
     * @return the end padding in pixels
     */
    public int getPaddingEnd() {
        if (!isPaddingResolved()) {
            resolvePadding();
        }
        return (getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
                mPaddingLeft : mPaddingRight;
    }
@@ -14913,10 +14995,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
        mPrivateFlags |= FORCE_LAYOUT;
        mPrivateFlags |= INVALIDATED;
        if (mLayoutParams != null) {
            mLayoutParams.onResolveLayoutDirection(getResolvedLayoutDirection());
        }
        if (mParent != null && !mParent.isLayoutRequested()) {
            mParent.requestLayout();
        }
@@ -14960,7 +15038,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
            // first clears the measured dimension flag
            mPrivateFlags &= ~MEASURED_DIMENSION_SET;
            if ((mPrivateFlags2 & PADDING_RESOLVED) == 0) {
            if (!isPaddingResolved()) {
                resolvePadding();
            }
+11 −1
Original line number Diff line number Diff line
@@ -2517,8 +2517,11 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
        super.dispatchDetachedFromWindow();
    }

    /**
     * @hide
     */
    @Override
    void internalSetPadding(int left, int top, int right, int bottom) {
    protected void internalSetPadding(int left, int top, int right, int bottom) {
        super.internalSetPadding(left, top, right, bottom);

        if ((mPaddingLeft | mPaddingTop | mPaddingRight | mPaddingBottom) != 0) {
@@ -3372,6 +3375,11 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
        if (child.hasTransientState()) {
            childHasTransientStateChanged(child, true);
        }

        if (child.getLayoutDirection() == View.LAYOUT_DIRECTION_INHERIT) {
            child.resetResolvedLayoutDirection();
            child.resolveRtlProperties();
        }
    }

    private void addInArray(View child, int index) {
@@ -3597,6 +3605,8 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
            childHasTransientStateChanged(view, false);
        }

        view.resetResolvedLayoutDirection();

        onViewRemoved(view);

        needGlobalAttributesUpdate(false);
+23 −3
Original line number Diff line number Diff line
@@ -151,7 +151,7 @@ public class CheckedTextView extends TextView implements Checkable {
            mCheckMarkWidth = 0;
        }
        mCheckMarkDrawable = d;
        // Do padding resolution. This will call setPadding() and do a requestLayout() if needed.
        // Do padding resolution. This will call internalSetPadding() and do a requestLayout() if needed.
        resolvePadding();
    }

@@ -169,6 +169,19 @@ public class CheckedTextView extends TextView implements Checkable {
        return mCheckMarkDrawable;
    }

    /**
     * @hide
     */
    @Override
    protected void internalSetPadding(int left, int top, int right, int bottom) {
        super.internalSetPadding(left, top, right, bottom);
        if (isLayoutRtl()) {
            mBasePadding = mUserPaddingLeft;
        } else {
            mBasePadding = mUserPaddingRight;
        }
    }

    @Override
    public void onPaddingChanged(int layoutDirection) {
        int newPadding = (mCheckMarkDrawable != null) ?
@@ -221,8 +234,15 @@ public class CheckedTextView extends TextView implements Checkable {
            final int width = getWidth();
            final int top = y;
            final int bottom = top + height;
            final int left = isLayoutRtl ? getPaddingEnd() : width - getPaddingEnd();
            final int right = left + mCheckMarkWidth;
            final int left;
            final int right;
            if (isLayoutRtl) {
                right = getPaddingEnd();
                left = right - mCheckMarkWidth;
            } else {
                left = width - getPaddingEnd();
                right = left + mCheckMarkWidth;
            }
            checkMarkDrawable.setBounds( left, top, right, bottom);
            checkMarkDrawable.draw(canvas);
        }