Merge "Add custom dialog with icon" into udc-dev

This commit is contained in:
Tetiana Meronyk
2023-04-20 15:12:58 +00:00
committed by Android (Google) Code Review
7 changed files with 526 additions and 0 deletions

View File

@@ -0,0 +1,39 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (C) 2021 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.
-->
<inset xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
android:insetTop="@dimen/dialog_button_vertical_inset"
android:insetBottom="@dimen/dialog_button_vertical_inset">
<ripple android:color="?android:attr/colorControlHighlight">
<item android:id="@android:id/mask">
<shape android:shape="rectangle">
<solid android:color="@android:color/white"/>
<corners android:radius="?android:attr/buttonCornerRadius"/>
</shape>
</item>
<item>
<shape android:shape="rectangle">
<corners android:radius="?android:attr/buttonCornerRadius"/>
<solid android:color="?androidprv:attr/colorAccentPrimary"/>
<padding android:left="@dimen/dialog_button_horizontal_padding"
android:top="@dimen/dialog_button_vertical_padding"
android:right="@dimen/dialog_button_horizontal_padding"
android:bottom="@dimen/dialog_button_vertical_padding"/>
</shape>
</item>
</ripple>
</inset>

View File

@@ -0,0 +1,42 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (C) 2023 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.
-->
<inset xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
android:insetTop="@dimen/dialog_button_vertical_inset"
android:insetBottom="@dimen/dialog_button_vertical_inset">
<ripple android:color="?android:attr/colorControlHighlight">
<item android:id="@android:id/mask">
<shape android:shape="rectangle">
<solid android:color="@android:color/white"/>
<corners android:radius="?android:attr/buttonCornerRadius"/>
</shape>
</item>
<item>
<shape android:shape="rectangle">
<corners android:radius="?android:attr/buttonCornerRadius"/>
<solid android:color="@android:color/transparent"/>
<stroke android:color="?androidprv:attr/colorAccentPrimaryVariant"
android:width="1dp"
/>
<padding android:left="@dimen/dialog_button_horizontal_padding"
android:top="@dimen/dialog_button_vertical_padding"
android:right="@dimen/dialog_button_horizontal_padding"
android:bottom="@dimen/dialog_button_vertical_padding"/>
</shape>
</item>
</ripple>
</inset>

View File

@@ -0,0 +1,25 @@
<!--
~ Copyright (C) 2023 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.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24.0dp"
android:height="24.0dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M17,17Q17.625,17 18.062,16.562Q18.5,16.125 18.5,15.5Q18.5,14.875 18.062,14.438Q17.625,14 17,14Q16.375,14 15.938,14.438Q15.5,14.875 15.5,15.5Q15.5,16.125 15.938,16.562Q16.375,17 17,17ZM17,20Q17.775,20 18.425,19.637Q19.075,19.275 19.475,18.675Q18.925,18.35 18.3,18.175Q17.675,18 17,18Q16.325,18 15.7,18.175Q15.075,18.35 14.525,18.675Q14.925,19.275 15.575,19.637Q16.225,20 17,20ZM12,22Q8.525,21.125 6.263,18.012Q4,14.9 4,11.1V5L12,2L20,5V10.675Q19.525,10.475 19.025,10.312Q18.525,10.15 18,10.075V6.4L12,4.15L6,6.4V11.1Q6,12.275 6.312,13.45Q6.625,14.625 7.188,15.688Q7.75,16.75 8.55,17.65Q9.35,18.55 10.325,19.15Q10.6,19.95 11.05,20.675Q11.5,21.4 12.075,21.975Q12.05,21.975 12.038,21.988Q12.025,22 12,22ZM17,22Q14.925,22 13.463,20.538Q12,19.075 12,17Q12,14.925 13.463,13.462Q14.925,12 17,12Q19.075,12 20.538,13.462Q22,14.925 22,17Q22,19.075 20.538,20.538Q19.075,22 17,22ZM12,11.65Q12,11.65 12,11.65Q12,11.65 12,11.65Q12,11.65 12,11.65Q12,11.65 12,11.65Q12,11.65 12,11.65Q12,11.65 12,11.65Q12,11.65 12,11.65Q12,11.65 12,11.65Q12,11.65 12,11.65Q12,11.65 12,11.65Z"/>
</vector>

View File

