Fix measure logic so that priority children can have more than 1/N space.
The priority previously just put the view at the front of the list, which ensured that super long user-provided actions couldn't cause the priority action at the end to be truncated. However, this still meant that a priority action at the start whose text would have it be longer than 1/3 of the action space would be capped at 1/3 instead of taking on some of the user-defined child's space. Bug: 187533622 Test: Post Notify2 app's Call style w/ Screen action; notice that "Decline" is not truncated. Change-Id: Ia18b2dc366ba7cac13ed845acac59d89206e7d5e
This commit is contained in:
@@ -17,11 +17,11 @@
|
||||
package com.android.internal.widget;
|
||||
|
||||
import android.annotation.DimenRes;
|
||||
import android.app.Notification;
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.drawable.RippleDrawable;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Pair;
|
||||
import android.view.Gravity;
|
||||
import android.view.RemotableViewMethod;
|
||||
import android.view.View;
|
||||
@@ -43,7 +43,7 @@ public class NotificationActionListLayout extends LinearLayout {
|
||||
private final int mGravity;
|
||||
private int mTotalWidth = 0;
|
||||
private int mExtraStartPadding = 0;
|
||||
private ArrayList<Pair<Integer, TextView>> mMeasureOrderTextViews = new ArrayList<>();
|
||||
private ArrayList<TextViewInfo> mMeasureOrderTextViews = new ArrayList<>();
|
||||
private ArrayList<View> mMeasureOrderOther = new ArrayList<>();
|
||||
private boolean mEmphasizedMode;
|
||||
private int mDefaultPaddingBottom;
|
||||
@@ -69,12 +69,18 @@ public class NotificationActionListLayout extends LinearLayout {
|
||||
ta.recycle();
|
||||
}
|
||||
|
||||
private static boolean isPriority(View actionView) {
|
||||
return actionView instanceof EmphasizedNotificationButton
|
||||
&& ((EmphasizedNotificationButton) actionView).isPriority();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
final int N = getChildCount();
|
||||
int textViews = 0;
|
||||
int otherViews = 0;
|
||||
int notGoneChildren = 0;
|
||||
int priorityChildren = 0;
|
||||
|
||||
for (int i = 0; i < N; i++) {
|
||||
View c = getChildAt(i);
|
||||
@@ -85,6 +91,9 @@ public class NotificationActionListLayout extends LinearLayout {
|
||||
}
|
||||
if (c.getVisibility() != GONE) {
|
||||
notGoneChildren++;
|
||||
if (isPriority(c)) {
|
||||
priorityChildren++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,9 +107,9 @@ public class NotificationActionListLayout extends LinearLayout {
|
||||
if (!needRebuild) {
|
||||
final int size = mMeasureOrderTextViews.size();
|
||||
for (int i = 0; i < size; i++) {
|
||||
Pair<Integer, TextView> pair = mMeasureOrderTextViews.get(i);
|
||||
if (pair.first != pair.second.getText().length()) {
|
||||
if (mMeasureOrderTextViews.get(i).needsRebuild()) {
|
||||
needRebuild = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -117,14 +126,19 @@ public class NotificationActionListLayout extends LinearLayout {
|
||||
int usedWidth = 0;
|
||||
|
||||
int measuredChildren = 0;
|
||||
int measuredPriorityChildren = 0;
|
||||
for (int i = 0; i < N; i++) {
|
||||
// Measure shortest children first. To avoid measuring twice, we approximate by looking
|
||||
// at the text length.
|
||||
View c;
|
||||
final boolean isPriority;
|
||||
final View c;
|
||||
if (i < otherSize) {
|
||||
c = mMeasureOrderOther.get(i);
|
||||
isPriority = false;
|
||||
} else {
|
||||
c = mMeasureOrderTextViews.get(i - otherSize).second;
|
||||
TextViewInfo info = mMeasureOrderTextViews.get(i - otherSize);
|
||||
c = info.mTextView;
|
||||
isPriority = info.mIsPriority;
|
||||
}
|
||||
if (c.getVisibility() == GONE) {
|
||||
continue;
|
||||
@@ -138,7 +152,18 @@ public class NotificationActionListLayout extends LinearLayout {
|
||||
// measure in the order of (approx.) size, a large view can still take more than its
|
||||
// share if the others are small.
|
||||
int availableWidth = innerWidth - usedWidth;
|
||||
int maxWidthForChild = availableWidth / (notGoneChildren - measuredChildren);
|
||||
int unmeasuredChildren = notGoneChildren - measuredChildren;
|
||||
int maxWidthForChild = availableWidth / unmeasuredChildren;
|
||||
if (isPriority) {
|
||||
// Priority children get a larger maximum share of the total space:
|
||||
// maximum priority share = (nPriority + 1) / (MAX + 1)
|
||||
int unmeasuredPriorityChildren = priorityChildren - measuredPriorityChildren;
|
||||
int unmeasuredOtherChildren = unmeasuredChildren - unmeasuredPriorityChildren;
|
||||
int widthReservedForOtherChildren = innerWidth * unmeasuredOtherChildren
|
||||
/ (Notification.MAX_ACTION_BUTTONS + 1);
|
||||
int widthAvailableForPriority = availableWidth - widthReservedForOtherChildren;
|
||||
maxWidthForChild = widthAvailableForPriority / unmeasuredPriorityChildren;
|
||||
}
|
||||
|
||||
usedWidthForChild = innerWidth - maxWidthForChild;
|
||||
}
|
||||
@@ -148,6 +173,9 @@ public class NotificationActionListLayout extends LinearLayout {
|
||||
|
||||
usedWidth += c.getMeasuredWidth() + lp.rightMargin + lp.leftMargin;
|
||||
measuredChildren++;
|
||||
if (isPriority) {
|
||||
measuredPriorityChildren++;
|
||||
}
|
||||
}
|
||||
|
||||
int collapsibleIndent = mCollapsibleIndentDimen == 0 ? 0
|
||||
@@ -170,12 +198,8 @@ public class NotificationActionListLayout extends LinearLayout {
|
||||
final int childCount = getChildCount();
|
||||
for (int i = 0; i < childCount; i++) {
|
||||
View c = getChildAt(i);
|
||||
if (isPriority(c)) {
|
||||
// add with 0 length to ensure that this view is measured before others.
|
||||
mMeasureOrderTextViews.add(Pair.create(0, (TextView) c));
|
||||
} else if (c instanceof TextView && ((TextView) c).getText().length() > 0) {
|
||||
mMeasureOrderTextViews.add(Pair.create(((TextView) c).getText().length(),
|
||||
(TextView)c));
|
||||
if (c instanceof TextView && ((TextView) c).getText().length() > 0) {
|
||||
mMeasureOrderTextViews.add(new TextViewInfo((TextView) c));
|
||||
} else {
|
||||
mMeasureOrderOther.add(c);
|
||||
}
|
||||
@@ -333,6 +357,28 @@ public class NotificationActionListLayout extends LinearLayout {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static final Comparator<Pair<Integer, TextView>> MEASURE_ORDER_COMPARATOR
|
||||
= (a, b) -> a.first.compareTo(b.first);
|
||||
public static final Comparator<TextViewInfo> MEASURE_ORDER_COMPARATOR = (a, b) -> {
|
||||
int priorityComparison = -Boolean.compare(a.mIsPriority, b.mIsPriority);
|
||||
return priorityComparison != 0
|
||||
? priorityComparison
|
||||
: Integer.compare(a.mTextLength, b.mTextLength);
|
||||
};
|
||||
|
||||
private static final class TextViewInfo {
|
||||
final boolean mIsPriority;
|
||||
final int mTextLength;
|
||||
final TextView mTextView;
|
||||
|
||||
TextViewInfo(TextView textView) {
|
||||
this.mIsPriority = isPriority(textView);
|
||||
this.mTextLength = textView.getText().length();
|
||||
this.mTextView = textView;
|
||||
}
|
||||
|
||||
boolean needsRebuild() {
|
||||
return mTextView.getText().length() != mTextLength
|
||||
|| isPriority(mTextView) != mIsPriority;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user