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

Commit 306fe5cc authored by Fabrice Di Meglio's avatar Fabrice Di Meglio
Browse files

Fix bug #8051633 Recent Apps thumbnails in RTL mode (Arabic / Hebrew / Farsi) should be aligned

Basically RelativeLayout was broken in a very stubtle way.

RelativeLayout needs in onMeasure() to have a width in RTL mode when "myWidth=-1" (meaning "not
defined") so that the rest of the onMeasure() computation can be done (children positioning and
width computation).

As there is no way to get its width apart from running the code, in RTL mode we set its width
arbitrary to the screen width for doing the width computation and children positoning.

Then, as a last pass, we will update and fix the children position (no need to do anything with
the computed width because it is correctly computed  already).

Change-Id: I426af3327160e751ef63ed3845aad5bab6dad661
parent b9781fe0
Loading
Loading
Loading
Loading
+39 −30
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@ import android.view.Gravity;
import android.view.View;
import android.view.ViewDebug;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.RemoteViews.RemoteView;
@@ -220,10 +221,13 @@ public class RelativeLayout extends ViewGroup {
    // Some apps came to rely on them. :(
    private boolean mAllowBrokenMeasureSpecs = false;

    private int mDisplayWidth;

    public RelativeLayout(Context context) {
        super(context);
        mAllowBrokenMeasureSpecs = context.getApplicationInfo().targetSdkVersion <=
                Build.VERSION_CODES.JELLY_BEAN_MR1;
        getDisplayWidth();
    }

    public RelativeLayout(Context context, AttributeSet attrs) {
@@ -231,6 +235,7 @@ public class RelativeLayout extends ViewGroup {
        initFromAttributes(context, attrs);
        mAllowBrokenMeasureSpecs = context.getApplicationInfo().targetSdkVersion <=
                Build.VERSION_CODES.JELLY_BEAN_MR1;
        getDisplayWidth();
    }

    public RelativeLayout(Context context, AttributeSet attrs, int defStyle) {
@@ -238,6 +243,7 @@ public class RelativeLayout extends ViewGroup {
        initFromAttributes(context, attrs);
        mAllowBrokenMeasureSpecs = context.getApplicationInfo().targetSdkVersion <=
                Build.VERSION_CODES.JELLY_BEAN_MR1;
        getDisplayWidth();
    }

    private void initFromAttributes(Context context, AttributeSet attrs) {
@@ -247,6 +253,11 @@ public class RelativeLayout extends ViewGroup {
        a.recycle();
    }

    private void getDisplayWidth() {
        WindowManager wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
        mDisplayWidth = wm.getDefaultDisplay().getWidth();
    }

    @Override
    public boolean shouldDelayChildPressedState() {
        return false;
@@ -438,38 +449,19 @@ public class RelativeLayout extends ViewGroup {
        final boolean isWrapContentWidth = widthMode != MeasureSpec.EXACTLY;
        final boolean isWrapContentHeight = heightMode != MeasureSpec.EXACTLY;

        // We need to know our size for doing the correct computation of children positioning in RTL
        // mode but there is no practical way to get it instead of running the code below.
        // So, instead of running the code twice, we just set the width to the "display width"
        // before the computation and then, as a last pass, we will update their real position with
        // an offset equals to "displayWidth - width".
        final int layoutDirection = getLayoutDirection();
        if (isLayoutRtl() && myWidth == -1) {
            myWidth = mDisplayWidth;
        }

        View[] views = mSortedHorizontalChildren;
        int count = views.length;

        // We need to know our size for doing the correct computation of positioning in RTL mode
        if (isLayoutRtl() && (myWidth == -1 || isWrapContentWidth)) {
            int w = getPaddingStart() + getPaddingEnd();
            for (int i = 0; i < count; i++) {
                View child = views[i];
                if (child.getVisibility() != GONE) {
                    LayoutParams params = (LayoutParams) child.getLayoutParams();
                    int[] rules = params.getRules(View.LAYOUT_DIRECTION_LTR);

                    applyHorizontalSizeRules(params, myWidth, rules);
                    measureChildHorizontal(child, params, -1, myHeight);

                    w += child.getMeasuredWidth();
                    w += params.leftMargin + params.rightMargin;
                }
            }
            if (myWidth == -1) {
                // Easy case: "myWidth" was undefined before so use the width we have just computed
                myWidth = w;
            } else {
                // "myWidth" was defined before, so take the min of it and the computed width if it
                // is a non null one
                if (w > 0) {
                    myWidth = Math.min(myWidth, w);
                }
            }
        }

        final int layoutDirection = getLayoutDirection();
        for (int i = 0; i < count; i++) {
            View child = views[i];
            if (child.getVisibility() != GONE) {
@@ -500,8 +492,12 @@ public class RelativeLayout extends ViewGroup {
                }

                if (isWrapContentWidth) {
                    if (isLayoutRtl()) {
                        width = Math.max(width, myWidth - params.mLeft);
                    } else {
                        width = Math.max(width, params.mRight);
                    }
                }

                if (isWrapContentHeight) {
                    height = Math.max(height, params.mBottom);
@@ -628,6 +624,19 @@ public class RelativeLayout extends ViewGroup {
            }
        }

        if (isLayoutRtl()) {
            final int offsetWidth = myWidth - width;
            for (int i = 0; i < count; i++) {
                View child = getChildAt(i);
                if (child.getVisibility() != GONE) {
                    LayoutParams params = (LayoutParams) child.getLayoutParams();
                    params.mLeft -= offsetWidth;
                    params.mRight -= offsetWidth;
                }
            }

        }

        setMeasuredDimension(width, height);
    }