From 60d9695bb84a5c2a8e9ef2df32b9d4105aea2b0a Mon Sep 17 00:00:00 2001 From: Alan Viverette Date: Tue, 16 Feb 2016 12:53:36 -0500 Subject: Force uniform width for MATCH_PARENT in AlertDialogLayout The initial layout passes run using whatever was specified by the parent, which ensures that TOO_SMALL will get set correctly when needed. The final layout pass runs as EXACTLY to ensure that MATCH_PARENT widths are correctly set. Bug: 27030200 Change-Id: Ia7af3f75746e725761e78e7c4eefb0b31f499113 --- .../android/internal/widget/AlertDialogLayout.java | 45 ++++++++++++++++++---- 1 file changed, 37 insertions(+), 8 deletions(-) diff --git a/core/java/com/android/internal/widget/AlertDialogLayout.java b/core/java/com/android/internal/widget/AlertDialogLayout.java index cc0db51fb4d5..891c920af336 100644 --- a/core/java/com/android/internal/widget/AlertDialogLayout.java +++ b/core/java/com/android/internal/widget/AlertDialogLayout.java @@ -17,7 +17,6 @@ package com.android.internal.widget; import android.annotation.AttrRes; -import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.StyleRes; import android.content.Context; @@ -107,14 +106,7 @@ public class AlertDialogLayout extends LinearLayout { final int heightMode = MeasureSpec.getMode(heightMeasureSpec); final int heightSize = MeasureSpec.getSize(heightMeasureSpec); - - // Treat all panel widths as MATCH_PARENT - // by translating AT_MOST to EXACTLY. final int widthMode = MeasureSpec.getMode(widthMeasureSpec); - if (widthMode == MeasureSpec.AT_MOST) { - final int widthSize = MeasureSpec.getSize(widthMeasureSpec); - widthMeasureSpec = MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.EXACTLY); - } int childState = 0; int usedHeight = getPaddingTop() + getPaddingBottom(); @@ -204,14 +196,51 @@ public class AlertDialogLayout extends LinearLayout { maxWidth = Math.max(maxWidth, child.getMeasuredWidth()); } } + maxWidth += getPaddingLeft() + getPaddingRight(); final int widthSizeAndState = resolveSizeAndState(maxWidth, widthMeasureSpec, childState); final int heightSizeAndState = resolveSizeAndState(usedHeight, heightMeasureSpec, 0); setMeasuredDimension(widthSizeAndState, heightSizeAndState); + + // If the children weren't already measured EXACTLY, we need to run + // another measure pass to for MATCH_PARENT widths. + if (widthMode != MeasureSpec.EXACTLY) { + forceUniformWidth(count, heightMeasureSpec); + } + return true; } + /** + * Remeasures child views to exactly match the layout's measured width. + * + * @param count the number of child views + * @param heightMeasureSpec the original height measure spec + */ + private void forceUniformWidth(int count, int heightMeasureSpec) { + // Pretend that the linear layout has an exact size. + final int uniformMeasureSpec = MeasureSpec.makeMeasureSpec( + getMeasuredWidth(), MeasureSpec.EXACTLY); + + for (int i = 0; i < count; i++) { + final View child = getChildAt(i); + if (child.getVisibility() != GONE) { + final LayoutParams lp = (LayoutParams) child.getLayoutParams(); + if (lp.width == LayoutParams.MATCH_PARENT) { + // Temporarily force children to reuse their old measured + // height. + final int oldHeight = lp.height; + lp.height = child.getMeasuredHeight(); + + // Remeasure with new dimensions. + measureChildWithMargins(child, uniformMeasureSpec, 0, heightMeasureSpec, 0); + lp.height = oldHeight; + } + } + } + } + /** * Attempts to resolve the minimum height of a view. *

-- cgit v1.2.3-59-g8ed1b