QQ登录

只需要一步,快速开始

APP扫码登录

只需要一步,快速开始

手机号码,快捷登录

手机号码,快捷登录

查看: 4392|回复: 0

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

[复制链接]

等级头衔

积分成就    金币 : 2857
   泡泡 : 1516
   精华 : 6
   在线时间 : 1313 小时
   最后登录 : 2025-1-17

丰功伟绩

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

联系方式
发表于 2021-5-24 11:02:43 | 显示全部楼层 |阅读模式
       Android 对话框支持自定义标题,内容,按钮和点击事件,基本上可以满足我们日常的使用。 但有时候我们想要修改对话框的文字,按钮颜色等,系统并没有提供对应的方法,正常情况下只能自定义布局。 接下来通过源码解析介绍几种修改 Dialog样式的方法。8 q( V. w2 [6 E
一、Dialog源码解析
% w5 p1 m1 s+ Q+ Q7 ]2 V) W1.1 new AlertDialog.Builder(this).create()
: F* c' _* q8 Z% w1 ~# K
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
    ) `& s( z4 }- U
1.2 AlertController
* b: V7 o' f( T) q
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 是对话框的默认样式3 i1 u& \$ ]6 G+ }6 r) C
<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的默认布局。- y' e. X3 D; ?
<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>
      标题布局:' q8 k9 l6 f& k7 r% F; \# d  I: |! b
<!-- 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>
      按钮布局:+ c4 G& V( [2 Z" l: u$ O
<!-- 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样式
/ r. W9 z- N+ ?2.1 通过findViewById& p9 t8 h# x; F7 u0 h
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 方法。$ [: [% Y3 F! m5 R
2.2 自定义style
7 n8 i2 I! f. O5 X/ n4 [       通过上面源码可以发现,Dialog三个按钮的样式如下:
- y. J" p& G- T4 |# Q
  • buttonBarNeutralButtonStyle
  • buttonBarNegativeButtonStyle
  • buttonBarPositiveButtonStyle) `6 x) N) i1 Z. p
<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即可达到修改效果。
- ?/ _% K5 z; Y6 G! P& ^       在style.xml添加如下代码:# m- H' k& x7 E# m, R! B
<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>
      具体使用:% d. I& [9 h: F& l; X
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, 2025-1-18 14:54

Powered by paopaomj X3.5 © 2016-2025 sitemap

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