161254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos/*
261254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos * Copyright (C) 2016 The Android Open Source Project
361254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos *
461254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos * Licensed under the Apache License, Version 2.0 (the "License");
561254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos * you may not use this file except in compliance with the License.
661254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos * You may obtain a copy of the License at
761254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos *
861254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos *      http://www.apache.org/licenses/LICENSE-2.0
961254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos *
1061254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos * Unless required by applicable law or agreed to in writing, software
1161254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos * distributed under the License is distributed on an "AS IS" BASIS,
1261254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1361254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos * See the License for the specific language governing permissions and
1461254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos * limitations under the License
1561254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos */
1661254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos
1761254356d6ce4193e516cf83c627f260431b7ce6Adrian Roospackage com.android.internal.widget;
1861254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos
1961254356d6ce4193e516cf83c627f260431b7ce6Adrian Roosimport android.content.Context;
2006e9e1fe004d668eb205590ff125c10f97285e3bSelim Cinekimport android.graphics.drawable.Drawable;
2161254356d6ce4193e516cf83c627f260431b7ce6Adrian Roosimport android.util.AttributeSet;
2261254356d6ce4193e516cf83c627f260431b7ce6Adrian Roosimport android.util.Pair;
2361254356d6ce4193e516cf83c627f260431b7ce6Adrian Roosimport android.view.Gravity;
2406e9e1fe004d668eb205590ff125c10f97285e3bSelim Cinekimport android.view.RemotableViewMethod;
2561254356d6ce4193e516cf83c627f260431b7ce6Adrian Roosimport android.view.View;
2606e9e1fe004d668eb205590ff125c10f97285e3bSelim Cinekimport android.widget.LinearLayout;
2761254356d6ce4193e516cf83c627f260431b7ce6Adrian Roosimport android.widget.RemoteViews;
2861254356d6ce4193e516cf83c627f260431b7ce6Adrian Roosimport android.widget.TextView;
2961254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos
3061254356d6ce4193e516cf83c627f260431b7ce6Adrian Roosimport java.util.ArrayList;
3161254356d6ce4193e516cf83c627f260431b7ce6Adrian Roosimport java.util.Comparator;
3261254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos
3361254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos/**
3461254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos * Layout for notification actions that ensures that no action consumes more than their share of
3561254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos * the remaining available width, and the last action consumes the remaining space.
3661254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos */
3761254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos@RemoteViews.RemoteView
3806e9e1fe004d668eb205590ff125c10f97285e3bSelim Cinekpublic class NotificationActionListLayout extends LinearLayout {
3961254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos
4061254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos    private int mTotalWidth = 0;
4161254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos    private ArrayList<Pair<Integer, TextView>> mMeasureOrderTextViews = new ArrayList<>();
4261254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos    private ArrayList<View> mMeasureOrderOther = new ArrayList<>();
4306e9e1fe004d668eb205590ff125c10f97285e3bSelim Cinek    private boolean mMeasureLinearly;
4406e9e1fe004d668eb205590ff125c10f97285e3bSelim Cinek    private int mDefaultPaddingEnd;
4506e9e1fe004d668eb205590ff125c10f97285e3bSelim Cinek    private Drawable mDefaultBackground;
4661254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos
4761254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos    public NotificationActionListLayout(Context context, AttributeSet attrs) {
4861254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos        super(context, attrs);
4961254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos    }
5061254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos
5161254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos    @Override
5261254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
5306e9e1fe004d668eb205590ff125c10f97285e3bSelim Cinek        if (mMeasureLinearly) {
5406e9e1fe004d668eb205590ff125c10f97285e3bSelim Cinek            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
5506e9e1fe004d668eb205590ff125c10f97285e3bSelim Cinek            return;
5606e9e1fe004d668eb205590ff125c10f97285e3bSelim Cinek        }
5761254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos        final int N = getChildCount();
5861254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos        int textViews = 0;
5961254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos        int otherViews = 0;
6061254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos        int notGoneChildren = 0;
6161254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos
6261254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos        View lastNotGoneChild = null;
6361254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos        for (int i = 0; i < N; i++) {
6461254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos            View c = getChildAt(i);
6561254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos            if (c instanceof TextView) {
6661254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos                textViews++;
6761254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos            } else {
6861254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos                otherViews++;
6961254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos            }
7061254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos            if (c.getVisibility() != GONE) {
7161254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos                notGoneChildren++;
7261254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos                lastNotGoneChild = c;
7361254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos            }
7461254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos        }
7561254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos
7661254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos        // Rebuild the measure order if the number of children changed or the text length of
7761254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos        // any of the children changed.
7861254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos        boolean needRebuild = false;
7961254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos        if (textViews != mMeasureOrderTextViews.size()
8061254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos                || otherViews != mMeasureOrderOther.size()) {
8161254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos            needRebuild = true;
8261254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos        }
8361254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos        if (!needRebuild) {
8461254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos            final int size = mMeasureOrderTextViews.size();
8561254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos            for (int i = 0; i < size; i++) {
8661254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos                Pair<Integer, TextView> pair = mMeasureOrderTextViews.get(i);
8761254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos                if (pair.first != pair.second.getText().length()) {
8861254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos                    needRebuild = true;
8961254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos                }
9061254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos            }
9161254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos        }
9261254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos        if (notGoneChildren > 1 && needRebuild) {
9361254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos            rebuildMeasureOrder(textViews, otherViews);
9461254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos        }
9561254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos
9661254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos        final boolean constrained =
9761254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos                MeasureSpec.getMode(widthMeasureSpec) != MeasureSpec.UNSPECIFIED;
9861254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos
9961254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos        final int innerWidth = MeasureSpec.getSize(widthMeasureSpec) - mPaddingLeft - mPaddingRight;
10061254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos        final int otherSize = mMeasureOrderOther.size();
10161254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos        int usedWidth = 0;
10261254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos
10361254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos        // Optimization: Don't do this if there's only one child.
10461254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos        int measuredChildren = 0;
10561254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos        for (int i = 0; i < N && notGoneChildren > 1; i++) {
10661254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos            // Measure shortest children first. To avoid measuring twice, we approximate by looking
10761254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos            // at the text length.
10861254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos            View c;
10961254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos            if (i < otherSize) {
11061254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos                c = mMeasureOrderOther.get(i);
11161254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos            } else {
11261254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos                c = mMeasureOrderTextViews.get(i - otherSize).second;
11361254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos            }
11461254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos            if (c.getVisibility() == GONE) {
11561254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos                continue;
11661254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos            }
11761254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos            MarginLayoutParams lp = (MarginLayoutParams) c.getLayoutParams();
11861254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos
11961254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos            int usedWidthForChild = usedWidth;
12061254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos            if (constrained) {
12161254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos                // Make sure that this child doesn't consume more than its share of the remaining
12261254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos                // total available space. Not used space will benefit subsequent views. Since we
12361254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos                // measure in the order of (approx.) size, a large view can still take more than its
12461254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos                // share if the others are small.
12561254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos                int availableWidth = innerWidth - usedWidth;
12661254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos                int maxWidthForChild = availableWidth / (notGoneChildren - measuredChildren);
12761254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos
12861254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos                usedWidthForChild = innerWidth - maxWidthForChild;
12961254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos            }
13061254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos
13161254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos            measureChildWithMargins(c, widthMeasureSpec, usedWidthForChild,
13261254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos                    heightMeasureSpec, 0 /* usedHeight */);
13361254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos
13461254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos            usedWidth += c.getMeasuredWidth() + lp.rightMargin + lp.leftMargin;
13561254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos            measuredChildren++;
13661254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos        }
13761254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos
13861254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos        // Make sure to measure the last child full-width if we didn't use up the entire width,
13961254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos        // or we didn't measure yet because there's just one child.
14061254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos        if (lastNotGoneChild != null && (constrained && usedWidth < innerWidth
14161254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos                || notGoneChildren == 1)) {
14261254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos            MarginLayoutParams lp = (MarginLayoutParams) lastNotGoneChild.getLayoutParams();
14361254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos            if (notGoneChildren > 1) {
14461254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos                // Need to make room, since we already measured this once.
14561254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos                usedWidth -= lastNotGoneChild.getMeasuredWidth() + lp.rightMargin + lp.leftMargin;
14661254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos            }
14761254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos
14861254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos            int originalWidth = lp.width;
14961254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos            lp.width = LayoutParams.MATCH_PARENT;
15061254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos            measureChildWithMargins(lastNotGoneChild, widthMeasureSpec, usedWidth,
15161254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos                    heightMeasureSpec, 0 /* usedHeight */);
15261254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos            lp.width = originalWidth;
15361254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos
15461254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos            usedWidth += lastNotGoneChild.getMeasuredWidth() + lp.rightMargin + lp.leftMargin;
15561254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos        }
15661254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos
15761254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos        mTotalWidth = usedWidth + mPaddingRight + mPaddingLeft;
15861254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos        setMeasuredDimension(resolveSize(getSuggestedMinimumWidth(), widthMeasureSpec),
15961254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos                resolveSize(getSuggestedMinimumHeight(), heightMeasureSpec));
16061254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos    }
16161254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos
16261254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos    private void rebuildMeasureOrder(int capacityText, int capacityOther) {
16361254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos        clearMeasureOrder();
16461254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos        mMeasureOrderTextViews.ensureCapacity(capacityText);
16561254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos        mMeasureOrderOther.ensureCapacity(capacityOther);
16661254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos        final int childCount = getChildCount();
16761254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos        for (int i = 0; i < childCount; i++) {
16861254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos            View c = getChildAt(i);
16961254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos            if (c instanceof TextView && ((TextView) c).getText().length() > 0) {
17061254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos                mMeasureOrderTextViews.add(Pair.create(((TextView) c).getText().length(),
17161254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos                        (TextView)c));
17261254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos            } else {
17361254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos                mMeasureOrderOther.add(c);
17461254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos            }
17561254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos        }
17661254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos        mMeasureOrderTextViews.sort(MEASURE_ORDER_COMPARATOR);
17761254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos    }
17861254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos
17961254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos    private void clearMeasureOrder() {
18061254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos        mMeasureOrderOther.clear();
18161254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos        mMeasureOrderTextViews.clear();
18261254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos    }
18361254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos
18461254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos    @Override
18561254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos    public void onViewAdded(View child) {
18661254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos        super.onViewAdded(child);
18761254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos        clearMeasureOrder();
18861254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos    }
18961254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos
19061254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos    @Override
19161254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos    public void onViewRemoved(View child) {
19261254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos        super.onViewRemoved(child);
19361254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos        clearMeasureOrder();
19461254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos    }
19561254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos
19661254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos    @Override
19761254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
19806e9e1fe004d668eb205590ff125c10f97285e3bSelim Cinek        if (mMeasureLinearly) {
19906e9e1fe004d668eb205590ff125c10f97285e3bSelim Cinek            super.onLayout(changed, left, top, right, bottom);
20006e9e1fe004d668eb205590ff125c10f97285e3bSelim Cinek            return;
20106e9e1fe004d668eb205590ff125c10f97285e3bSelim Cinek        }
20261254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos        final boolean isLayoutRtl = isLayoutRtl();
20361254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos        final int paddingTop = mPaddingTop;
20461254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos
20561254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos        int childTop;
20661254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos        int childLeft;
20761254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos
20861254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos        // Where bottom of child should go
20961254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos        final int height = bottom - top;
21061254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos
21161254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos        // Space available for child
21261254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos        int innerHeight = height - paddingTop - mPaddingBottom;
21361254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos
21461254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos        final int count = getChildCount();
21561254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos
21661254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos        final int layoutDirection = getLayoutDirection();
21761254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos        switch (Gravity.getAbsoluteGravity(Gravity.START, layoutDirection)) {
21861254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos            case Gravity.RIGHT:
21961254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos                // mTotalWidth contains the padding already
22061254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos                childLeft = mPaddingLeft + right - left - mTotalWidth;
22161254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos                break;
22261254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos
22361254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos            case Gravity.LEFT:
22461254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos            default:
22561254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos                childLeft = mPaddingLeft;
22661254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos                break;
22761254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos        }
22861254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos
22961254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos        int start = 0;
23061254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos        int dir = 1;
23161254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos        //In case of RTL, start drawing from the last child.
23261254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos        if (isLayoutRtl) {
23361254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos            start = count - 1;
23461254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos            dir = -1;
23561254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos        }
23661254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos
23761254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos        for (int i = 0; i < count; i++) {
23861254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos            final int childIndex = start + dir * i;
23961254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos            final View child = getChildAt(childIndex);
24061254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos            if (child.getVisibility() != GONE) {
24161254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos                final int childWidth = child.getMeasuredWidth();
24261254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos                final int childHeight = child.getMeasuredHeight();
24361254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos
24461254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos                final MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();
24561254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos
24661254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos                childTop = paddingTop + ((innerHeight - childHeight) / 2)
24761254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos                            + lp.topMargin - lp.bottomMargin;
24861254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos
24961254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos                childLeft += lp.leftMargin;
25061254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos                child.layout(childLeft, childTop, childLeft + childWidth, childTop + childHeight);
25161254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos                childLeft += childWidth + lp.rightMargin;
25261254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos            }
25361254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos        }
25461254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos    }
25561254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos
25661254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos    @Override
25706e9e1fe004d668eb205590ff125c10f97285e3bSelim Cinek    protected void onFinishInflate() {
25806e9e1fe004d668eb205590ff125c10f97285e3bSelim Cinek        super.onFinishInflate();
25906e9e1fe004d668eb205590ff125c10f97285e3bSelim Cinek        mDefaultPaddingEnd = getPaddingEnd();
26006e9e1fe004d668eb205590ff125c10f97285e3bSelim Cinek        mDefaultBackground = getBackground();
26161254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos    }
26261254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos
26306e9e1fe004d668eb205590ff125c10f97285e3bSelim Cinek    /**
26406e9e1fe004d668eb205590ff125c10f97285e3bSelim Cinek     * Set whether the list is in a mode where some actions are emphasized. This will trigger an
26506e9e1fe004d668eb205590ff125c10f97285e3bSelim Cinek     * equal measuring where all actions are full height and change a few parameters like
26606e9e1fe004d668eb205590ff125c10f97285e3bSelim Cinek     * the padding.
26706e9e1fe004d668eb205590ff125c10f97285e3bSelim Cinek     */
26806e9e1fe004d668eb205590ff125c10f97285e3bSelim Cinek    @RemotableViewMethod
26906e9e1fe004d668eb205590ff125c10f97285e3bSelim Cinek    public void setEmphasizedMode(boolean emphasizedMode) {
27006e9e1fe004d668eb205590ff125c10f97285e3bSelim Cinek        mMeasureLinearly = emphasizedMode;
27106e9e1fe004d668eb205590ff125c10f97285e3bSelim Cinek        setPaddingRelative(getPaddingStart(), getPaddingTop(),
27206e9e1fe004d668eb205590ff125c10f97285e3bSelim Cinek                emphasizedMode ? 0 : mDefaultPaddingEnd, getPaddingBottom());
27306e9e1fe004d668eb205590ff125c10f97285e3bSelim Cinek        setBackground(emphasizedMode ? null : mDefaultBackground);
27406e9e1fe004d668eb205590ff125c10f97285e3bSelim Cinek        requestLayout();
27561254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos    }
27661254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos
27761254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos    public static final Comparator<Pair<Integer, TextView>> MEASURE_ORDER_COMPARATOR
27861254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos            = (a, b) -> a.first.compareTo(b.first);
27961254356d6ce4193e516cf83c627f260431b7ce6Adrian Roos}
280