android 对话框(Dialog)使用
android 对话框(Dialog)使用
参考:
对话框:https://developer.android.com/guide/topics/ui/dialogs.html
使用 AlertDialog
类进行对话框的基本功能创建:
AlertDialog:https://developer.android.com/reference/android/app/AlertDialog.html
通过扩展 DialogFragment
可以自定义更多的功能:
DialogFragment:https://developer.android.com/reference/android/support/v4/app/DialogFragment.html
实现功能:
- 基本对话框(标题,图标,内容和选择按钮);
setCanceledOnTouchOutside
和setCancelable
的使用方法;- 扩展
DialogFragment
; - 添加列表(传统单选列表,永久性单选列表(单选按钮),永久性多选列表(复选框));
- 自定义布局
- 将事件传递回对话框的宿主(通过接口);
onDismiss()
和onCancel()
的使用方法
基本对话框(标题,图标,内容和选择按钮)
实现代码:
package com.example.dialogtest.one;import android.content.Context;import android.content.DialogInterface;import android.support.v7.app.AlertDialog;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.widget.Toast;import com.example.dialogtest.R;public class OneActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_one); final Context context = this; AlertDialog.Builder builder = new AlertDialog.Builder(context); builder.setTitle("zj") .setIcon(android.R.drawable.sym_def_app_icon) .setMessage("Hello World") .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { Toast.makeText(context, "positive", Toast.LENGTH_SHORT).show(); } }) .setNeutralButton("中性", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { Toast.makeText(context, "netural", Toast.LENGTH_SHORT).show(); } }) .setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { Toast.makeText(context, "negative", Toast.LENGTH_SHORT).show(); } }); AlertDialog dialog = builder.create(); dialog.show(); }}
注1:这里设置了3个类型的按钮(肯定,中性,否定),每种类型按钮只能添加一个
注2:输入的 Context
为当前 activity
,否则会出错
setCanceledOnTouchOutside
和 setCancelable
的使用方法
对话框出现之后,点击其他位置,对话框就会消失。有两种方法可以避免这种情况
参考:
Android4.0的Alertdialog对话框,设置点击其他位置不消失
第一个是设置函数 setCanceledOnTouchOutside
为 false
/** * Sets whether this dialog is canceled when touched outside the window's * bounds. If setting to true, the dialog is set to be cancelable if not * already set. * * @param cancel Whether the dialog should be canceled when touched outside * the window. */public void setCanceledOnTouchOutside(boolean cancel) { if (cancel && !mCancelable) { mCancelable = true; } mWindow.setCloseOnTouchOutside(cancel);}
实现代码:
...AlertDialog dialog = builder.create();dialog.setCanceledOnTouchOutside(false);dialog.show();
此时,点击屏幕其他位置,对话框将不会消失,但点击返回键仍可以取消对话框。如果想要取消返回键功能,可以设置函数 setCancelable
为 false
/** * Sets whether this dialog is cancelable with the * {@link KeyEvent#KEYCODE_BACK BACK} key. */public void setCancelable(boolean flag) { mCancelable = flag;}
实现代码:
...AlertDialog dialog = builder.create();dialog.setCancelable(false);dialog.show();
扩展 DialogFragment
使用 DialogFragment 管理对话框可确保它能正确处理生命周期事件,如用户按“返回”按钮或旋转屏幕时。 此外,DialogFragment 类还允许您将对话框的 UI 作为嵌入式组件在较大 UI 中重复使用,就像传统 Fragment 一样(例如,当您想让对话框 UI 在大屏幕和小屏幕上具有不同外观时)。
在 OnCreateDialog
回调方法中创建 AlertDialog
新建 CustomDialogFragment.java
:
package com.example.dialogtest.two;import android.app.Dialog;import android.content.Context;import android.content.DialogInterface;import android.os.Bundle;import android.support.annotation.NonNull;import android.support.v4.app.DialogFragment;import android.support.v7.app.AlertDialog;import android.widget.Toast;/** * Created by Lenovo on 2017/2/26. */public class CustomDialogFragment extends DialogFragment { @NonNull @Override public Dialog onCreateDialog(Bundle savedInstanceState) {// return super.onCreateDialog(savedInstanceState); final Context context = getActivity(); AlertDialog.Builder builder = new AlertDialog.Builder(context); builder.setTitle("zj") .setIcon(android.R.drawable.sym_def_app_icon) .setMessage("Hello World") .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { Toast.makeText(context, "positive", Toast.LENGTH_SHORT).show(); } }) .setNeutralButton("中性", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { Toast.makeText(context, "netural", Toast.LENGTH_SHORT).show(); } }) .setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { Toast.makeText(context, "negative", Toast.LENGTH_SHORT).show(); } }); return builder.create(); }}
然后就可以在 activity
中使用这个 fragment
:
package com.example.dialogtest.two;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import com.example.dialogtest.R;public class TwoActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_two); CustomDialogFragment dialogFragment = new CustomDialogFragment(); dialogFragment.show(getSupportFragmentManager(), "tag"); }}
函数 show
有两个参数,第一个传入 FragmentManager
,第二个传入一个字符串作为标记
添加列表(传统单选列表,永久性单选列表(单选按钮),永久性多选列表(复选框))
设置传统单选列表
新建 ThreeDialogFragment.java
:
package com.example.dialogtest.three;import android.app.Dialog;import android.content.Context;import android.content.DialogInterface;import android.os.Bundle;import android.support.annotation.NonNull;import android.support.v4.app.DialogFragment;import android.support.v7.app.AlertDialog;import android.widget.Toast;/** * Created by Lenovo on 2017/2/26. */public class ThreeDialogFragment extends DialogFragment { @NonNull @Override public Dialog onCreateDialog(Bundle savedInstanceState) {// return super.onCreateDialog(savedInstanceState); final Context context = getActivity(); AlertDialog.Builder builder = new AlertDialog.Builder(context); final String[] arr = getResources().getStringArray(android.R.array.phoneTypes); builder.setItems(arr, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { Toast.makeText(context, arr[which], Toast.LENGTH_SHORT).show(); } }); return builder.create(); }}
新建 ThreeActivity.java
:
package com.example.dialogtest.three;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import com.example.dialogtest.R;public class ThreeActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_three); ThreeDialogFragment dialogFragment = new ThreeDialogFragment(); dialogFragment.show(getSupportFragmentManager(), "tag"); }}
关键函数:builder.setItems
/** * Set a list of items to be displayed in the dialog as the content, you will be notified of the * selected item via the supplied listener. This should be an array type i.e. R.array.foo * * @return This Builder object to allow for chaining of calls to set methods */public Builder setItems(@ArrayRes int itemsId, final OnClickListener listener) { P.mItems = P.mContext.getResources().getTextArray(itemsId); P.mOnClickListener = listener; return this;}/** * Set a list of items to be displayed in the dialog as the content, you will be notified of the * selected item via the supplied listener. * * @return This Builder object to allow for chaining of calls to set methods */public Builder setItems(CharSequence[] items, final OnClickListener listener) { P.mItems = items; P.mOnClickListener = listener; return this;}
注1:设置的列表将在内容区域内出现,所以列表和消息不能同时出现
注2:也可以通过设置 adapter
来动态加载列表内容
设置永久性单选列表(单选按钮)
关键代码:
int id = -1;@NonNull@Overridepublic Dialog onCreateDialog(Bundle savedInstanceState) {// return super.onCreateDialog(savedInstanceState); final Context context = getActivity(); AlertDialog.Builder builder = new AlertDialog.Builder(context); final String[] arr = getResources().getStringArray(android.R.array.phoneTypes); builder.setTitle(R.string.app_name) .setSingleChoiceItems(arr, id, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { Toast.makeText(context, arr[which], Toast.LENGTH_SHORT).show(); id = which; } }) .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { Toast.makeText(context, arr[id], Toast.LENGTH_SHORT).show(); } }) .setNegativeButton(android.R.string.ok, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { Toast.makeText(context, arr[id], Toast.LENGTH_SHORT).show(); } }); return builder.create();}
关键函数:builder.setSingleChoiceItems
/** * Set a list of items to be displayed in the dialog as the content, you will be notified of * the selected item via the supplied listener. This should be an array type i.e. * R.array.foo The list will have a check mark displayed to the right of the text for the * checked item. Clicking on an item in the list will not dismiss the dialog. Clicking on a * button will dismiss the dialog. * * @param itemsId the resource id of an array i.e. R.array.foo * @param checkedItem specifies which item is checked. If -1 no items are checked. * @param listener notified when an item on the list is clicked. The dialog will not be * dismissed when an item is clicked. It will only be dismissed if clicked on a * button, if no buttons are supplied it's up to the user to dismiss the dialog. * * @return This Builder object to allow for chaining of calls to set methods */ public Builder setSingleChoiceItems(@ArrayRes int itemsId, int checkedItem, final OnClickListener listener) { P.mItems = P.mContext.getResources().getTextArray(itemsId); P.mOnClickListener = listener; P.mCheckedItem = checkedItem; P.mIsSingleChoice = true; return this; } /** * Set a list of items to be displayed in the dialog as the content, you will be notified of * the selected item via the supplied listener. The list will have a check mark displayed to * the right of the text for the checked item. Clicking on an item in the list will not * dismiss the dialog. Clicking on a button will dismiss the dialog. * * @param cursor the cursor to retrieve the items from. * @param checkedItem specifies which item is checked. If -1 no items are checked. * @param labelColumn The column name on the cursor containing the string to display in the * label. * @param listener notified when an item on the list is clicked. The dialog will not be * dismissed when an item is clicked. It will only be dismissed if clicked on a * button, if no buttons are supplied it's up to the user to dismiss the dialog. * * @return This Builder object to allow for chaining of calls to set methods */ public Builder setSingleChoiceItems(Cursor cursor, int checkedItem, String labelColumn, final OnClickListener listener) { P.mCursor = cursor; P.mOnClickListener = listener; P.mCheckedItem = checkedItem; P.mLabelColumn = labelColumn; P.mIsSingleChoice = true; return this; }
有3个参数,第一个输入数组;
第二个输入预先指定的选项,若值为 -1 则没有指定选项;
第三个为监听接口。
设置永久性多选列表(复选框)
关键代码:
package com.example.dialogtest.five;import android.app.Dialog;import android.content.Context;import android.content.DialogInterface;import android.os.Bundle;import android.support.annotation.NonNull;import android.support.v4.app.DialogFragment;import android.support.v7.app.AlertDialog;import android.widget.Toast;import com.example.dialogtest.R;import java.util.ArrayList;import java.util.List;/** * Created by Lenovo on 2017/2/26. */public class FiveDialog extends DialogFragment { List list; String[] arr; @NonNull @Override public Dialog onCreateDialog(Bundle savedInstanceState) {// return super.onCreateDialog(savedInstanceState); list = new ArrayList<>(); arr = getResources().getStringArray(android.R.array.phoneTypes); final Context context = getActivity(); AlertDialog.Builder builder = new AlertDialog.Builder(context); builder.setTitle(R.string.app_name) .setMultiChoiceItems(arr, null, new DialogInterface.OnMultiChoiceClickListener() { @Override public void onClick(DialogInterface dialog, int which, boolean isChecked) { if (isChecked) { // If the user checked the item, add it to the selected items list.add(arr[which]); Toast.makeText(context, "you choose " + arr[which], Toast.LENGTH_SHORT).show(); } else if (list.contains(arr[which])) { // Else, if the item is already in the array, remove it list.remove(arr[which]); Toast.makeText(context, "you dischoose " + arr[which], Toast.LENGTH_SHORT).show(); } } }) .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int id) { // User clicked OK, so save the mSelectedItems results somewhere // or return them to the component that opened the dialog Toast.makeText(context, list.toString(), Toast.LENGTH_SHORT).show(); } }) .setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int id) { Toast.makeText(context, list.toString(), Toast.LENGTH_SHORT).show(); } }); return builder.create(); }}
关键函数: builder.setMultiChoiceItems
/** * Set a list of items to be displayed in the dialog as the content, * you will be notified of the selected item via the supplied listener. * This should be an array type, e.g. R.array.foo. The list will have * a check mark displayed to the right of the text for each checked * item. Clicking on an item in the list will not dismiss the dialog. * Clicking on a button will dismiss the dialog. * * @param itemsId the resource id of an array i.e. R.array.foo * @param checkedItems specifies which items are checked. It should be null in which case no * items are checked. If non null it must be exactly the same length as the array of * items. * @param listener notified when an item on the list is clicked. The dialog will not be * dismissed when an item is clicked. It will only be dismissed if clicked on a * button, if no buttons are supplied it's up to the user to dismiss the dialog. * * @return This Builder object to allow for chaining of calls to set methods */ public Builder setMultiChoiceItems(@ArrayRes int itemsId, boolean[] checkedItems, final OnMultiChoiceClickListener listener) { P.mItems = P.mContext.getResources().getTextArray(itemsId); P.mOnCheckboxClickListener = listener; P.mCheckedItems = checkedItems; P.mIsMultiChoice = true; return this; } /** * Set a list of items to be displayed in the dialog as the content, * you will be notified of the selected item via the supplied listener. * The list will have a check mark displayed to the right of the text * for each checked item. Clicking on an item in the list will not * dismiss the dialog. Clicking on a button will dismiss the dialog. * * @param items the text of the items to be displayed in the list. * @param checkedItems specifies which items are checked. It should be null in which case no * items are checked. If non null it must be exactly the same length as the array of * items. * @param listener notified when an item on the list is clicked. The dialog will not be * dismissed when an item is clicked. It will only be dismissed if clicked on a * button, if no buttons are supplied it's up to the user to dismiss the dialog. * * @return This Builder object to allow for chaining of calls to set methods */ public Builder setMultiChoiceItems(CharSequence[] items, boolean[] checkedItems, final OnMultiChoiceClickListener listener) { P.mItems = items; P.mOnCheckboxClickListener = listener; P.mCheckedItems = checkedItems; P.mIsMultiChoice = true; return this; }
该函数有3个参数:第一个表示输入的内容数组;
第二个表示预先选定的选项,是一个 boolean
数组,其长度必须和内容数组一致;
第三个表示监听的接口
自定义布局
对话框的内容区域可以设置为自定义布局
如果您想让对话框具有自定义布局,请创建一个布局,然后通过调用 AlertDialog.Builder 对象上的 setView() 将其添加到 AlertDialog。
默认情况下,自定义布局会填充对话框窗口,但您仍然可以使用 AlertDialog.Builder 方法来添加按钮和标题。
要扩展 DialogFragment 中的布局,请通过 getLayoutInflater() 获取一个 LayoutInflater 并调用 inflate(),其中第一个参数是布局资源 ID,第二个参数是布局的父视图。然后,您可以调用 setView() 将布局放入对话框。
实现代码:
package com.zj.dialogtest.view;import android.app.AlertDialog;import android.app.Dialog;import android.app.DialogFragment;import android.content.Context;import android.content.DialogInterface;import android.os.Bundle;import android.view.LayoutInflater;import android.view.View;import android.widget.EditText;import android.widget.Toast;import com.zj.dialogtest.R;/** * Created by zj on 17-2-27. */public class ViewDialogFragment extends DialogFragment { private View view; private EditText editText; private EditText editText2; @Override public Dialog onCreateDialog(Bundle savedInstanceState) {// return super.onCreateDialog(savedInstanceState); LayoutInflater inflater = getActivity().getLayoutInflater(); final Context context = getActivity(); AlertDialog.Builder builder = new AlertDialog.Builder(context); view = inflater.inflate(R.layout.dialog_signin, null); editText = (EditText)view.findViewById(R.id.username); editText2 = (EditText)view.findViewById(R.id.password); builder.setView(view) .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialogInterface, int i) { Toast.makeText(context, editText.getText()+" "+editText2.getText(), Toast.LENGTH_SHORT).show(); } }) .setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialogInterface, int i) { Toast.makeText(context, editText.getText()+" "+editText2.getText(), Toast.LENGTH_SHORT).show(); } }); return builder.create(); }}
将事件传递回对话框的宿主(通过接口)
通过定义接口,将对话框的操作信息返回给打开对话框的 activity
:
新建 InterDialogFragment.java
:
package com.zj.dialogtest.inter;import android.app.Activity;import android.app.AlertDialog;import android.app.Dialog;import android.content.Context;import android.content.DialogInterface;import android.os.Bundle;import android.support.v4.app.DialogFragment;import com.zj.dialogtest.R;import java.util.ArrayList;import java.util.List;import java.util.StringTokenizer;/** * Created by zj on 17-2-27. */public class InterDialogFragment extends DialogFragment { private List list; String[] arr; /* The activity that creates an instance of this dialog fragment must * implement this interface in order to receive event callbacks. * Each method passes the DialogFragment in case the host needs to query it. */ public interface NoticeDialogListener { public void onDialogPositiveClick(DialogFragment dialog, List list); public void onDialogNegativeClick(DialogFragment dialog, List list); } // Use this instance of the interface to deliver action events NoticeDialogListener mListener; // Override the Fragment.onAttach() method to instantiate the NoticeDialogListener @Override public void onAttach(Activity activity) { super.onAttach(activity); // Verify that the host activity implements the callback interface try { // Instantiate the NoticeDialogListener so we can send events to the host mListener = (NoticeDialogListener) activity; } catch (ClassCastException e) { // The activity doesn't implement the interface, throw exception throw new ClassCastException(activity.toString() + " must implement NoticeDialogListener"); } } @Override public Dialog onCreateDialog(Bundle savedInstanceState) {// return super.onCreateDialog(savedInstanceState); list = new ArrayList<>(); arr = getResources().getStringArray(android.R.array.phoneTypes); Context context = getActivity(); AlertDialog.Builder builder = new AlertDialog.Builder(context); builder.setTitle(R.string.app_name) .setMultiChoiceItems(arr, null, new DialogInterface.OnMultiChoiceClickListener() { @Override public void onClick(DialogInterface dialogInterface, int i, boolean b) { if (b) { list.add(arr[i]); } else { if (list.contains(arr[i])) { list.remove(arr[i]); } } } }) .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialogInterface, int i) { mListener.onDialogPositiveClick(InterDialogFragment.this, list); } }) .setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialogInterface, int i) { List temp = new ArrayList(); for (String str : arr) { if (!list.contains(str)) { temp.add(str); } } mListener.onDialogNegativeClick(InterDialogFragment.this, temp); } }); return builder.create(); }}
新建 InterActivity.java
:
package com.zj.dialogtest.inter;import android.support.v4.app.DialogFragment;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.widget.Toast;import com.zj.dialogtest.R;import java.util.List;public class InterActivity extends AppCompatActivity implements InterDialogFragment.NoticeDialogListener { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_inter); InterDialogFragment dialogFragment = new InterDialogFragment(); dialogFragment.show(getSupportFragmentManager(), "tag"); } @Override public void onDialogNegativeClick(DialogFragment dialog, List list) { Toast.makeText(this, "you dont't click "+list.toString(), Toast.LENGTH_SHORT).show(); } @Override public void onDialogPositiveClick(DialogFragment dialog, List list) { Toast.makeText(this, "you click "+list.toString(), Toast.LENGTH_SHORT).show(); }}
onDismiss()
和 onCancel()
的使用方法
通常情况下,当你点击对话框外屏幕,或者点击返回键,或者点击对话框按钮时,对话框将会自动消失。
如果你使用 DialogFragment
来定义对话框,那么对话框在消失之前会调用 onDismiss()
或者 onCancel()
,有两种情况:
- 点击对话框外屏幕,或者返回键,将会先调用
onCancel()
,再调用onDismiss()
; - 点击对话框按钮,将会调用方法
onDismiss()
。
也可以显式调用 DialogFragment
的 dismiss()
方法;或者 Dialog
的 cancel()
方法。
示例代码:
package com.zj.dialogtest.Exit;import android.app.AlertDialog;import android.app.Dialog;import android.content.DialogInterface;import android.os.Bundle;import android.support.annotation.NonNull;import android.support.v4.app.DialogFragment;import android.util.Log;import com.zj.dialogtest.R;/** * Created by zj on 17-2-27. */public class ExitDialogFragment extends DialogFragment { private static final String TAG = ExitDialogFragment.class.getSimpleName(); @NonNull @Override public Dialog onCreateDialog(Bundle savedInstanceState) {// return super.onCreateDialog(savedInstanceState); AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); builder.setTitle(R.string.app_name) .setIcon(R.mipmap.ic_launcher) .setMessage("Hello World") .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialogInterface, int i) { } }) .setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialogInterface, int i) { } }); Dialog dialog = builder.create();// this.dismiss();// dialog.cancel(); return dialog; } @Override public void onDismiss(DialogInterface dialog) { super.onDismiss(dialog); Log.e(TAG, "onDismiss: "); } @Override public void onCancel(DialogInterface dialog) { super.onCancel(dialog); Log.e(TAG, "onCancel: "); }}
更多相关文章
- android ExpandableListView伸缩列表
- android 笔记 --- Android应用程序的权限列表
- AndroidStudio 备忘录之Spinner(下拉列表)
- 将要更新到android 4.0的手机列表
- Android实现九宫格 主界面应用列表效果
- android 获取对话框关闭事件
- Android 自定义格式的对话框
- 【Android】Android中AlertDialog对话框的使用实例
- 旋转对话框