参考:
对话框: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
@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.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: ");
}
}