QQ登录

只需要一步,快速开始

APP扫码登录

只需要一步,快速开始

手机号码,快捷登录

手机号码,快捷登录

查看: 4342|回复: 0

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

[复制链接]

等级头衔

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

丰功伟绩

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

联系方式
发表于 2021-5-24 11:02:43 | 显示全部楼层 |阅读模式
       Android 对话框支持自定义标题,内容,按钮和点击事件,基本上可以满足我们日常的使用。 但有时候我们想要修改对话框的文字,按钮颜色等,系统并没有提供对应的方法,正常情况下只能自定义布局。 接下来通过源码解析介绍几种修改 Dialog样式的方法。  H5 H+ z; i3 l# x- p5 a/ b
一、Dialog源码解析
% ]2 V/ U+ x+ M. I2 S. B+ h8 Q1.1 new AlertDialog.Builder(this).create()0 q& l, O- a$ @; `7 M- T
protected AlertDialog(@NonNull Context context, @StyleRes int themeResId) {
        super(context, resolveDialogTheme(context, themeResId));
        //创建AlertController,是Dialog布局相关代码
        mAlert = new AlertController(getContext(), this, getWindow());
    }

        @NonNull
        public AlertDialog create() {
            // We can't use Dialog's 3-arg constructor with the createThemeContextWrapper param,
            // so we always have to re-set the theme
            final AlertDialog dialog = new AlertDialog(P.mContext, mTheme);
            P.apply(dialog.mAlert);
            dialog.setCancelable(P.mCancelable);
            if (P.mCancelable) {
                dialog.setCanceledOnTouchOutside(true);
            }
            dialog.setOnCancelListener(P.mOnCancelListener);
            dialog.setOnDismissListener(P.mOnDismissListener);
            if (P.mOnKeyListener != null) {
                dialog.setOnKeyListener(P.mOnKeyListener);
            }
            return dialog;
        }

        public void apply(AlertController dialog) {
            if (mCustomTitleView != null) {
                dialog.setCustomTitle(mCustomTitleView);
            } else {
                if (mTitle != null) {
                    dialog.setTitle(mTitle);
                }
                if (mIcon != null) {
                    dialog.setIcon(mIcon);
                }
                if (mIconId != 0) {
                    dialog.setIcon(mIconId);
                }
            ..........
  • AlertDialog 构造函数中会创建 AlertController,用来控制对话框的布局
  • P.apply(dialog.mAlert); 将用户自定义的配置赋值给 AlertController
    : v* s1 {5 G5 k7 A7 a( l
1.2 AlertController: G5 I) t6 I! y* q/ U2 x
public AlertController(Context context, AppCompatDialog di, Window window) {
        mContext = context;
        mDialog = di;
        mWindow = window;
        mHandler = new ButtonHandler(di);

        final TypedArray a = context.obtainStyledAttributes(null, R.styleable.AlertDialog,
                R.attr.alertDialogStyle, 0);

        mAlertDialogLayout = a.getResourceId(R.styleable.AlertDialog_android_layout, 0);
        mButtonPanelSideLayout = a.getResourceId(R.styleable.AlertDialog_buttonPanelSideLayout, 0);

        mListLayout = a.getResourceId(R.styleable.AlertDialog_listLayout, 0);
        mMultiChoiceItemLayout = a.getResourceId(R.styleable.AlertDialog_multiChoiceItemLayout, 0);
        mSingleChoiceItemLayout = a
                .getResourceId(R.styleable.AlertDialog_singleChoiceItemLayout, 0);
        mListItemLayout = a.getResourceId(R.styleable.AlertDialog_listItemLayout, 0);
        mShowTitle = a.getBoolean(R.styleable.AlertDialog_showTitle, true);
        mButtonIconDimen = a.getDimensionPixelSize(R.styleable.AlertDialog_buttonIconDimen, 0);

        a.recycle();

        /* We use a custom title so never request a window title */
        di.supportRequestWindowFeature(Window.FEATURE_NO_TITLE);
    }
      R.attr.alertDialogStyle 是对话框的默认样式  G9 M1 x% p# ]
<item name="alertDialogStyle">@style/AlertDialog.AppCompat</item>
        <style name="AlertDialog.AppCompat" parent="Base.AlertDialog.AppCompat"/>
              <style name="Base.AlertDialog.AppCompat" parent="android:Widget">
                <item name="android:layout">@layout/abc_alert_dialog_material</item>
                <item name="listLayout">@layout/abc_select_dialog_material</item>
                        <item name="listItemLayout">@layout/select_dialog_item_material</item>
                <item name="multiChoiceItemLayout">@layout/select_dialog_multichoice_material</item>
                <item name="singleChoiceItemLayout">@layout/select_dialog_singlechoice_material</item>
                <item name="buttonIconDimen">@dimen/abc_alert_dialog_button_dimen</item>
            </style>
      上述代码可以看出,abc_alert_dialog_material 就是dialog的默认布局。
9 W' [6 Z7 L5 h# E6 Z4 Z
<androidx.appcompat.widget.AlertDialogLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/parentPanel"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:gravity="start|left|top"
    android:orientation="vertical">

    <include layout="@layout/abc_alert_dialog_title_material"/>

    <FrameLayout
        android:id="@+id/contentPanel"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:minHeight="48dp">

        <View android:id="@+id/scrollIndicatorUp"
              android:layout_width="match_parent"
              android:layout_height="1dp"
              android:layout_gravity="top"
              android:background="?attr/colorControlHighlight"
              android:visibility="gone"/>

        <androidx.core.widget.NestedScrollView
            android:id="@+id/scrollView"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:clipToPadding="false">

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="vertical">

                <android.widget.Space
                    android:id="@+id/textSpacerNoTitle"
                    android:layout_width="match_parent"
                    android:layout_height="@dimen/abc_dialog_padding_top_material"
                    android:visibility="gone"/>

                <TextView
                    android:id="@android:id/message"
                    style="@style/TextAppearance.AppCompat.Subhead"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:paddingLeft="?attr/dialogPreferredPadding"
                    android:paddingRight="?attr/dialogPreferredPadding"/>

                <android.widget.Space
                    android:id="@+id/textSpacerNoButtons"
                    android:layout_width="match_parent"
                    android:layout_height="@dimen/abc_dialog_padding_top_material"
                    android:visibility="gone"/>
            </LinearLayout>
        </androidx.core.widget.NestedScrollView>

        <View android:id="@+id/scrollIndicatorDown"
              android:layout_width="match_parent"
              android:layout_height="1dp"
              android:layout_gravity="bottom"
              android:background="?attr/colorControlHighlight"
              android:visibility="gone"/>

    </FrameLayout>

    <FrameLayout
        android:id="@+id/customPanel"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:minHeight="48dp">

        <FrameLayout
            android:id="@+id/custom"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"/>
    </FrameLayout>

    <include layout="@layout/abc_alert_dialog_button_bar_material"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"/>

</androidx.appcompat.widget.AlertDialogLayout>
      标题布局:) W0 s5 `; v! l. @  k, v8 y! o
