一、引子
学过Android的同学都知道,对话框的重要程度非常高,任何一款 app几乎都离不开对话框,值得庆幸的是,对话框的运用在Android中还是相对比较容易的。虽然很简单,但我在项目中还是碰到些问题,比如,如何实现自定义的对话框NegativeButton的点击效果、如何改变标题的字体大小和颜色等。

二、分析和实现
下面来看一下下面那张效果图,微信长按通讯录时弹出的对话框。

我相信,只要是有了一定Android基础的同学都能实现此功能,就算一时忘记了,稍微google下也是能做出来的;根据效果图可以看到,系统自带的alertDialog肯定无法实现这样的效果,所以得通过自定义xml来实现布局,并在AlertDialog.Builder中调用AlertDialog.Builder.setView(View view)把自定义的布局文件塞进去,代码也很简单,直接贴出来。

1、wechat_dialog.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:orientation="vertical"android:layout_width="match_parent"android:layout_height="match_parent"android:background="@color/white"><TextView
        android:id="@+id/id_name"android:layout_width="wrap_content"android:layout_height="wrap_content"android:textSize="18sp"android:text="曾文明"android:textColor="@color/bigColor"android:padding="20dp"/><View
        android:layout_width="match_parent"android:layout_height="1dp"android:background="@color/lineColor"android:layout_marginLeft="10dp"android:layout_marginRight="10dp"/><TextView
        android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="修改备注"android:padding="18dp"android:textSize="14sp"android:textColor="@color/txtColor"/>
</LinearLayout>

在MainActivity中调用

public static void showWeChatTitleDialog(Context context){AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(context) ;dialogBuilder.create() ;LayoutInflater inflater = LayoutInflater.from(context) ;View view = inflater.inflate(R.layout.wechat_dialog, null) ;dialogBuilder.setView(view) ;dialogBuilder.show() ;
}

运行效果就是上图的效果。到这里为止,不能说明任何问题,最多只能说明AlertDialog使用起来并不复杂,接下来才是重点;还是先来看一张效果图

也许你会说,这个也很简单,跟前面那张图的实现方式一样,自己写一个布局,然后通过 setView 把布局设置进去,没错,我相信很多人都是这样实现的。但是我告诉大家,这里的实现方式不是通过 setView()的方式来实现的,而是通过修改 Android 系统原生的 AlertDialog 中的控件来达到我们想要的效果。这样做的好处是什么呢?我们知道,如果是我们自己写布局文件肯定是需要为最下方的两个按钮设置点击事件,这样代码量就非常大;而 AlertDialog 的NegativeButton和PositiveButton已经为我们提供了点击事件的接口,使用起来非常简单。
先来看看如何修改NegativeButton的字体颜色?
1、毫无疑问第一步我们先要获取Button,在 AlertDialog 中有这样一个方法

public Button getButton(int whichButton) {return mAlert.getButton(whichButton);
}

所以 可以通过以下代码获取

Button mNegativeButton = mAlertDialog.getButton(AlertDialog.BUTTON_NEGATIVE) ;

2、设置Button的字体颜色为绿色,同时也可以设置点击状态

mNegativeButton.setTextColor(0xff45c01a);
mNegativeButton.setBackgroundResource(R.drawable.button_selector);

