Android通用UI组件之Dialog

背景

Dialog是Android开发中经常使用的UI组件,为了方便显示对话框,系统提供了AlertDialog,它提供了丰富的API,使用时只须要设置相应的属性便可。但一般状况下,不会直接使用AlertDialog, 由于APP的设计并不必定都遵循Material Design的设计标准,同时这种通用的UI组件的设计风格也会常常发生变化。因此一般状况下,都会对AlertDialog的样式进行自定义,使其可以适用于各类设计风格。java

自定义Dialog

自定义Dialog一般使用如下三种方式:android

  • 经过AlertDialog提供的setView方法设置布局;
  • 继承AlertDialog, 在onCreate中调用setContentView加载布局;
  • 继承DialogFragment, 在onCreateView中加载布局;

具体的核心代码实现以下所示:git

// 方法一
View dialogView = View.inflate(this, R.layout.dialog_common_layout, null);
/**
 * 经过dialogView.findViewById获取相应的View并设置对应的值
 */
new AlertDialog.Builder(this)
	.setView(dialogView)
	.show();


// 方法二
public class CommonDialog extends AlertDialog {

	public CommonDialog(Context context) {
		super(context);
	}
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.dialog_common_layout);
		/**
		 * 经过findViewById获取相应的View,设置对应的值
		 */
	}
}


// 方法三
public class CommonDialog extends DialogFragment {

	@Nullable
	@Override
	public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
		View dialogView = inflater.inflate(R.layout.dialog_common_layout, null);
		/**
		 * 经过dialogView.findViewById获取相应的View并设置对应的值
		 */
		return dialogView;
	}
}
复制代码

第一种和第二种方法直接使用的Dialog类型, 这种方式Dialog的生命周期很差控制,容易出现WindowManager$BadTokenException异常。因此为了Dialog的生命周期可以和Activity同步,推荐使用DialogFragment。可是在使用DialogFragment时,最好不要在onCreateView中直接加载布局,由于这种方式至关于弃用了系统提供的AlertDialog样式,若是APP要求使用系统提供的原生组件,此时修改起来可能就比较麻烦。其实DialogFragment还有一个重要的API——onCreateDialog,返回Dialog对象,因此可在里面建立AlertDialog, 根据定义的样式返回相应的风格。github

APP中使用Dialog的地方不少,但经常使用的也就那么几种:提示对话框,选择对话框,底部弹框,加载框,为了更好地进行风格切换,这里同时支持了Material Design的设计风格(系统默认的样式)和自定义的设计风格,只须要设置相应的风格便可。样式以下图所示,具体的源码参考CommonDilaogide

image

修改Dialog默认样式

在使用默认的对话框时,有时可能须要改变这几个View的颜色,但AlertDialog并无提供直接的API进行设置,经过如下方法对其中的View进行设置。布局

AlertDialog Title的样式可经过设置Dialog主题中的windowTitle属性实现:ui

<!-- Title的文字样式 -->
<style name="AlertDialogTitleStyle">
    <item name="android:textSize">48dp</item>
    <item name="android:textColor">#ff0000</item>
    <item name="android:textStyle">bold</item>
</style>

<!-- Dialog的主题样式 -->
<style name="CommonDialog" parent="Theme.AppCompat.Dialog">
    <!-- 引用定义的Title样式 -->
    <item name="android:windowTitleStyle">@style/AlertDialogTitleStyle</item>
    <item name="android:windowBackground">@color/transparent</item>
</style>
复制代码

其余的View可经过系统id进行获取:this

MessageViewId: android.R.id.message
PositiveButtonId: android.R.id.button1
NegativeButtonId: android.R.id.button2
复制代码

先调用Dialog的show方法(由于调用show方法后Dialog才开始加载布局),而后获取相应的View进行设置样式,例如MessageView样式的修改:spa

AlertDialog dialog = builder.show();
TextView messageText = dialog.findViewById(android.R.id.message);
messageText.setTextColor(Color.RED);
messageText.setTextSize(20);
复制代码

Dialog主题

在自定义Dialog时,可能须要对Dialog所使用的主题进行定义,这里介绍Dialog主题中经常使用的几个属性:设计

<style name="CommonDialog" parent="Theme.AppCompat.Dialog">
    <!-- 背景遮罩的不透明度,backgroundDimEnabled为true时有效 -->
    <item name="android:backgroundDimAmount">0.4</item>
    <!-- 是否须要背景遮罩 -->
    <item name="android:backgroundDimEnabled">true</item>
    <!-- Dialog是否悬停 -->
    <item name="android:windowIsFloating">true</item>
    <!-- dialog的最小宽度占总屏幕宽度的百分比 -->
    <item name="android:windowMinWidthMinor">85%</item>
    <!-- Dialog内容区域的背景 -->
    <item name="android:windowBackground">@color/transparent</item>
</style>
复制代码

windowBackground属性须要注意一下,若是Dialog的自定义布局中设置了背景,那么这里可将其设置为透明,不然在低版本的Android系统上会出现黑色边框。若是自定义布局中没有设置背景,可将windowBackground属性设置为相应的Drawable资源。

固然,Dialog的主题中还有不少属性。但没有对齐相关的属性。若是须要修改Dialog的对齐方式,可在show方法调用以后,获取Dialog的LayoutParams参数进行相应的设置。例如让Dialog显示在底部:

WindowManager.LayoutParams params = dialog.getWindow().getAttributes();
params.gravity = Gravity.BOTTOM;
dialog.getWindow().setAttributes(params);
复制代码

总结

在对系统UI组件进行封装时,必定要考虑原生的样式,尽量利用系统提供的组件实现。这样可在各类不一样的UI风格之间进行切换。

相关文章
相关标签/搜索