<!-- abc_alert_dialog_title_material: -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:id="@+id/topPanel"
              android:layout_width="match_parent"
              android:layout_height="wrap_content"
              android:orientation="vertical">

    <!-- If the client uses a customTitle, it will be added here. -->

    <LinearLayout
        android:id="@+id/title_template"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center_vertical|start|left"
        android:orientation="horizontal"
        android:paddingLeft="?attr/dialogPreferredPadding"
        android:paddingRight="?attr/dialogPreferredPadding"
        android:paddingTop="@dimen/abc_dialog_padding_top_material">

        <ImageView
            android:id="@android:id/icon"
            android:layout_width="32dip"
            android:layout_height="32dip"
            android:layout_marginEnd="8dip"
            android:layout_marginRight="8dip"
            android:scaleType="fitCenter"
            android:src="@null"/>

        <androidx.appcompat.widget.DialogTitle
            android:id="@+id/alertTitle"
            style="?android:attr/windowTitleStyle"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="start"
            android:ellipsize="end"
            android:singleLine="true"
            android:textAlignment="viewStart"/>

    </LinearLayout>

    <android.widget.Space
        android:id="@+id/titleDividerNoCustom"
        android:layout_width="match_parent"
        android:layout_height="@dimen/abc_dialog_title_divider_material"
        android:visibility="gone"/>