@@ -0,0 +1,99 @@
<!--
~ Copyright (C) 2023 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.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:padding="@dimen/grant_admin_dialog_padding"
android:paddingBottom="0dp">
<ImageView
android:id="@+id/dialog_with_icon_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription=""/>
<TextView
android:id="@+id/dialog_with_icon_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
style="@style/DialogWithIconTitle"
android:text="@string/user_grant_admin_title"
android:textDirection="locale"/>
<TextView
android:id="@+id/dialog_with_icon_message"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="10dp"
android:gravity="center"
style="@style/TextAppearanceSmall"
android:text=""
android:textDirection="locale"/>
<LinearLayout
android:id="@+id/custom_layout"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:paddingBottom="0dp">
</LinearLayout>
<LinearLayout
android:id="@+id/button_panel"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:paddingBottom="0dp">
<Button
android:id="@+id/button_cancel"
style="@style/DialogButtonNegative"
android:layout_width="wrap_content"
android:buttonCornerRadius="28dp"
android:layout_height="wrap_content"
android:visibility="gone"/>
<Space
android:layout_width="0dp"
android:layout_height="1dp"
android:layout_weight="1" >
</Space>
<Button
android:id="@+id/button_back"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/DialogButtonNegative"
android:buttonCornerRadius="40dp"
android:clickable="true"
android:focusable="true"
android:text="Back"
android:visibility="gone"
/>
<Space
android:layout_width="0dp"
android:layout_height="1dp"
android:layout_weight="0.05"
>
</Space>
<Button
android:id="@+id/button_ok"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/DialogButtonPositive"
android:clickable="true"
android:focusable="true"
android:visibility="gone"
/>
</LinearLayout>
</LinearLayout>

View File

@@ -112,4 +112,13 @@
<!-- Size of grant admin privileges dialog padding -->
<dimen name="grant_admin_dialog_padding">16dp</dimen>
<dimen name="dialog_button_horizontal_padding">16dp</dimen>
<dimen name="dialog_button_vertical_padding">8dp</dimen>
<!-- The button will be 48dp tall, but the background needs to be 36dp tall -->
<dimen name="dialog_button_vertical_inset">6dp</dimen>
<dimen name="dialog_top_padding">24dp</dimen>
<dimen name="dialog_bottom_padding">18dp</dimen>
<dimen name="dialog_side_padding">24dp</dimen>
<dimen name="dialog_button_bar_top_padding">32dp</dimen>
</resources>

View File

@@ -83,4 +83,39 @@
<item name="android:textDirection">locale</item>
<item name="android:ellipsize">end</item>
</style>
<style name="DialogWithIconTitle" parent="@android:TextAppearance.DeviceDefault.Headline">
<item name="android:textSize">@dimen/broadcast_dialog_title_text_size</item>
<item name="android:textColor">?android:attr/textColorPrimary</item>
<item name="android:textDirection">locale</item>
<item name="android:ellipsize">end</item>
</style>
<style name="DialogButtonPositive" xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
<item name="android:buttonCornerRadius">0dp</item>
<item name="android:background">@drawable/dialog_btn_filled</item>
<item name="android:textColor">?androidprv:attr/textColorOnAccent</item>
<item name="android:textSize">14sp</item>
<item name="android:lineHeight">20sp</item>
<item name="android:fontFamily">@*android:string/config_bodyFontFamilyMedium</item>
<item name="android:stateListAnimator">@null</item>
<item name="android:minWidth">0dp</item>
</style>
<style name="DialogButtonNegative">
<item name="android:buttonCornerRadius">28dp</item>
<item name="android:background">@drawable/dialog_btn_outline</item>
<item name="android:buttonCornerRadius">28dp</item>
<item name="android:textColor">?android:attr/textColorPrimary</item>
<item name="android:textSize">14sp</item>
<item name="android:lineHeight">20sp</item>
<item name="android:fontFamily">@*android:string/config_bodyFontFamilyMedium</item>
<item name="android:stateListAnimator">@null</item>
<item name="android:minWidth">0dp</item>
</style>
<style name="TextStyleMessage">
<item name="android:textAppearance">?android:attr/textAppearanceSmall</item>
<item name="android:textSize">16dp</item>
</style>
</resources>

View File

