Android Dialog相关
一、Dialog
Android弹窗在应用中是经常出现的一个组件,当系统需要弹出一个消息和提示的时候就需要用到一个弹窗进行提示。首先了解一下什么是弹窗
android官方文档对Dialog的介绍
A dialog is a small window that prompts the user to make a decision or enter additional information. A dialog does not fill the screen and is normally used for modal events that require users to take an action before they can proceed.
dialog就是一个在屏幕上弹出一个可以让用户做出一个选择,或者输入额外的信息的对话框,一个对话框并不会沾满我们整个的屏幕,并且通常用于模型事件当中需要用户做出一个决定后才会继续执行。
Dialog类是dialog对话框的基类,但是我们应该避免直接使用这个类来实例化一个dialog对话框,我们应当使用其子类来得到一个对话框:
java.lang.Object
↳ android.app.Dialog
Known Direct Subclasses
AlertDialog, CharacterPickerDialog, MediaRouteChooserDialog, MediaRouteControllerDialog, Presentation
Known Indirect Subclasses
DatePickerDialog, ProgressDialog, TimePickerDialog
以上Dialog的子类对应的是不同功能的弹窗,可以根据自己的需要进行选择使用,比如DatePickerDialog可以调用系统自带的时间选择弹窗,选择自己需要的样式进行显示,选择时间后可以对选择的日期进行操作。其他的弹窗也是一样的用法。
二、自定义Dialog
有时候可能自带的Dialog并不能满足特定的样式需求,这时候就可以进行自定义Dialog,通过继承Dialog基类进行自定义。
固定样式的弹窗
下面以一个简单的弹窗样式进行自定义操作:
public class NoticeDialog extends Dialog implements View.OnClickListener {
private TextView mTvTitle;
private TextView mTvContent;
private Button mBtnCancel;
private Button mBtnConfirm;
private Button mBtnConfirmCenter;
private String title;
private String content;
private String cancel;
private String confirm;
private int dialogType;
/**
* 弹窗类型为有确认和取消按钮
*/
public static final int NOTICE_DIALOG = 0;
/**
* 弹窗类型为只有确认按钮,用于清除缓存成功提示弹窗
*/
public static final int CONFIRM_DIALOG = 1;
private OnCancelClickListener cancelClickListener;
private OnConfirmClickListener confirmClickListener;
public interface OnConfirmClickListener {
/**
* 点击确认按钮
*/
void onConfirmClick();
}
public interface OnCancelClickListener {
/**
* 点击取消按钮
*/
void onCancelClick();
}
public void setOnCancelClickListener(OnCancelClickListener cancelClickListener) {
this.cancelClickListener = cancelClickListener;
}
public void setOnConfirmClickListener(OnConfirmClickListener confirmClickListener) {
this.confirmClickListener = confirmClickListener;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate (savedInstanceState);
setContentView (R.layout.app_layout_notice_dialog);
initView ();
initData ();
}
public NoticeDialog(@NonNull Context context) {
super (context, R.style.CustomDialog);
}
public NoticeDialog(@NonNull Context context,String title, String content, String cancel, String confirm, int dialogType) {
super (context, R.style.CustomDialog);
this.title = title;
this.content = content;
this.cancel = cancel;
this.confirm = confirm;
this.dialogType = dialogType;
}
private void initView() {
mTvTitle = findViewById (R.id.tv_dialog_title);
mTvContent = findViewById (R.id.tv_dialog_content);
mBtnCancel = findViewById (R.id.btn_dialog_cancel);
mBtnCancel.setOnClickListener (this);
mBtnConfirm = findViewById (R.id.btn_dialog_confirm);
mBtnConfirm.setOnClickListener (this);
mBtnConfirmCenter = findViewById (R.id.btn_dialog_confirm_center);
mBtnConfirmCenter.setOnClickListener (this);
if(dialogType == CONFIRM_DIALOG) {
mBtnConfirmCenter.setVisibility (View.VISIBLE);
} else if(dialogType == NOTICE_DIALOG) {
mBtnConfirmCenter.setVisibility (View.INVISIBLE);
}
}
private void initData() {
mTvTitle.setText (title);
mTvContent.setText (content);
mBtnCancel.setText (cancel);
mBtnConfirm.setText (confirm);
mBtnConfirmCenter.setText (confirm);
}
@Override
public void onClick(View v) {
switch (v.getId ()) {
case R.id.btn_dialog_cancel:
if(cancelClickListener != null) {
cancelClickListener.onCancelClick ();
}
break;
case R.id.btn_dialog_confirm:
if(confirmClickListener != null) {
confirmClickListener.onConfirmClick ();
}
break;
case R.id.btn_dialog_confirm_center:
cancel ();
break;
default:
break;
}
}
/**
* 设置弹窗的显示内容
*
* @param title
* @param content
* @param cancel
* @param confirm
*/
public void setDialog(String title, String content, String cancel, String confirm, int dialogType) {
this.title = title;
this.content = content;
this.cancel = cancel;
this.confirm = confirm;
this.dialogType = dialogType;
}
public static void showDialog(Context context,String title, String content, String cancel, String confirm, int dialogType){
NoticeDialog dialog = new NoticeDialog (context,title,content,cancel,confirm,dialogType);
dialog.show ();
}
}
这个样式的弹窗支持自定义弹窗上面显示的文字和确定的样式,自定义Dialog的style代码:
<!--自定义Dialog-->
<style name="CustomDialog" parent="android:style/Theme.Dialog">
<!--背景颜色及和透明程度-->
<item name="android:windowBackground">@android:color/transparent</item>
<!--是否去除标题 -->
<item name="android:windowNoTitle">true</item>
<!--是否去除边框-->
<item name="android:windowFrame">@null</item>
<!--是否浮现在activity之上-->
<item name="android:windowIsFloating">true</item>
<!--是否模糊-->
<item name="android:backgroundDimEnabled">true</item>
</style>
使用起来也十分方便
if(dialog == null) {
dialog = new NoticeDialog (context);
dialog.setDialog ("提示信息", "您的账号在其他地方登录,若不是您本人操作,请及时修改密码", "取消", "登录", NoticeDialog.NOTICE_DIALOG);
dialog.setOnConfirmClickListener (new NoticeDialog.OnConfirmClickListener () {
@Override
public void onConfirmClick() {
ActivityController.finishAll ();
MemoryData.getInstance ().getUserInterface ().startLoginActivity (context);
dialog.cancel ();
}
});
dialog.setOnCancelClickListener (new NoticeDialog.OnCancelClickListener () {
@Override
public void onCancelClick() {
ActivityController.finishAll ();
BackgroundService.getInstance ().stopService ();
dialog.cancel ();
}
});
dialog.setCanceledOnTouchOutside (false);
dialog.show ();
}
三、DialogFragment的使用
1.什么是DialogFragment?
DialogFragment在android 3.0时被引入。是一种特殊的Fragment,用于在Activity的内容之上展示一个模态的对话框。典型的用于:展示警告框,输入框,确认框等等。在DialogFragment产生之前,我们创建对话框一般采用AlertDialog和Dialog。注:官方不推荐直接使用Dialog创建对话框。
- DialogFragment 本身是 Fragment 的子类,有着和 Fragment 基本一样的生命周期,使用 DialogFragment 来管理对话框,当旋转屏幕和按下后退键的时候可以更好的管理其生命周期
- 在手机配置变化导致 Activity 需要重新创建时,例如旋转屏幕,基于 DialogFragment 的对话框将会由 FragmentManager 自动重建,然而基于 Dialog 实现的对话框却没有这样的能力
2.DialogFragment 的使用
使用 DialogFragment 至少需要实现 onCreateView() 或者 onCreateDialog() 方法,onCreateView() 即使用自定义的 xml 布局文件来展示 Dialog,而 onCreateDialog() 即使用 AlertDialog 或者 Dialog 创建出 我们想要的 Dialog。其生命周期为
- onCreateDialog()->onActivityCreated()->onDestroyView()
public class MyDialogFragment extends DialogFragment {
private static MyDialogFragment mMyDialog;
public static MyDialogFragment newInstance() {
if(mMyDialog== null) {
mMyDialog= new MyDialogFragment ();
}
return mMyDialog;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate (savedInstanceState);
setCancelable (true);
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
Dialog dialog = new Dialog (getActivity (), R.style.PopupDialog);
dialog.setCanceledOnTouchOutside (true);
dialog.requestWindowFeature (Window.FEATURE_NO_TITLE);
dialog.setContentView (R.layout.dialog_history_filter);
Window window = dialog.getWindow ();
WindowManager.LayoutParams params = window.getAttributes ();
params.width = WindowManager.LayoutParams.MATCH_PARENT;
params.height = WindowManager.LayoutParams.WRAP_CONTENT;
params.gravity = Gravity.TOP;
window.setAttributes (params);
return dialog;
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
View dialogView = inflater.inflate (R.layout.dialog_history_filter, container, false);
return dialogView;
}
@Override
public void onStart() {
super.onStart ();
}
@Override
public void onDestroyView() {
super.onDestroyView ();
unbinder.unbind ();
}
@Override
public void onDismiss(DialogInterface dialog) {
super.onDismiss (dialog);
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState (outState);
}
}
在要显示的地方使用方法
MyDialogFragment myDialog = MyDialogFragment .newInstance();
myDialog .show (getFragmentManager (), MyDialogFragment .class.getName ());
四、悬浮框PopupWindow
使用
//准备PopupWindow的布局View
View popupView = LayoutInflater.from(this).inflate(R.layout.popup, null);
//初始化一个PopupWindow,width和height都是WRAP_CONTENT
PopupWindow popupWindow = new PopupWindow(
ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
//设置PopupWindow的视图内容
popupWindow.setContentView(popupView);
//点击空白区域PopupWindow消失,这里必须先设置setBackgroundDrawable,否则点击无反应
popupWindow.setBackgroundDrawable(new ColorDrawable(0x00000000));
popupWindow.setOutsideTouchable(true);
//设置PopupWindow动画
popupWindow.setAnimationStyle(R.style.AnimDown);
//设置是否允许PopupWindow的范围超过屏幕范围
popupWindow.setClippingEnabled(true);
//设置PopupWindow消失监听
popupWindow.setOnDismissListener(new PopupWindow.OnDismissListener() {
@Override
public void onDismiss() {
}
});
//PopupWindow在targetView下方弹出
popupWindow.showAsDropDown(targetView);