QQ登录

只需要一步,快速开始

APP扫码登录

只需要一步,快速开始

手机号码,快捷登录

泡泡马甲APP 更多内容请下载泡泡马甲手机客户端APP 立即下载 ×
查看: 4180|回复: 0

[Android/IOS] Android修改Dialog样式的方法

[复制链接]

等级头衔

积分成就    金币 : 2802
   泡泡 : 1516
   精华 : 6
   在线时间 : 1242 小时
   最后登录 : 2024-4-18

丰功伟绩

优秀达人突出贡献荣誉管理论坛元老

联系方式
发表于 2021-5-24 11:02:43 | 显示全部楼层 |阅读模式
       Android 对话框支持自定义标题,内容,按钮和点击事件,基本上可以满足我们日常的使用。 但有时候我们想要修改对话框的文字,按钮颜色等,系统并没有提供对应的方法,正常情况下只能自定义布局。 接下来通过源码解析介绍几种修改 Dialog样式的方法。
/ f) G& o9 a* g/ X3 W  r: m一、Dialog源码解析3 U3 E4 y) c  M4 O  L  u! V
1.1 new AlertDialog.Builder(this).create()& c4 p9 R1 P! }
  1. protected AlertDialog(@NonNull Context context, @StyleRes int themeResId) {
  2.         super(context, resolveDialogTheme(context, themeResId));
  3.         //创建AlertController,是Dialog布局相关代码
  4.         mAlert = new AlertController(getContext(), this, getWindow());
  5.     }
  6.         @NonNull
  7.         public AlertDialog create() {
  8.             // We can't use Dialog's 3-arg constructor with the createThemeContextWrapper param,
  9.             // so we always have to re-set the theme
  10.             final AlertDialog dialog = new AlertDialog(P.mContext, mTheme);
  11.             P.apply(dialog.mAlert);
  12.             dialog.setCancelable(P.mCancelable);
  13.             if (P.mCancelable) {
  14.                 dialog.setCanceledOnTouchOutside(true);
  15.             }
  16.             dialog.setOnCancelListener(P.mOnCancelListener);
  17.             dialog.setOnDismissListener(P.mOnDismissListener);
  18.             if (P.mOnKeyListener != null) {
  19.                 dialog.setOnKeyListener(P.mOnKeyListener);
  20.             }
  21.             return dialog;
  22.         }
  23.         public void apply(AlertController dialog) {
  24.             if (mCustomTitleView != null) {
  25.                 dialog.setCustomTitle(mCustomTitleView);
  26.             } else {
  27.                 if (mTitle != null) {
  28.                     dialog.setTitle(mTitle);
  29.                 }
  30.                 if (mIcon != null) {
  31.                     dialog.setIcon(mIcon);
  32.                 }
  33.                 if (mIconId != 0) {
  34.                     dialog.setIcon(mIconId);
  35.                 }
  36.             ..........
  • AlertDialog 构造函数中会创建 AlertController,用来控制对话框的布局
  • P.apply(dialog.mAlert); 将用户自定义的配置赋值给 AlertController
    $ v/ S  _+ w: ^$ f0 ^
1.2 AlertController) m; |: T4 a5 F3 x. M
  1. public AlertController(Context context, AppCompatDialog di, Window window) {
  2.         mContext = context;
  3.         mDialog = di;
  4.         mWindow = window;
  5.         mHandler = new ButtonHandler(di);
  6.         final TypedArray a = context.obtainStyledAttributes(null, R.styleable.AlertDialog,
  7.                 R.attr.alertDialogStyle, 0);
  8.         mAlertDialogLayout = a.getResourceId(R.styleable.AlertDialog_android_layout, 0);
  9.         mButtonPanelSideLayout = a.getResourceId(R.styleable.AlertDialog_buttonPanelSideLayout, 0);
  10.         mListLayout = a.getResourceId(R.styleable.AlertDialog_listLayout, 0);
  11.         mMultiChoiceItemLayout = a.getResourceId(R.styleable.AlertDialog_multiChoiceItemLayout, 0);
  12.         mSingleChoiceItemLayout = a
  13.                 .getResourceId(R.styleable.AlertDialog_singleChoiceItemLayout, 0);
  14.         mListItemLayout = a.getResourceId(R.styleable.AlertDialog_listItemLayout, 0);
  15.         mShowTitle = a.getBoolean(R.styleable.AlertDialog_showTitle, true);
  16.         mButtonIconDimen = a.getDimensionPixelSize(R.styleable.AlertDialog_buttonIconDimen, 0);
  17.         a.recycle();
  18.         /* We use a custom title so never request a window title */
  19.         di.supportRequestWindowFeature(Window.FEATURE_NO_TITLE);
  20.     }
      R.attr.alertDialogStyle 是对话框的默认样式, ]5 Z2 c; z, J8 }& Y0 K( j* D1 S* t
  1. <item name="alertDialogStyle">@style/AlertDialog.AppCompat</item>
  2.         <style name="AlertDialog.AppCompat" parent="Base.AlertDialog.AppCompat"/>
  3.               <style name="Base.AlertDialog.AppCompat" parent="android:Widget">
  4.                 <item name="android:layout">@layout/abc_alert_dialog_material</item>
  5.                 <item name="listLayout">@layout/abc_select_dialog_material</item>
  6.                         <item name="listItemLayout">@layout/select_dialog_item_material</item>
  7.                 <item name="multiChoiceItemLayout">@layout/select_dialog_multichoice_material</item>
  8.                 <item name="singleChoiceItemLayout">@layout/select_dialog_singlechoice_material</item>
  9.                 <item name="buttonIconDimen">@dimen/abc_alert_dialog_button_dimen</item>
  10.             </style>
      上述代码可以看出,abc_alert_dialog_material 就是dialog的默认布局。
6 I6 Y. S2 [, D9 R1 }! k6 \
  1. <androidx.appcompat.widget.AlertDialogLayout
  2.     xmlns:android="http://schemas.android.com/apk/res/android"
  3.     android:id="@+id/parentPanel"
  4.     android:layout_width="match_parent"
  5.     android:layout_height="wrap_content"
  6.     android:gravity="start|left|top"
  7.     android:orientation="vertical">
  8.     <include layout="@layout/abc_alert_dialog_title_material"/>
  9.     <FrameLayout
  10.         android:id="@+id/contentPanel"
  11.         android:layout_width="match_parent"
  12.         android:layout_height="wrap_content"
  13.         android:minHeight="48dp">
  14.         <View android:id="@+id/scrollIndicatorUp"
  15.               android:layout_width="match_parent"
  16.               android:layout_height="1dp"
  17.               android:layout_gravity="top"
  18.               android:background="?attr/colorControlHighlight"
  19.               android:visibility="gone"/>
  20.         <androidx.core.widget.NestedScrollView
  21.             android:id="@+id/scrollView"
  22.             android:layout_width="match_parent"
  23.             android:layout_height="wrap_content"
  24.             android:clipToPadding="false">
  25.             <LinearLayout
  26.                 android:layout_width="match_parent"
  27.                 android:layout_height="wrap_content"
  28.                 android:orientation="vertical">
  29.                 <android.widget.Space
  30.                     android:id="@+id/textSpacerNoTitle"
  31.                     android:layout_width="match_parent"
  32.                     android:layout_height="@dimen/abc_dialog_padding_top_material"
  33.                     android:visibility="gone"/>
  34.                 <TextView
  35.                     android:id="@android:id/message"
  36.                     style="@style/TextAppearance.AppCompat.Subhead"
  37.                     android:layout_width="match_parent"
  38.                     android:layout_height="wrap_content"
  39.                     android:paddingLeft="?attr/dialogPreferredPadding"
  40.                     android:paddingRight="?attr/dialogPreferredPadding"/>
  41.                 <android.widget.Space
  42.                     android:id="@+id/textSpacerNoButtons"
  43.                     android:layout_width="match_parent"
  44.                     android:layout_height="@dimen/abc_dialog_padding_top_material"
  45.                     android:visibility="gone"/>
  46.             </LinearLayout>
  47.         </androidx.core.widget.NestedScrollView>
  48.         <View android:id="@+id/scrollIndicatorDown"
  49.               android:layout_width="match_parent"
  50.               android:layout_height="1dp"
  51.               android:layout_gravity="bottom"
  52.               android:background="?attr/colorControlHighlight"
  53.               android:visibility="gone"/>
  54.     </FrameLayout>
  55.     <FrameLayout
  56.         android:id="@+id/customPanel"
  57.         android:layout_width="match_parent"
  58.         android:layout_height="wrap_content"
  59.         android:minHeight="48dp">
  60.         <FrameLayout
  61.             android:id="@+id/custom"
  62.             android:layout_width="match_parent"
  63.             android:layout_height="wrap_content"/>
  64.     </FrameLayout>
  65.     <include layout="@layout/abc_alert_dialog_button_bar_material"
  66.              android:layout_width="match_parent"
  67.              android:layout_height="wrap_content"/>
  68. </androidx.appcompat.widget.AlertDialogLayout>
      标题布局:
, \7 B6 D. D/ m; |
  1. <!-- abc_alert_dialog_title_material: -->
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3.               android:id="@+id/topPanel"
  4.               android:layout_width="match_parent"
  5.               android:layout_height="wrap_content"
  6.               android:orientation="vertical">
  7.     <!-- If the client uses a customTitle, it will be added here. -->
  8.     <LinearLayout
  9.         android:id="@+id/title_template"
  10.         android:layout_width="match_parent"
  11.         android:layout_height="wrap_content"
  12.         android:gravity="center_vertical|start|left"
  13.         android:orientation="horizontal"
  14.         android:paddingLeft="?attr/dialogPreferredPadding"
  15.         android:paddingRight="?attr/dialogPreferredPadding"
  16.         android:paddingTop="@dimen/abc_dialog_padding_top_material">
  17.         <ImageView
  18.             android:id="@android:id/icon"
  19.             android:layout_width="32dip"
  20.             android:layout_height="32dip"
  21.             android:layout_marginEnd="8dip"
  22.             android:layout_marginRight="8dip"
  23.             android:scaleType="fitCenter"
  24.             android:src="@null"/>
  25.         <androidx.appcompat.widget.DialogTitle
  26.             android:id="@+id/alertTitle"
  27.             style="?android:attr/windowTitleStyle"
  28.             android:layout_width="match_parent"
  29.             android:layout_height="wrap_content"
  30.             android:layout_gravity="start"
  31.             android:ellipsize="end"
  32.             android:singleLine="true"
  33.             android:textAlignment="viewStart"/>
  34.     </LinearLayout>
  35.     <android.widget.Space
  36.         android:id="@+id/titleDividerNoCustom"
  37.         android:layout_width="match_parent"
  38.         android:layout_height="@dimen/abc_dialog_title_divider_material"
  39.         android:visibility="gone"/>
  40. </LinearLayout>
      按钮布局:
. @2 Q, x4 h: ?- L2 f' G
  1. <!-- abc_alert_dialog_button_bar_material: -->
  2. <ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
  3.             android:id="@+id/buttonPanel"
  4.             style="?attr/buttonBarStyle"
  5.             android:layout_width="match_parent"
  6.             android:layout_height="wrap_content"
  7.             android:fillViewport="true"
  8.             android:scrollIndicators="top|bottom">
  9.     <androidx.appcompat.widget.ButtonBarLayout
  10.         android:layout_width="match_parent"
  11.         android:layout_height="wrap_content"
  12.         android:gravity="bottom"
  13.         android:layoutDirection="locale"
  14.         android:orientation="horizontal"
  15.         android:paddingBottom="4dp"
  16.         android:paddingLeft="12dp"
  17.         android:paddingRight="12dp"
  18.         android:paddingTop="4dp">
  19.         <Button
  20.             android:id="@android:id/button3"
  21.             style="?attr/buttonBarNeutralButtonStyle"
  22.             android:layout_width="wrap_content"
  23.             android:layout_height="wrap_content"/>
  24.         <android.widget.Space
  25.             android:id="@+id/spacer"
  26.             android:layout_width="0dp"
  27.             android:layout_height="0dp"
  28.             android:layout_weight="1"
  29.             android:visibility="invisible"/>
  30.         <Button
  31.             android:id="@android:id/button2"
  32.             style="?attr/buttonBarNegativeButtonStyle"
  33.             android:layout_width="wrap_content"
  34.             android:layout_height="wrap_content"/>
  35.         <Button
  36.             android:id="@android:id/button1"
  37.             style="?attr/buttonBarPositiveButtonStyle"
  38.             android:layout_width="wrap_content"
  39.             android:layout_height="wrap_content"/>
  40.     </androidx.appcompat.widget.ButtonBarLayout>
  41. </ScrollView>
二、修改Dialog样式3 w' i  Q' c: \' }  u
2.1 通过findViewById
6 r3 \' E, H. Q7 P6 ?: a
  1. AlertDialog.Builder builder = new AlertDialog.Builder(this);
  2. builder.setMessage(msg);
  3. builder.setPositiveButton(getString(R.string.yes), null);
  4. AlertDialog dialog = builder.create();
  5. dialog.show();
  6. //直接通过id找到对应的控件
  7. Button button = dialog.findViewById(android.R.id.button1);
  8. //或者通过getButton方法也可以获取到
  9. Button button2 = dialog.getButton(DialogInterface.BUTTON_POSITIVE)
      这种修改方式必须在 show() 之后调用,否则会出现空指针异常。这个是因为,执行 show() 方法的时候,dialog才会初始化布局,具体源码可以查看 Dialog 的 onCreate 方法。
; P5 d5 K/ K7 }0 h% F' X2.2 自定义style0 l0 {, w0 ~; t) X6 q
       通过上面源码可以发现,Dialog三个按钮的样式如下:" }; x& P; K" w
  • buttonBarNeutralButtonStyle
  • buttonBarNegativeButtonStyle
  • buttonBarPositiveButtonStyle
    * ^! m9 B* Y: `  ^
  1. <Button
  2.     android:id="@android:id/button3"
  3.     style="?attr/buttonBarNeutralButtonStyle"
  4.     android:layout_width="wrap_content"
  5.     android:layout_height="wrap_content"/>
  6. <android.widget.Space
  7.     android:id="@+id/spacer"
  8.     android:layout_width="0dp"
  9.     android:layout_height="0dp"
  10.     android:layout_weight="1"
  11.     android:visibility="invisible"/>
  12. <Button
  13.     android:id="@android:id/button2"
  14.     style="?attr/buttonBarNegativeButtonStyle"
  15.     android:layout_width="wrap_content"
  16.     android:layout_height="wrap_content"/>
  17. <Button
  18.     android:id="@android:id/button1"
  19.     style="?attr/buttonBarPositiveButtonStyle"
  20.     android:layout_width="wrap_content"
  21.     android:layout_height="wrap_content"/>
      自定义样式替换上述 style即可达到修改效果。: v& X/ Z4 K& f4 R5 K6 f
       在style.xml添加如下代码:' W0 N5 V% R: L% P
  1. <style name="accessPositiveBtnStyle" parent="Widget.AppCompat.Button.ButtonBar.AlertDialog">
  2.     <item name="android:textColor">@color/test1</item>
  3. </style>
  4. <style name="accessNegativeBtnStyle" parent="Widget.AppCompat.Button.ButtonBar.AlertDialog">
  5.     <item name="android:textColor">@color/test2</item>
  6. </style>
  7. <!-- 弹出框样式 -->
  8. <style name="testDialogTheme" parent="Theme.AppCompat.Light.Dialog.Alert">
  9.     <item name="buttonBarPositiveButtonStyle">@style/accessPositiveBtnStyle</item>
  10.     <item name="buttonBarNegativeButtonStyle">@style/accessNegativeBtnStyle</item>
  11. </style>
      具体使用:
$ r& f9 t/ y( I& {& l
  1. AlertDialog.Builder builder = new AlertDialog.Builder(this, R.style.testDialogTheme);
  2.     builder.setMessage("Test");
  3.     builder.setCancelable(false);
  4.     builder.setPositiveButton("确认", null);
  5.     builder.setNegativeButton("取消", null);
  6.     Dialog dialog = builder.create();
  7.     dialog.show();
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|小黑屋|paopaomj.COM ( 渝ICP备18007172号 )

GMT+8, 2024-4-28 09:40

Powered by paopaomj X3.4 © 2016-2024 sitemap

快速回复 返回顶部 返回列表