</LinearLayout>
      按钮布局:7 j: v) Z2 M/ b6 z& U9 Z
<!-- abc_alert_dialog_button_bar_material: -->
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
            android:id="@+id/buttonPanel"
            style="?attr/buttonBarStyle"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:fillViewport="true"
            android:scrollIndicators="top|bottom">

    <androidx.appcompat.widget.ButtonBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="bottom"
        android:layoutDirection="locale"
        android:orientation="horizontal"
        android:paddingBottom="4dp"
        android:paddingLeft="12dp"
        android:paddingRight="12dp"
        android:paddingTop="4dp">

        <Button
            android:id="@android:id/button3"
            style="?attr/buttonBarNeutralButtonStyle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>

        <android.widget.Space
            android:id="@+id/spacer"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:visibility="invisible"/>

        <Button
            android:id="@android:id/button2"
            style="?attr/buttonBarNegativeButtonStyle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>

        <Button
            android:id="@android:id/button1"
            style="?attr/buttonBarPositiveButtonStyle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>

    </androidx.appcompat.widget.ButtonBarLayout>

</ScrollView>
二、修改Dialog样式
/ p4 s/ E* N: [1 ^9 v3 i( a3 B2.1 通过findViewById
% |1 H" d. o% L/ g4 e. l& t
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage(msg);
builder.setPositiveButton(getString(R.string.yes), null);
AlertDialog dialog = builder.create();
dialog.show();
 //直接通过id找到对应的控件
Button button = dialog.findViewById(android.R.id.button1);
 //或者通过getButton方法也可以获取到
 Button button2 = dialog.getButton(DialogInterface.BUTTON_POSITIVE)
      这种修改方式必须在 show() 之后调用,否则会出现空指针异常。这个是因为,执行 show() 方法的时候,dialog才会初始化布局,具体源码可以查看 Dialog 的 onCreate 方法。
7 n+ p& Z. r3 Z9 p. n0 Q1 \# T2.2 自定义style
* z5 m. l8 W3 ~       通过上面源码可以发现,Dialog三个按钮的样式如下:5 ?; i3 {0 o. K4 ]4 ?
  • buttonBarNeutralButtonStyle
  • buttonBarNegativeButtonStyle
  • buttonBarPositiveButtonStyle2 b; x4 N! `3 b, ]$ ^  p2 q
<Button
    android:id="@android:id/button3"
    style="?attr/buttonBarNeutralButtonStyle"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"/>
 
<android.widget.Space
    android:id="@+id/spacer"
    android:layout_width="0dp"
    android:layout_height="0dp"
    android:layout_weight="1"
    android:visibility="invisible"/>
 
<Button
    android:id="@android:id/button2"
    style="?attr/buttonBarNegativeButtonStyle"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"/>
 
<Button
    android:id="@android:id/button1"
    style="?attr/buttonBarPositiveButtonStyle"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"/>
      自定义样式替换上述 style即可达到修改效果。  N! n8 A* L$ G3 H% }' W. a9 x
       在style.xml添加如下代码:
7 A% F/ A# E, \" ~8 H: ]( s: s- m& \
<style name="accessPositiveBtnStyle" parent="Widget.AppCompat.Button.ButtonBar.AlertDialog">
    <item name="android:textColor">@color/test1</item>
</style>
 
<style name="accessNegativeBtnStyle" parent="Widget.AppCompat.Button.ButtonBar.AlertDialog">
    <item name="android:textColor">@color/test2</item>
</style>
 
<!-- 弹出框样式 -->
<style name="testDialogTheme" parent="Theme.AppCompat.Light.Dialog.Alert">
    <item name="buttonBarPositiveButtonStyle">@style/accessPositiveBtnStyle</item>
    <item name="buttonBarNegativeButtonStyle">@style/accessNegativeBtnStyle</item>
</style>
      具体使用:
: u$ i% G6 x# a; S8 J
AlertDialog.Builder builder = new AlertDialog.Builder(this, R.style.testDialogTheme);
    builder.setMessage("Test");
    builder.setCancelable(false);
    builder.setPositiveButton("确认", null);
    builder.setNegativeButton("取消", null);
    Dialog dialog = builder.create();
    dialog.show();
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2024-12-4 05:26

Powered by paopaomj X3.5 © 2016-2025 sitemap

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