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