@@ -0,0 +1,277 @@
/*
* Copyright (C) 2023 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.settingslib.utils;
import android.annotation.IntDef;
import android.annotation.StringRes;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.android.settingslib.R;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
* This class is used to create custom dialog with icon, title, message and custom view that are
* horizontally centered.
*/
public class CustomDialogHelper {
@Retention(RetentionPolicy.SOURCE)
@IntDef({ICON, TITLE, MESSAGE, LAYOUT, BACK_BUTTON, NEGATIVE_BUTTON, POSITIVE_BUTTON})
public @interface LayoutComponent {}
@Retention(RetentionPolicy.SOURCE)
@IntDef({BACK_BUTTON, NEGATIVE_BUTTON, POSITIVE_BUTTON})
public @interface LayoutButton {}
public static final int ICON = 0;
public static final int TITLE = 1;
public static final int MESSAGE = 2;
public static final int LAYOUT = 3;
public static final int BACK_BUTTON = 4;
public static final int NEGATIVE_BUTTON = 5;
public static final int POSITIVE_BUTTON = 6;
private View mDialogContent;
private Dialog mDialog;
private Context mContext;
private LayoutInflater mLayoutInflater;
private ImageView mDialogIcon;
private TextView mDialogTitle;
private TextView mDialogMessage;
private LinearLayout mCustomLayout;
private Button mPositiveButton;
private Button mNegativeButton;
private Button mBackButton;
public CustomDialogHelper(Context context) {
mContext = context;
mLayoutInflater = LayoutInflater.from(context);
mDialogContent = mLayoutInflater.inflate(R.layout.dialog_with_icon, null);
mDialogIcon = mDialogContent.findViewById(R.id.dialog_with_icon_icon);
mDialogTitle = mDialogContent.findViewById(R.id.dialog_with_icon_title);
mDialogMessage = mDialogContent.findViewById(R.id.dialog_with_icon_message);
mCustomLayout = mDialogContent.findViewById(R.id.custom_layout);
mPositiveButton = mDialogContent.findViewById(R.id.button_ok);
mNegativeButton = mDialogContent.findViewById(R.id.button_cancel);
mBackButton = mDialogContent.findViewById(R.id.button_back);
createDialog();
}
/**
* Creates dialog with content defined in constructor.
*/
private void createDialog() {
mDialog = new AlertDialog.Builder(mContext)
.setView(mDialogContent)
.setCancelable(true)
.create();
mDialog.getWindow()
.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
}
/**
* Sets title and listener for positive button.
*/
public CustomDialogHelper setPositiveButton(@StringRes int resid,
View.OnClickListener onClickListener) {
setButton(POSITIVE_BUTTON, resid, onClickListener);
return this;
}
/**
* Sets positive button text.
*/
public CustomDialogHelper setPositiveButtonText(@StringRes int resid) {
mPositiveButton.setText(resid);
return this;
}
/**
* Sets title and listener for negative button.
*/
public CustomDialogHelper setNegativeButton(@StringRes int resid,
View.OnClickListener onClickListener) {
setButton(NEGATIVE_BUTTON, resid, onClickListener);
return this;
}
/**
* Sets negative button text.
*/
public CustomDialogHelper setNegativeButtonText(@StringRes int resid) {
mNegativeButton.setText(resid);
return this;
}
/**
* Sets title and listener for back button.
*/
public CustomDialogHelper setBackButton(@StringRes int resid,
View.OnClickListener onClickListener) {
setButton(BACK_BUTTON, resid, onClickListener);
return this;
}
/**
* Sets title for back button.
*/
public CustomDialogHelper setBackButtonText(@StringRes int resid) {
mBackButton.setText(resid);
return this;
}
private void setButton(@LayoutButton int whichButton, @StringRes int resid,
View.OnClickListener listener) {
switch (whichButton) {
case POSITIVE_BUTTON :
mPositiveButton.setText(resid);
mPositiveButton.setVisibility(View.VISIBLE);
mPositiveButton.setOnClickListener(listener);
break;
case NEGATIVE_BUTTON:
mNegativeButton.setText(resid);
mNegativeButton.setVisibility(View.VISIBLE);
mNegativeButton.setOnClickListener(listener);
break;
case BACK_BUTTON:
mBackButton.setText(resid);
mBackButton.setVisibility(View.VISIBLE);
mBackButton.setOnClickListener(listener);
break;
default:
break;
}
}
/**
* Modifies state of button.
* //TODO: modify method to allow setting state for any button.
*/
public CustomDialogHelper setButtonEnabled(boolean enabled) {
mPositiveButton.setEnabled(enabled);
return this;
}
/**
* Sets title of the dialog.
*/
public CustomDialogHelper setTitle(@StringRes int resid) {
mDialogTitle.setText(resid);
return this;
}
/**
* Sets message of the dialog.
*/
public CustomDialogHelper setMessage(@StringRes int resid) {
mDialogMessage.setText(resid);
return this;
}
/**
* Sets icon of the dialog.
*/
public CustomDialogHelper setIcon(Drawable icon) {
mDialogIcon.setImageDrawable(icon);
return this;
}
/**
* Removes all views that were previously added to the custom layout part.
*/
public CustomDialogHelper clearCustomLayout() {
mCustomLayout.removeAllViews();
return this;
}
/**
* Hides custom layout.
*/
public void hideCustomLayout() {
mCustomLayout.setVisibility(View.GONE);
}
/**
* Shows custom layout.
*/
public void showCustomLayout() {
mCustomLayout.setVisibility(View.VISIBLE);
}
/**
* Adds view to custom layout.
*/
public CustomDialogHelper addCustomView(View view) {
mCustomLayout.addView(view);
return this;
}
/**
* Returns dialog.
*/
public Dialog getDialog() {
return mDialog;
}
/**
* Sets visibility of layout component.
* @param element part of the layout visibility of which is being changed.
* @param isVisible true if visibility is set to View.VISIBLE
* @return this
*/
public CustomDialogHelper setVisibility(@LayoutComponent int element, boolean isVisible) {
int visibility;
if (isVisible) {
visibility = View.VISIBLE;
} else {
visibility = View.GONE;
}
switch (element) {
case ICON:
mDialogIcon.setVisibility(visibility);
break;
case TITLE:
mDialogTitle.setVisibility(visibility);
break;
case MESSAGE:
mDialogMessage.setVisibility(visibility);
break;
case BACK_BUTTON:
mBackButton.setVisibility(visibility);
break;
case NEGATIVE_BUTTON:
mNegativeButton.setVisibility(visibility);
break;
case POSITIVE_BUTTON:
mPositiveButton.setVisibility(visibility);
break;
default:
break;
}
return this;
}
}