Button的效果已经实现了,同理另一个按钮也可以实现,再来看看 title 的字体颜色, 当然也希望能像获取 Button 一样,获取 title,进入 AlertDialog.java找啊,找啊,结果翻了个底朝天,硬是没有这样的方法。那怎么办?这时候就需要用到 Resources下的一个方法

    public int getIdentifier(String name, String defType, String defPackage) {if (name == null) {throw new NullPointerException("name is null");}try {return Integer.parseInt(name);} catch (Exception e) {// Ignore}return mAssets.getResourceIdentifier(name, defType, defPackage);}

这个方法的作用是什么呢?根据方法名可知,获取 Identifier,就是获取识别码,也就是代码中唯一的 Id。那这个方法的三个参数又分别代表什么东西呢?
name:资源文件中所需要操作的名称
defType:资源文件中操作的类型
defPackage:资源文件所在的包名
这样说比较难理解,还是举个例子,如果 defType 类型为 id,那么 name 就是android:id=”@+id/id_title”中的id_title
接下来就来看看怎么通过这个方法获取 alertDialog 的 title
1、获取 AlertDialog 中的 title

final int titleId = mContext.getResources().getIdentifier("alertTitle","id","android") ;TextView titleTxt = (TextView) mAlertDialog.findViewById(titleId);

“alertTitle”为系统alert_dialog.xml布局文件中title控件的 id 名称android:id=”@+id/alertTitle”,”id”代表获取的是 id,”android”为系统包名

2、设置 title 的字体颜色为绿色

titleTxt.setTextColor(0xff45c01a);

既然拿到了 title 的 View,就可以随心所欲的根据我们需求来设置效果。
再来看看这条绿色的线条和中间内容区域的设置

        final int titleDivider = mContext.getResources().getIdentifier("titleDivider","id","android") ;View titleDividerImg =  mAlertDialog.findViewById(titleDivider);titleDividerImg.setVisibility(View.VISIBLE);
titleDividerImg.setBackgroundColor(0xff45c01a);final int contentPanel = mContext.getResources().getIdentifier("contentPanel","id","android") ;LinearLayout contentPanelLayout = (LinearLayout) mAlertDialog.findViewById(contentPanel);contentPanelLayout.setVisibility(View.VISIBLE);final int message = mContext.getResources().getIdentifier("message","id","android") ;TextView messageTextView = (TextView) mAlertDialog.findViewById(message);messageTextView.setTextSize(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,20,mContext.getResources().getDisplayMetrics()));messageTextView.setPadding(20,20,20,20);messageTextView.setVisibility(View.VISIBLE);

我们回到获取NegativeButton的代码中,其实既然 title 和 titleDivider能通过getIdentifier获取,button 同样能通过getIdentifier来获取,具体实现代码如下:

        final int button1 = mContext.getResources().getIdentifier("button1","id","android") ;Button negativeButton = (Button) mAlertDialog.findViewById(button1);negativeButton.setBackgroundResource(R.drawable.button_selector);negativeButton.setVisibility(View.VISIBLE);negativeButton.setTextColor(0xff45c01a);final int button2 = mContext.getResources().getIdentifier("button2","id","android") ;Button positiveButton = (Button) mAlertDialog.findViewById(button2);positiveButton.setBackgroundResource(R.drawable.button_selector);positiveButton.setVisibility(View.VISIBLE);positiveButton.setTextColor(0xff45c01a);

可以看到,第二张效果图,完全是使用的系统自带的对话框布局实现。
三、归纳
可以看到整篇文章的核心就是

public int getIdentifier(String name, String defType, String defPackage)

掌握了这个方法,对于修改 AlertDialog 就不在话下,当然此方法的用处在这里只能算的上是冰上一脚。
需要对 AlertDialog 的各个控件熟练运用就必须知道系统的alert_dialog.xml定义了那些 View,alert_dialog.xml的路径是
//device/apps/common/res/layout/alert_dialog.xml。
四、alert_dialog.xml的源码

<?xml version="1.0" encoding="utf-8"?><!--
*//* //device/apps/common/res/layout/alert_dialog.xml
**
** Copyright 2006, 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:id="@+id/parentPanel"android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="vertical"android:paddingTop="9dip"android:paddingBottom="3dip"android:paddingStart="3dip"android:paddingEnd="1dip"><LinearLayout android:id="@+id/topPanel"android:layout_width="match_parent"android:layout_height="wrap_content"android:minHeight="54dip"android:orientation="vertical"><LinearLayout android:id="@+id/title_template"android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal"android:gravity="center_vertical"android:layout_marginTop="6dip"android:layout_marginBottom="9dip"android:layout_marginStart="10dip"android:layout_marginEnd="10dip"><ImageView android:id="@+id/icon"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="top"android:paddingTop="6dip"android:paddingEnd="10dip"android:src="@drawable/ic_dialog_info" /><com.android.internal.widget.DialogTitle android:id="@+id/alertTitle"style="?android:attr/textAppearanceLarge"android:singleLine="true"android:ellipsize="end"android:layout_width="match_parent"android:layout_height="wrap_content"android:textAlignment="viewStart" /></LinearLayout><ImageView android:id="@+id/titleDivider"android:layout_width="match_parent"android:layout_height="1dip"android:visibility="gone"android:scaleType="fitXY"android:gravity="fill_horizontal"android:src="@android:drawable/divider_horizontal_dark" /><!-- If the client uses a customTitle, it will be added here. --></LinearLayout><LinearLayout android:id="@+id/contentPanel"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_weight="1"android:orientation="vertical"><ScrollView android:id="@+id/scrollView"android:layout_width="match_parent"android:layout_height="wrap_content"android:paddingTop="2dip"android:paddingBottom="12dip"android:paddingStart="14dip"android:paddingEnd="10dip"android:overScrollMode="ifContentScrolls"><TextView android:id="@+id/message"style="?android:attr/textAppearanceMedium"android:layout_width="match_parent"android:layout_height="wrap_content"android:padding="5dip" /></ScrollView></LinearLayout><FrameLayout android:id="@+id/customPanel"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_weight="1"><FrameLayout android:id="@+android:id/custom"android:layout_width="match_parent"android:layout_height="wrap_content"android:paddingTop="5dip"android:paddingBottom="5dip" /></FrameLayout><LinearLayout android:id="@+id/buttonPanel"android:layout_width="match_parent"android:layout_height="wrap_content"android:minHeight="54dip"android:orientation="vertical" ><LinearLayout
    style="?android:attr/buttonBarStyle"android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal"android:paddingTop="4dip"android:paddingStart="2dip"android:paddingEnd="2dip"android:measureWithLargestChild="true"><LinearLayout android:id="@+id/leftSpacer"android:layout_weight="0.25"android:layout_width="0dip"android:layout_height="wrap_content"android:orientation="horizontal"android:visibility="gone" /><Button android:id="@+id/button1"android:layout_width="0dip"android:layout_gravity="start"android:layout_weight="1"style="?android:attr/buttonBarButtonStyle"android:maxLines="2"android:layout_height="wrap_content" /><Button android:id="@+id/button3"android:layout_width="0dip"android:layout_gravity="center_horizontal"android:layout_weight="1"style="?android:attr/buttonBarButtonStyle"android:maxLines="2"android:layout_height="wrap_content" /><Button android:id="@+id/button2"android:layout_width="0dip"android:layout_gravity="end"android:layout_weight="1"style="?android:attr/buttonBarButtonStyle"android:maxLines="2"android:layout_height="wrap_content" /><LinearLayout android:id="@+id/rightSpacer"android:layout_width="0dip"android:layout_weight="0.25"android:layout_height="wrap_content"android:orientation="horizontal"android:visibility="gone" /></LinearLayout></LinearLayout></LinearLayout>

源码下载地址:AlertDialog通过自带的布局实现自定义的风格

Android AlertDialog对话框自定义风格的另类实现相关推荐

  1. Android AlertDialog 对话框开启和关闭输入法问题

    Android AlertDialog 对话框开启和关闭输入法问题 AlertDialog 对话框是android jar包自带的对话框,说实话 真的很丑,黑白相间,不是很推荐使用.大多时候 特别是项 ...

  2. 一对一视频聊天软件源码,Android AlertDialog 对话框

    一对一视频聊天软件源码,Android AlertDialog 对话框实现的相关代码 button = (Button) findViewById(R.id.button_alertDialog);b ...

  3. Android AlertDialog对话框不能阻塞进程

    因为AlertDialog对话框不能阻塞当前进程,如果在对话框后,有继续运行的代码,或有切换界面的代码,对话框会一闪而过,不等用户选择. 正确的做法应该是: if (条件){ AlertDialog ...

  4. android AlertDialog 对话框的基本使用

    /** * @setIcon 设置对话框图标 * @setTitle 设置对话框标题 * @setMessage 设置对话框消息提示 * setXXX方法返回Dialog对象,因此可以链式设置属性 * ...

  5. 如何在android中创建自定义对话框?

    本文翻译自:How to create a Custom Dialog box in android? I want to create a custom dialog box like below ...

  6. 【Android】对话框 AlertDialog

    [Android]对话框 AlertDialog 本讲介绍一下Android基本组件:对话框AlertDialog. 来源:http://blog.csdn.net/feng88724/article ...

  7. Android笔记之自定义对话框

    效果如下图 对话框布局 dialog_uninstallation_confirmation.xml <?xml version="1.0" encoding="u ...

  8. Android基础入门教程——2.5.3 AlertDialog(对话框)详解

    Android基础入门教程--2.5.3 AlertDialog(对话框)详解 标签(空格分隔): Android基础入门教程 本节引言: 本节继续给大家带来是显示提示信息的第三个控件AlertDia ...

  9. 【Android 常见控件使用】AlertDialog(对话框)详解

    文章目录 AlertDialog(对话框)详解 本节引言 1.基本使用流程 2.几种常用的对话框使用示例 3.通过Builder的setView()定制显示的AlertDialog AlertDial ...

最新文章

  1. ICinsights:中国芯片难达成既定的2025目标
  2. CStringArray序列化处理
  3. linux内存管理策略,Glibc内存管理—ptmalloc内存分配策略(1)
  4. linux帮助命令和用法,Linux命令帮助及history命令的使用
  5. 模板引擎工作原理_广州seo了解下搜索引擎的工作原理是什么
  6. 2018江苏冬令营5 交换矩阵
  7. windows server 2008r2 如何隐藏iis版本号_如何拥有自己炫酷的个人博客
  8. sitck-breaking折棍法理解
  9. vs2017 html安装,解决vs2017无法安装问题
  10. python代理IP的使用
  11. incaseformat蠕虫病毒样本分析
  12. 往事如烟随风,切如梦初醒
  13. 不同数据类型与Json之间的转换
  14. ion orphaned memory
  15. 海思SDK学习(10)海思媒体处理软件平台MMP(9)AUDIO音频
  16. 几种你不知道的获取浙A牌照的方法
  17. 2020年ICPC辽宁省赛- 最长回文串(Java)
  18. photoshop 人物修容的大体步骤
  19. 搞 AI 建模预测都在用 Python,其实入门用 SPL 也不错
  20. python class tynu()_Pisanie pierwszej aplikacji Django, część 4.

热门文章

  1. 【错误】SpringBoot启动网页显示“Please sign in”的解决方案
  2. 测试指令和位测试指令的用法-TEST
  3. ORACLE(SQL基础)
  4. 【C++】第二章 数据类型:整型/sizeof关键字/实型(浮点型)/ 字符型/转义字符/字符串型 /布尔类型/数据的输入
  5. 解决Oracle Temp01.dbf文件过大
  6. GUI之place布局
  7. win10_3D画图软件文字粘贴时的BUG解决
  8. python实现矩阵转化图像
  9. java 链表 深拷贝_单链表深拷贝的实现
  10. 类型转换函数(atof(),atoi(),atol())