Loading core/java/com/android/internal/app/AlertController.java +8 −6 Original line number Diff line number Diff line Loading @@ -43,7 +43,6 @@ import android.view.ViewStub; import android.view.Window; import android.view.WindowInsets; import android.view.WindowManager; import android.widget.AbsListView; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.ArrayAdapter; Loading Loading @@ -115,6 +114,8 @@ public class AlertController { private int mSingleChoiceItemLayout; private int mListItemLayout; private boolean mShowTitle; private int mButtonPanelLayoutHint = AlertDialog.LAYOUT_HINT_NONE; private Handler mHandler; Loading Loading @@ -150,7 +151,7 @@ public class AlertController { private WeakReference<DialogInterface> mDialog; public ButtonHandler(DialogInterface dialog) { mDialog = new WeakReference<DialogInterface>(dialog); mDialog = new WeakReference<>(dialog); } @Override Loading Loading @@ -200,6 +201,7 @@ public class AlertController { mListItemLayout = a.getResourceId( R.styleable.AlertDialog_listItemLayout, R.layout.select_dialog_item); mShowTitle = a.getBoolean(R.styleable.AlertDialog_showTitle, true); a.recycle(); } Loading Loading @@ -600,21 +602,21 @@ public class AlertController { } private void setupTitle(ViewGroup topPanel) { if (mCustomTitleView != null) { if (mCustomTitleView != null && mShowTitle) { // Add the custom title view directly to the topPanel layout LayoutParams lp = new LayoutParams( final LayoutParams lp = new LayoutParams( LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT); topPanel.addView(mCustomTitleView, 0, lp); // Hide the title template View titleTemplate = mWindow.findViewById(R.id.title_template); final View titleTemplate = mWindow.findViewById(R.id.title_template); titleTemplate.setVisibility(View.GONE); } else { mIconView = (ImageView) mWindow.findViewById(R.id.icon); final boolean hasTextTitle = !TextUtils.isEmpty(mTitle); if (hasTextTitle) { if (hasTextTitle && mShowTitle) { // Display the title if a title is supplied, else hide it. mTitleView = (TextView) mWindow.findViewById(R.id.alertTitle); mTitleView.setText(mTitle); Loading core/java/com/android/internal/widget/AlertDialogLayout.java 0 → 100644 +239 −0 Original line number Diff line number Diff line /* * Copyright (C) 2016 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ 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; import android.util.AttributeSet; import android.view.View; import android.view.ViewGroup; import android.widget.LinearLayout; import com.android.internal.R; /** * Special implementation of linear layout that's capable of laying out alert * dialog components. * <p> * A dialog consists of up to three panels. All panels are optional, and a * dialog may contain only a single panel. The panels are laid out according * to the following guidelines: * <ul> * <li>topPanel: exactly wrap_content</li> * <li>contentPanel OR customPanel: at most fill_parent, first priority for * extra space</li> * <li>buttonPanel: at least minHeight, at most wrap_content, second * priority for extra space</li> * </ul> */ public class AlertDialogLayout extends LinearLayout { public AlertDialogLayout(@Nullable Context context) { super(context); } public AlertDialogLayout(@Nullable Context context, @Nullable AttributeSet attrs) { super(context, attrs); } public AlertDialogLayout(@Nullable Context context, @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) { super(context, attrs, defStyleAttr); } public AlertDialogLayout(@Nullable Context context, @Nullable AttributeSet attrs, @AttrRes int defStyleAttr, @StyleRes int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { if (!tryOnMeasure(widthMeasureSpec, heightMeasureSpec)) { // Failed to perform custom measurement, let superclass handle it. super.onMeasure(widthMeasureSpec, heightMeasureSpec); } } private boolean tryOnMeasure(int widthMeasureSpec, int heightMeasureSpec) { View topPanel = null; View buttonPanel = null; View middlePanel = null; final int count = getChildCount(); for (int i = 0; i < count; i++) { final View child = getChildAt(i); if (child.getVisibility() == View.GONE) { continue; } final int id = child.getId(); switch (id) { case R.id.topPanel: topPanel = child; break; case R.id.buttonPanel: buttonPanel = child; break; case R.id.contentPanel: case R.id.customPanel: if (middlePanel != null) { // Both the content and custom are visible. Abort! return false; } middlePanel = child; break; default: // Unknown top-level child. Abort! return false; } } 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(); if (topPanel != null) { topPanel.measure(widthMeasureSpec, MeasureSpec.UNSPECIFIED); usedHeight += topPanel.getMeasuredHeight(); childState = combineMeasuredStates(childState, topPanel.getMeasuredState()); } int buttonHeight = 0; int buttonWantsHeight = 0; if (buttonPanel != null) { buttonPanel.measure(widthMeasureSpec, MeasureSpec.UNSPECIFIED); buttonHeight = resolveMinimumHeight(buttonPanel); buttonWantsHeight = buttonPanel.getMeasuredHeight() - buttonHeight; usedHeight += buttonHeight; childState = combineMeasuredStates(childState, buttonPanel.getMeasuredState()); } int middleHeight = 0; if (middlePanel != null) { final int childHeightSpec; if (heightMode == MeasureSpec.UNSPECIFIED) { childHeightSpec = MeasureSpec.UNSPECIFIED; } else { childHeightSpec = MeasureSpec.makeMeasureSpec( Math.max(0, heightSize - usedHeight), heightMode); } middlePanel.measure(widthMeasureSpec, childHeightSpec); middleHeight = middlePanel.getMeasuredHeight(); usedHeight += middleHeight; childState = combineMeasuredStates(childState, middlePanel.getMeasuredState()); } int remainingHeight = heightSize - usedHeight; // Time for the "real" button measure pass. If we have remaining space, // make the button pane bigger up to its target height. Otherwise, // just remeasure the button at whatever height it needs. if (buttonPanel != null) { usedHeight -= buttonHeight; final int heightToGive = Math.min(remainingHeight, buttonWantsHeight); if (heightToGive > 0) { remainingHeight -= heightToGive; buttonHeight += heightToGive; } final int childHeightSpec = MeasureSpec.makeMeasureSpec( buttonHeight, MeasureSpec.EXACTLY); buttonPanel.measure(widthMeasureSpec, childHeightSpec); usedHeight += buttonPanel.getMeasuredHeight(); childState = combineMeasuredStates(childState, buttonPanel.getMeasuredState()); } // If we still have remaining space, make the middle pane bigger up // to the maximum height. if (middlePanel != null && remainingHeight > 0) { usedHeight -= middleHeight; final int heightToGive = remainingHeight; remainingHeight -= heightToGive; middleHeight += heightToGive; // Pass the same height mode as we're using for the dialog itself. // If it's EXACTLY, then the middle pane MUST use the entire // height. final int childHeightSpec = MeasureSpec.makeMeasureSpec( middleHeight, heightMode); middlePanel.measure(widthMeasureSpec, childHeightSpec); usedHeight += middlePanel.getMeasuredHeight(); childState = combineMeasuredStates(childState, middlePanel.getMeasuredState()); } // Compute desired width as maximum child width. int maxWidth = 0; for (int i = 0; i < count; i++) { final View child = getChildAt(i); if (child.getVisibility() != View.GONE) { 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); return true; } /** * Attempts to resolve the minimum height of a view. * <p> * If the view doesn't have a minimum height set and only contains a single * child, attempts to resolve the minimum height of the child view. * * @param v the view whose minimum height to resolve * @return the minimum height */ private int resolveMinimumHeight(View v) { final int minHeight = v.getMinimumHeight(); if (minHeight > 0) { return minHeight; } if (v instanceof ViewGroup) { final ViewGroup vg = (ViewGroup) v; if (vg.getChildCount() == 1) { return resolveMinimumHeight(vg.getChildAt(0)); } } return 0; } } core/java/com/android/internal/widget/ButtonBarLayout.java +44 −2 Original line number Diff line number Diff line Loading @@ -30,15 +30,19 @@ import com.android.internal.R; * orientation when it can't fit its child views horizontally. */ public class ButtonBarLayout extends LinearLayout { // Whether to allow vertically stacked button bars. This is disabled for // configurations with a small (e.g. less than 320dp) screen height. --> /** Minimum screen height required for button stacking. */ private static final int ALLOW_STACKING_MIN_HEIGHT_DP = 320; /** Amount of the second button to "peek" above the fold when stacked. */ private static final int PEEK_BUTTON_DP = 16; /** Whether the current configuration allows stacking. */ private boolean mAllowStacking; private int mLastWidthSize = -1; private int mMinimumHeight = 0; public ButtonBarLayout(Context context, AttributeSet attrs) { super(context, attrs); Loading Loading @@ -105,6 +109,44 @@ public class ButtonBarLayout extends LinearLayout { if (needsRemeasure) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); } // Compute minimum height such that, when stacked, some portion of the // second button is visible. int minHeight = 0; final int firstVisible = getNextVisibleChildIndex(0); if (firstVisible >= 0) { final View firstButton = getChildAt(firstVisible); final LayoutParams firstParams = (LayoutParams) firstButton.getLayoutParams(); minHeight += getPaddingTop() + firstButton.getMeasuredHeight() + firstParams.topMargin + firstParams.bottomMargin; if (isStacked()) { final int secondVisible = getNextVisibleChildIndex(firstVisible + 1); if (secondVisible >= 0) { minHeight += getChildAt(secondVisible).getPaddingTop() + PEEK_BUTTON_DP * getResources().getDisplayMetrics().density; } } else { minHeight += getPaddingBottom(); } } if (getMinimumHeight() != minHeight) { setMinimumHeight(minHeight); } } private int getNextVisibleChildIndex(int index) { for (int i = index, count = getChildCount(); i < count; i++) { if (getChildAt(i).getVisibility() == View.VISIBLE) { return i; } } return -1; } @Override public int getMinimumHeight() { return Math.max(mMinimumHeight, super.getMinimumHeight()); } private void setStacked(boolean stacked) { Loading core/res/res/layout/alert_dialog_button_bar_material.xml +45 −39 Original line number Diff line number Diff line Loading @@ -15,9 +15,15 @@ limitations under the License. --> <com.android.internal.widget.ButtonBarLayout xmlns:android="http://schemas.android.com/apk/res/android" <ScrollView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/buttonPanel" android:layout_width="match_parent" android:layout_height="wrap_content" android:scrollbarAlwaysDrawVerticalTrack="true" android:scrollIndicators="top|bottom" android:fillViewport="true" style="?attr/buttonBarStyle"> <com.android.internal.widget.ButtonBarLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layoutDirection="locale" Loading @@ -26,8 +32,7 @@ android:paddingEnd="12dp" android:paddingTop="4dp" android:paddingBottom="4dp" android:gravity="bottom" style="?attr/buttonBarStyle"> android:gravity="bottom"> <Button android:id="@+id/button3" Loading @@ -54,3 +59,4 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" /> </com.android.internal.widget.ButtonBarLayout> </ScrollView> core/res/res/layout/alert_dialog_material.xml +6 −5 Original line number Diff line number Diff line Loading @@ -15,7 +15,7 @@ limitations under the License. --> <LinearLayout <com.android.internal.widget.AlertDialogLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/parentPanel" android:layout_width="match_parent" Loading @@ -28,7 +28,6 @@ android:id="@+id/contentPanel" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="1" android:minHeight="48dp"> <ScrollView Loading Loading @@ -64,7 +63,6 @@ android:id="@+id/customPanel" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="1" android:minHeight="48dp"> <FrameLayout Loading @@ -73,5 +71,8 @@ android:layout_height="wrap_content" /> </FrameLayout> <include layout="@layout/alert_dialog_button_bar_material" /> </LinearLayout> <include android:layout_width="match_parent" android:layout_height="wrap_content" layout="@layout/alert_dialog_button_bar_material" /> </com.android.internal.widget.AlertDialogLayout> Loading
core/java/com/android/internal/app/AlertController.java +8 −6 Original line number Diff line number Diff line Loading @@ -43,7 +43,6 @@ import android.view.ViewStub; import android.view.Window; import android.view.WindowInsets; import android.view.WindowManager; import android.widget.AbsListView; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.ArrayAdapter; Loading Loading @@ -115,6 +114,8 @@ public class AlertController { private int mSingleChoiceItemLayout; private int mListItemLayout; private boolean mShowTitle; private int mButtonPanelLayoutHint = AlertDialog.LAYOUT_HINT_NONE; private Handler mHandler; Loading Loading @@ -150,7 +151,7 @@ public class AlertController { private WeakReference<DialogInterface> mDialog; public ButtonHandler(DialogInterface dialog) { mDialog = new WeakReference<DialogInterface>(dialog); mDialog = new WeakReference<>(dialog); } @Override Loading Loading @@ -200,6 +201,7 @@ public class AlertController { mListItemLayout = a.getResourceId( R.styleable.AlertDialog_listItemLayout, R.layout.select_dialog_item); mShowTitle = a.getBoolean(R.styleable.AlertDialog_showTitle, true); a.recycle(); } Loading Loading @@ -600,21 +602,21 @@ public class AlertController { } private void setupTitle(ViewGroup topPanel) { if (mCustomTitleView != null) { if (mCustomTitleView != null && mShowTitle) { // Add the custom title view directly to the topPanel layout LayoutParams lp = new LayoutParams( final LayoutParams lp = new LayoutParams( LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT); topPanel.addView(mCustomTitleView, 0, lp); // Hide the title template View titleTemplate = mWindow.findViewById(R.id.title_template); final View titleTemplate = mWindow.findViewById(R.id.title_template); titleTemplate.setVisibility(View.GONE); } else { mIconView = (ImageView) mWindow.findViewById(R.id.icon); final boolean hasTextTitle = !TextUtils.isEmpty(mTitle); if (hasTextTitle) { if (hasTextTitle && mShowTitle) { // Display the title if a title is supplied, else hide it. mTitleView = (TextView) mWindow.findViewById(R.id.alertTitle); mTitleView.setText(mTitle); Loading
core/java/com/android/internal/widget/AlertDialogLayout.java 0 → 100644 +239 −0 Original line number Diff line number Diff line /* * Copyright (C) 2016 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ 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; import android.util.AttributeSet; import android.view.View; import android.view.ViewGroup; import android.widget.LinearLayout; import com.android.internal.R; /** * Special implementation of linear layout that's capable of laying out alert * dialog components. * <p> * A dialog consists of up to three panels. All panels are optional, and a * dialog may contain only a single panel. The panels are laid out according * to the following guidelines: * <ul> * <li>topPanel: exactly wrap_content</li> * <li>contentPanel OR customPanel: at most fill_parent, first priority for * extra space</li> * <li>buttonPanel: at least minHeight, at most wrap_content, second * priority for extra space</li> * </ul> */ public class AlertDialogLayout extends LinearLayout { public AlertDialogLayout(@Nullable Context context) { super(context); } public AlertDialogLayout(@Nullable Context context, @Nullable AttributeSet attrs) { super(context, attrs); } public AlertDialogLayout(@Nullable Context context, @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) { super(context, attrs, defStyleAttr); } public AlertDialogLayout(@Nullable Context context, @Nullable AttributeSet attrs, @AttrRes int defStyleAttr, @StyleRes int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { if (!tryOnMeasure(widthMeasureSpec, heightMeasureSpec)) { // Failed to perform custom measurement, let superclass handle it. super.onMeasure(widthMeasureSpec, heightMeasureSpec); } } private boolean tryOnMeasure(int widthMeasureSpec, int heightMeasureSpec) { View topPanel = null; View buttonPanel = null; View middlePanel = null; final int count = getChildCount(); for (int i = 0; i < count; i++) { final View child = getChildAt(i); if (child.getVisibility() == View.GONE) { continue; } final int id = child.getId(); switch (id) { case R.id.topPanel: topPanel = child; break; case R.id.buttonPanel: buttonPanel = child; break; case R.id.contentPanel: case R.id.customPanel: if (middlePanel != null) { // Both the content and custom are visible. Abort! return false; } middlePanel = child; break; default: // Unknown top-level child. Abort! return false; } } 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(); if (topPanel != null) { topPanel.measure(widthMeasureSpec, MeasureSpec.UNSPECIFIED); usedHeight += topPanel.getMeasuredHeight(); childState = combineMeasuredStates(childState, topPanel.getMeasuredState()); } int buttonHeight = 0; int buttonWantsHeight = 0; if (buttonPanel != null) { buttonPanel.measure(widthMeasureSpec, MeasureSpec.UNSPECIFIED); buttonHeight = resolveMinimumHeight(buttonPanel); buttonWantsHeight = buttonPanel.getMeasuredHeight() - buttonHeight; usedHeight += buttonHeight; childState = combineMeasuredStates(childState, buttonPanel.getMeasuredState()); } int middleHeight = 0; if (middlePanel != null) { final int childHeightSpec; if (heightMode == MeasureSpec.UNSPECIFIED) { childHeightSpec = MeasureSpec.UNSPECIFIED; } else { childHeightSpec = MeasureSpec.makeMeasureSpec( Math.max(0, heightSize - usedHeight), heightMode); } middlePanel.measure(widthMeasureSpec, childHeightSpec); middleHeight = middlePanel.getMeasuredHeight(); usedHeight += middleHeight; childState = combineMeasuredStates(childState, middlePanel.getMeasuredState()); } int remainingHeight = heightSize - usedHeight; // Time for the "real" button measure pass. If we have remaining space, // make the button pane bigger up to its target height. Otherwise, // just remeasure the button at whatever height it needs. if (buttonPanel != null) { usedHeight -= buttonHeight; final int heightToGive = Math.min(remainingHeight, buttonWantsHeight); if (heightToGive > 0) { remainingHeight -= heightToGive; buttonHeight += heightToGive; } final int childHeightSpec = MeasureSpec.makeMeasureSpec( buttonHeight, MeasureSpec.EXACTLY); buttonPanel.measure(widthMeasureSpec, childHeightSpec); usedHeight += buttonPanel.getMeasuredHeight(); childState = combineMeasuredStates(childState, buttonPanel.getMeasuredState()); } // If we still have remaining space, make the middle pane bigger up // to the maximum height. if (middlePanel != null && remainingHeight > 0) { usedHeight -= middleHeight; final int heightToGive = remainingHeight; remainingHeight -= heightToGive; middleHeight += heightToGive; // Pass the same height mode as we're using for the dialog itself. // If it's EXACTLY, then the middle pane MUST use the entire // height. final int childHeightSpec = MeasureSpec.makeMeasureSpec( middleHeight, heightMode); middlePanel.measure(widthMeasureSpec, childHeightSpec); usedHeight += middlePanel.getMeasuredHeight(); childState = combineMeasuredStates(childState, middlePanel.getMeasuredState()); } // Compute desired width as maximum child width. int maxWidth = 0; for (int i = 0; i < count; i++) { final View child = getChildAt(i); if (child.getVisibility() != View.GONE) { 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); return true; } /** * Attempts to resolve the minimum height of a view. * <p> * If the view doesn't have a minimum height set and only contains a single * child, attempts to resolve the minimum height of the child view. * * @param v the view whose minimum height to resolve * @return the minimum height */ private int resolveMinimumHeight(View v) { final int minHeight = v.getMinimumHeight(); if (minHeight > 0) { return minHeight; } if (v instanceof ViewGroup) { final ViewGroup vg = (ViewGroup) v; if (vg.getChildCount() == 1) { return resolveMinimumHeight(vg.getChildAt(0)); } } return 0; } }
core/java/com/android/internal/widget/ButtonBarLayout.java +44 −2 Original line number Diff line number Diff line Loading @@ -30,15 +30,19 @@ import com.android.internal.R; * orientation when it can't fit its child views horizontally. */ public class ButtonBarLayout extends LinearLayout { // Whether to allow vertically stacked button bars. This is disabled for // configurations with a small (e.g. less than 320dp) screen height. --> /** Minimum screen height required for button stacking. */ private static final int ALLOW_STACKING_MIN_HEIGHT_DP = 320; /** Amount of the second button to "peek" above the fold when stacked. */ private static final int PEEK_BUTTON_DP = 16; /** Whether the current configuration allows stacking. */ private boolean mAllowStacking; private int mLastWidthSize = -1; private int mMinimumHeight = 0; public ButtonBarLayout(Context context, AttributeSet attrs) { super(context, attrs); Loading Loading @@ -105,6 +109,44 @@ public class ButtonBarLayout extends LinearLayout { if (needsRemeasure) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); } // Compute minimum height such that, when stacked, some portion of the // second button is visible. int minHeight = 0; final int firstVisible = getNextVisibleChildIndex(0); if (firstVisible >= 0) { final View firstButton = getChildAt(firstVisible); final LayoutParams firstParams = (LayoutParams) firstButton.getLayoutParams(); minHeight += getPaddingTop() + firstButton.getMeasuredHeight() + firstParams.topMargin + firstParams.bottomMargin; if (isStacked()) { final int secondVisible = getNextVisibleChildIndex(firstVisible + 1); if (secondVisible >= 0) { minHeight += getChildAt(secondVisible).getPaddingTop() + PEEK_BUTTON_DP * getResources().getDisplayMetrics().density; } } else { minHeight += getPaddingBottom(); } } if (getMinimumHeight() != minHeight) { setMinimumHeight(minHeight); } } private int getNextVisibleChildIndex(int index) { for (int i = index, count = getChildCount(); i < count; i++) { if (getChildAt(i).getVisibility() == View.VISIBLE) { return i; } } return -1; } @Override public int getMinimumHeight() { return Math.max(mMinimumHeight, super.getMinimumHeight()); } private void setStacked(boolean stacked) { Loading
core/res/res/layout/alert_dialog_button_bar_material.xml +45 −39 Original line number Diff line number Diff line Loading @@ -15,9 +15,15 @@ limitations under the License. --> <com.android.internal.widget.ButtonBarLayout xmlns:android="http://schemas.android.com/apk/res/android" <ScrollView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/buttonPanel" android:layout_width="match_parent" android:layout_height="wrap_content" android:scrollbarAlwaysDrawVerticalTrack="true" android:scrollIndicators="top|bottom" android:fillViewport="true" style="?attr/buttonBarStyle"> <com.android.internal.widget.ButtonBarLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layoutDirection="locale" Loading @@ -26,8 +32,7 @@ android:paddingEnd="12dp" android:paddingTop="4dp" android:paddingBottom="4dp" android:gravity="bottom" style="?attr/buttonBarStyle"> android:gravity="bottom"> <Button android:id="@+id/button3" Loading @@ -54,3 +59,4 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" /> </com.android.internal.widget.ButtonBarLayout> </ScrollView>
core/res/res/layout/alert_dialog_material.xml +6 −5 Original line number Diff line number Diff line Loading @@ -15,7 +15,7 @@ limitations under the License. --> <LinearLayout <com.android.internal.widget.AlertDialogLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/parentPanel" android:layout_width="match_parent" Loading @@ -28,7 +28,6 @@ android:id="@+id/contentPanel" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="1" android:minHeight="48dp"> <ScrollView Loading Loading @@ -64,7 +63,6 @@ android:id="@+id/customPanel" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="1" android:minHeight="48dp"> <FrameLayout Loading @@ -73,5 +71,8 @@ android:layout_height="wrap_content" /> </FrameLayout> <include layout="@layout/alert_dialog_button_bar_material" /> </LinearLayout> <include android:layout_width="match_parent" android:layout_height="wrap_content" layout="@layout/alert_dialog_button_bar_material" /> </com.android.internal.widget.AlertDialogLayout>