我有一个带有 EditText
的对话框供输入。当我单击对话框上的“是”按钮时,它将验证输入,然后关闭对话框。但是,如果输入错误,我想留在同一个对话框中。每次无论输入什么,当我单击“否”按钮时,对话框都应该自动关闭。我怎样才能禁用它?顺便说一句,我使用 PositiveButton 和 NegativeButton 作为对话框上的按钮。
编辑:正如一些评论所指出的,这只适用于 API 8+。
这是一个较晚的答案,但您可以将 onShowListener 添加到 AlertDialog ,然后您可以在其中覆盖按钮的 onClickListener 。
final AlertDialog dialog = new AlertDialog.Builder(context)
.setView(v)
.setTitle(R.string.my_title)
.setPositiveButton(android.R.string.ok, null) //Set to null. We override the onclick
.setNegativeButton(android.R.string.cancel, null)
.create();
dialog.setOnShowListener(new DialogInterface.OnShowListener() {
@Override
public void onShow(DialogInterface dialogInterface) {
Button button = ((AlertDialog) dialog).getButton(AlertDialog.BUTTON_POSITIVE);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// TODO Do something
//Dismiss once everything is OK.
dialog.dismiss();
}
});
}
});
dialog.show();
以下是所有类型对话框的一些解决方案,包括适用于所有 API 级别的 AlertDialog.Builder 解决方案(适用于 API 8 以下,此处的其他答案不适用)。有使用 AlertDialog.Builder、DialogFragment 和 DialogPreference 的 AlertDialogs 解决方案。
下面是代码示例,展示了如何覆盖默认的常用按钮处理程序并防止对话框关闭这些不同形式的对话框。所有示例都显示了如何防止正按钮关闭对话框。
注意:对于那些想要了解更多细节的人,在示例之后,将描述对话框关闭如何在基本 android 类的后台工作,以及为什么选择以下方法
AlertDialog.Builder - 在 show() 之后立即更改默认按钮处理程序
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setMessage("Test for preventing dialog close");
builder.setPositiveButton("Test",
new DialogInterface.OnClickListener()
{
@Override
public void onClick(DialogInterface dialog, int which)
{
//Do nothing here because we override this button later to change the close behaviour.
//However, we still need this because on older versions of Android unless we
//pass a handler the button doesn't get instantiated
}
});
final AlertDialog dialog = builder.create();
dialog.show();
//Overriding the handler immediately after show is probably a better approach than OnShowListener as described below
dialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v)
{
Boolean wantToCloseDialog = false;
//Do stuff, possibly set wantToCloseDialog to true then...
if(wantToCloseDialog)
dialog.dismiss();
//else dialog stays open. Make sure you have an obvious way to close the dialog especially if you set cancellable to false.
}
});
DialogFragment - 覆盖 onResume()
@Override
public Dialog onCreateDialog(Bundle savedInstanceState)
{
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setMessage("Test for preventing dialog close");
builder.setPositiveButton("Test",
new DialogInterface.OnClickListener()
{
@Override
public void onClick(DialogInterface dialog, int which)
{
//Do nothing here because we override this button later to change the close behaviour.
//However, we still need this because on older versions of Android unless we
//pass a handler the button doesn't get instantiated
}
});
return builder.create();
}
//onStart() is where dialog.show() is actually called on
//the underlying dialog, so we have to do it there or
//later in the lifecycle.
//Doing it in onResume() makes sure that even if there is a config change
//environment that skips onStart then the dialog will still be functioning
//properly after a rotation.
@Override
public void onResume()
{
super.onResume();
final AlertDialog d = (AlertDialog)getDialog();
if(d != null)
{
Button positiveButton = (Button) d.getButton(Dialog.BUTTON_POSITIVE);
positiveButton.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v)
{
Boolean wantToCloseDialog = false;
//Do stuff, possibly set wantToCloseDialog to true then...
if(wantToCloseDialog)
d.dismiss();
//else dialog stays open. Make sure you have an obvious way to close the dialog especially if you set cancellable to false.
}
});
}
}
DialogPreference - 覆盖 showDialog()
@Override
protected void onPrepareDialogBuilder(Builder builder)
{
super.onPrepareDialogBuilder(builder);
builder.setPositiveButton("Test", this); //Set the button here so it gets created
}
@Override
protected void showDialog(Bundle state)
{
super.showDialog(state); //Call show on default first so we can override the handlers
final AlertDialog d = (AlertDialog) getDialog();
d.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v)
{
Boolean wantToCloseDialog = false;
//Do stuff, possibly set wantToCloseDialog to true then...
if(wantToCloseDialog)
d.dismiss();
//else dialog stays open. Make sure you have an obvious way to close the dialog especially if you set cancellable to false.
}
});
}
方法说明:
查看 Android 源代码,AlertDialog 默认实现通过向 OnCreate() 中的所有实际按钮注册一个通用按钮处理程序来工作。单击按钮时,通用按钮处理程序将单击事件转发到您在 setButton() 中传递的任何处理程序,然后调用关闭对话框。如果您希望在按下这些按钮之一时阻止对话框关闭,您必须替换公共按钮处理程序以获取按钮的实际视图。因为它是在 OnCreate() 中分配的,所以必须在调用默认 OnCreate() 实现后替换它。在 show() 方法的过程中调用 OnCreate。您可以创建一个自定义 Dialog 类并覆盖 OnCreate() 以调用 super.OnCreate() 然后覆盖按钮处理程序,但是如果您制作自定义对话框,您不会免费获得 Builder,在这种情况下有什么意义?因此,在使用对话框的设计方式但控制何时关闭时,一种方法是首先调用 dialog.Show(),然后使用 dialog.getButton() 获取对按钮的引用以覆盖单击处理程序。另一种方法是使用 setOnShowListener() 并实现查找按钮视图并替换 OnShowListener 中的处理程序。两者之间的功能差异“几乎”为零,具体取决于最初创建对话框实例的线程。查看源代码,onShowListener 被一条消息调用,该消息发布到在创建该对话框的线程上运行的处理程序。因此,由于您的 OnShowListener 是由消息队列上发布的消息调用的,因此从技术上讲,调用您的侦听器可能会在显示完成后延迟一段时间。因此,我认为最安全的方法是第一种:调用 show.Dialog(),然后立即在同一执行路径中替换按钮处理程序。由于您调用 show() 的代码将在主 GUI 线程上运行,这意味着您遵循 show() 的任何代码都将在该线程上的任何其他代码之前执行,而 OnShowListener 方法的时间由消息队列。
ProgressDialog
?
替代解决方案
我想从用户体验的角度提出一个替代答案。
为什么要在单击按钮时阻止对话框关闭?大概是因为您有一个自定义对话框,其中用户尚未做出选择或尚未完全填写所有内容。如果他们没有完成,那么你根本不应该让他们点击肯定按钮。只需禁用它,直到一切准备就绪。
这里的其他答案提供了很多技巧来覆盖积极的按钮点击。如果这很重要,Android 不是已经提供了一种方便的方法吗?他们没有。
相反,Dialogs design guide 显示了这种情况的一个示例。在用户做出选择之前,确定按钮被禁用。根本不需要压倒一切的技巧。对用户来说很明显,在继续之前还需要做一些事情。
https://i.stack.imgur.com/np1RE.png
如何禁用积极按钮
请参阅 Android documentation for creating a custom dialog layout。它建议您将 AlertDialog
放在 DialogFragment
中。然后,您需要做的就是在布局元素上设置监听器,以了解何时启用或禁用肯定按钮。
如果您的自定义对话框有单选按钮,则使用 RadioGroup.OnCheckedChangeListener。
如果您的自定义对话框有复选框,则使用 CompoundButton.OnCheckedChangeListener。
如果您的自定义对话框具有 EditText,则使用 TextWatcher。
可以像这样禁用积极按钮:
AlertDialog dialog = (AlertDialog) getDialog();
dialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(false);
这是一个完整的工作 DialogFragment
,带有一个禁用的正按钮,如上图中可能使用的。
import android.support.v4.app.DialogFragment;
import android.support.v7.app.AlertDialog;
public class MyDialogFragment extends DialogFragment {
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
// inflate the custom dialog layout
LayoutInflater inflater = getActivity().getLayoutInflater();
View view = inflater.inflate(R.layout.my_dialog_layout, null);
// add a listener to the radio buttons
RadioGroup radioGroup = (RadioGroup) view.findViewById(R.id.radio_group);
radioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup radioGroup, int i) {
// enable the positive button after a choice has been made
AlertDialog dialog = (AlertDialog) getDialog();
dialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(true);
}
});
// build the alert dialog
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setView(view)
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int id) {
// TODO: use an interface to pass the user choice back to the activity
}
})
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
MyDialogFragment.this.getDialog().cancel();
}
});
return builder.create();
}
@Override
public void onResume() {
super.onResume();
// disable positive button by default
AlertDialog dialog = (AlertDialog) getDialog();
dialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(false);
}
}
自定义对话框可以从这样的活动中运行:
MyDialogFragment dialog = new MyDialogFragment();
dialog.show(getFragmentManager(), "MyTag");
笔记
为简洁起见,我省略了将用户选择信息传递回活动的通信接口。但是,文档显示了这是如何完成的。
onCreateDialog 中的按钮仍然为空,所以我在 onResume 中禁用了它。如果用户切换到另一个应用程序然后返回而不关闭对话框,这会产生不希望的效果,即再次禁用它。这也可以通过取消选择任何用户选择或通过从 onCreateDialog 调用 Runnable 来禁用下一个运行循环上的按钮来解决。 view.post(new Runnable() { @Override public void run() { AlertDialog dialog = (AlertDialog) getDialog(); dialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(false); } });
有关的
带有一个、两个和三个按钮的 Android 警报对话框
如何在 Android 警报对话框中显示列表视图?
我编写了一个简单的类(AlertDialogBuilder),您可以在按下对话框按钮时使用它来禁用自动关闭功能。
它也与 Android 1.6 兼容,因此它不使用 OnShowListener(仅 API >= 8 可用)。
因此,您可以使用此 CustomAlertDialogBuilder,而不是使用 AlertDialog.Builder。最重要的部分是你不应该调用 create(),而应该只调用 show() 方法。我添加了 setCanceledOnTouchOutside() 和 setOnDismissListener 等方法,以便您仍然可以直接在构建器上设置它们。
我在 Android 1.6、2.x、3.x 和 4.x 上对其进行了测试,所以它应该工作得很好。如果您发现一些问题,请在此处发表评论。
package com.droidahead.lib.utils;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.view.View;
import android.view.View.OnClickListener;
public class CustomAlertDialogBuilder extends AlertDialog.Builder {
/**
* Click listeners
*/
private DialogInterface.OnClickListener mPositiveButtonListener = null;
private DialogInterface.OnClickListener mNegativeButtonListener = null;
private DialogInterface.OnClickListener mNeutralButtonListener = null;
/**
* Buttons text
*/
private CharSequence mPositiveButtonText = null;
private CharSequence mNegativeButtonText = null;
private CharSequence mNeutralButtonText = null;
private DialogInterface.OnDismissListener mOnDismissListener = null;
private Boolean mCancelOnTouchOutside = null;
public CustomAlertDialogBuilder(Context context) {
super(context);
}
public CustomAlertDialogBuilder setOnDismissListener (DialogInterface.OnDismissListener listener) {
mOnDismissListener = listener;
return this;
}
@Override
public CustomAlertDialogBuilder setNegativeButton(CharSequence text, DialogInterface.OnClickListener listener) {
mNegativeButtonListener = listener;
mNegativeButtonText = text;
return this;
}
@Override
public CustomAlertDialogBuilder setNeutralButton(CharSequence text, DialogInterface.OnClickListener listener) {
mNeutralButtonListener = listener;
mNeutralButtonText = text;
return this;
}
@Override
public CustomAlertDialogBuilder setPositiveButton(CharSequence text, DialogInterface.OnClickListener listener) {
mPositiveButtonListener = listener;
mPositiveButtonText = text;
return this;
}
@Override
public CustomAlertDialogBuilder setNegativeButton(int textId, DialogInterface.OnClickListener listener) {
setNegativeButton(getContext().getString(textId), listener);
return this;
}
@Override
public CustomAlertDialogBuilder setNeutralButton(int textId, DialogInterface.OnClickListener listener) {
setNeutralButton(getContext().getString(textId), listener);
return this;
}
@Override
public CustomAlertDialogBuilder setPositiveButton(int textId, DialogInterface.OnClickListener listener) {
setPositiveButton(getContext().getString(textId), listener);
return this;
}
public CustomAlertDialogBuilder setCanceledOnTouchOutside (boolean cancelOnTouchOutside) {
mCancelOnTouchOutside = cancelOnTouchOutside;
return this;
}
@Override
public AlertDialog create() {
throw new UnsupportedOperationException("CustomAlertDialogBuilder.create(): use show() instead..");
}
@Override
public AlertDialog show() {
final AlertDialog alertDialog = super.create();
DialogInterface.OnClickListener emptyOnClickListener = new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) { }
};
// Enable buttons (needed for Android 1.6) - otherwise later getButton() returns null
if (mPositiveButtonText != null) {
alertDialog.setButton(AlertDialog.BUTTON_POSITIVE, mPositiveButtonText, emptyOnClickListener);
}
if (mNegativeButtonText != null) {
alertDialog.setButton(AlertDialog.BUTTON_NEGATIVE, mNegativeButtonText, emptyOnClickListener);
}
if (mNeutralButtonText != null) {
alertDialog.setButton(AlertDialog.BUTTON_NEUTRAL, mNeutralButtonText, emptyOnClickListener);
}
// Set OnDismissListener if available
if (mOnDismissListener != null) {
alertDialog.setOnDismissListener(mOnDismissListener);
}
if (mCancelOnTouchOutside != null) {
alertDialog.setCanceledOnTouchOutside(mCancelOnTouchOutside);
}
alertDialog.show();
// Set the OnClickListener directly on the Button object, avoiding the auto-dismiss feature
// IMPORTANT: this must be after alert.show(), otherwise the button doesn't exist..
// If the listeners are null don't do anything so that they will still dismiss the dialog when clicked
if (mPositiveButtonListener != null) {
alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
mPositiveButtonListener.onClick(alertDialog, AlertDialog.BUTTON_POSITIVE);
}
});
}
if (mNegativeButtonListener != null) {
alertDialog.getButton(AlertDialog.BUTTON_NEGATIVE).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
mNegativeButtonListener.onClick(alertDialog, AlertDialog.BUTTON_NEGATIVE);
}
});
}
if (mNeutralButtonListener != null) {
alertDialog.getButton(AlertDialog.BUTTON_NEUTRAL).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
mNeutralButtonListener.onClick(alertDialog, AlertDialog.BUTTON_NEUTRAL);
}
});
}
return alertDialog;
}
}
编辑这是一个关于如何使用 CustomAlertDialogBuilder 的小例子:
// Create the CustomAlertDialogBuilder
CustomAlertDialogBuilder dialogBuilder = new CustomAlertDialogBuilder(context);
// Set the usual data, as you would do with AlertDialog.Builder
dialogBuilder.setIcon(R.drawable.icon);
dialogBuilder.setTitle("Dialog title");
dialogBuilder.setMessage("Some text..");
// Set your buttons OnClickListeners
dialogBuilder.setPositiveButton ("Button 1", new DialogInterface.OnClickListener() {
public void onClick (DialogInterface dialog, int which) {
// Do something...
// Dialog will not dismiss when the button is clicked
// call dialog.dismiss() to actually dismiss it.
}
});
// By passing null as the OnClickListener the dialog will dismiss when the button is clicked.
dialogBuilder.setNegativeButton ("Close", null);
// Set the OnDismissListener (if you need it)
dialogBuilder.setOnDismissListener(new DialogInterface.OnDismissListener() {
public void onDismiss(DialogInterface dialog) {
// dialog was just dismissed..
}
});
// (optional) set whether to dismiss dialog when touching outside
dialogBuilder.setCanceledOnTouchOutside(false);
// Show the dialog
dialogBuilder.show();
干杯,
尤维
Context mContext
并将其设置在构造函数中。
如果您使用的是 DialogFragment
,这里有一些东西——无论如何,这是处理对话框的推荐方法。
AlertDialog 的 setButton()
方法(我想 AlertDialogBuilder
的 setPositiveButton()
和 setNegativeButton()
也一样)会发生什么,您使用它设置的按钮(例如 AlertDialog.BUTTON_POSITIVE
)实际上会触发两个不同的 OnClickListener
按下时的对象。
第一个是 DialogInterface.OnClickListener,它是 setButton()
、setPositiveButton()
和 setNegativeButton()
的参数。
另一个是 View.OnClickListener,它将设置为在按下任何按钮时自动关闭您的 AlertDialog
- 并由 AlertDialog
自己设置。
您可以做的是使用 setButton()
和 null
作为 DialogInterface.OnClickListener
,创建按钮,然后在 View.OnClickListener
中调用您的自定义操作方法。例如,
@Override
public Dialog onCreateDialog(Bundle savedInstanceState)
{
AlertDialog alertDialog = new AlertDialog(getActivity());
// set more items...
alertDialog.setButton(AlertDialog.BUTTON_POSITIVE, "OK", null);
return alertDialog;
}
然后,您可以在 DialogFragment
的 onResume()
方法中覆盖默认 AlertDialog
按钮的 View.OnClickListener
(否则会关闭对话框):
@Override
public void onResume()
{
super.onResume();
AlertDialog alertDialog = (AlertDialog) getDialog();
Button okButton = alertDialog.getButton(AlertDialog.BUTTON_POSITIVE);
okButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v)
{
performOkButtonAction();
}
});
}
private void performOkButtonAction() {
// Do your stuff here
}
您需要在 onResume()
方法中进行设置,因为在显示对话框之前 getButton()
将返回 null
!
这应该会导致您的自定义操作方法只被调用一次,并且默认情况下不会关闭对话框。
受汤姆回答的启发,我相信这里的想法是:
将创建对话框期间的onClickListener设置为null
然后在显示对话框后设置一个 onClickListener。
您可以像 Tom 一样覆盖 onShowListener
。或者,您可以
在调用 AlertDialog 的 show() 后获取按钮将按钮的 onClickListener 设置如下(我认为更具可读性)。
代码:
AlertDialog.Builder builder = new AlertDialog.Builder(context);
// ...
final AlertDialog dialog = builder.create();
dialog.show();
// now you can override the default onClickListener
Button b = dialog.getButton(AlertDialog.BUTTON_POSITIVE);
b.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Log.i(TAG, "ok button is clicked");
handleClick(dialog);
}
});
对于 pre API 8,如果 editText 的内容不正确,我使用布尔标志、关闭侦听器和再次调用 dialog.show 解决了问题。像这样:
case ADD_CLIENT:
LayoutInflater factoryClient = LayoutInflater.from(this);
final View EntryViewClient = factoryClient.inflate(
R.layout.alert_dialog_add_client, null);
EditText ClientText = (EditText) EntryViewClient
.findViewById(R.id.client_edit);
AlertDialog.Builder builderClient = new AlertDialog.Builder(this);
builderClient
.setTitle(R.string.alert_dialog_client)
.setCancelable(false)
.setView(EntryViewClient)
.setPositiveButton("Save",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,
int whichButton) {
EditText newClient = (EditText) EntryViewClient
.findViewById(R.id.client_edit);
String newClientString = newClient
.getText().toString();
if (checkForEmptyFields(newClientString)) {
//If field is empty show toast and set error flag to true;
Toast.makeText(getApplicationContext(),
"Fields cant be empty",
Toast.LENGTH_SHORT).show();
add_client_error = true;
} else {
//Here save the info and set the error flag to false
add_client_error = false;
}
}
})
.setNegativeButton("Cancel",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,
int id) {
add_client_error = false;
dialog.cancel();
}
});
final AlertDialog alertClient = builderClient.create();
alertClient.show();
alertClient
.setOnDismissListener(new DialogInterface.OnDismissListener() {
@Override
public void onDismiss(DialogInterface dialog) {
//If the error flag was set to true then show the dialog again
if (add_client_error == true) {
alertClient.show();
} else {
return;
}
}
});
return true;
this link 处的答案是一个简单的解决方案,它与 API 3 兼容。它与 Tom Bollwitt 的解决方案非常相似,但没有使用不太兼容的 OnShowListener。
是的你可以。您基本上需要: 使用 DialogBuilder show() 对话框创建对话框 在显示的对话框中找到按钮并覆盖它们的 onClickListener
自从我扩展了一个 EditTextPreference 以来,我对 Kamen 的代码做了一些小的修改。
@Override
protected void showDialog(Bundle state) {
super.showDialog(state);
class mocl implements OnClickListener{
private final AlertDialog dialog;
public mocl(AlertDialog dialog) {
this.dialog = dialog;
}
@Override
public void onClick(View v) {
//checks if EditText is empty, and if so tells the user via Toast
//otherwise it closes dialog and calls the EditTextPreference's onClick
//method to let it know that the button has been pressed
if (!IntPreference.this.getEditText().getText().toString().equals("")){
dialog.dismiss();
IntPreference.this.onClick(dialog,DialogInterface.BUTTON_POSITIVE);
}
else {
Toast t = Toast.makeText(getContext(), "Enter a number!", Toast.LENGTH_SHORT);
t.show();
}
}
}
AlertDialog d = (AlertDialog) getDialog();
Button b = d.getButton(DialogInterface.BUTTON_POSITIVE);
b.setOnClickListener(new mocl((d)));
}
好好玩!
超级简单的 Kotlin 方法
with(AlertDialog.Builder(this)) {
setTitle("Title")
setView(R.layout.dialog_name)
setPositiveButton("Ok", null)
setNegativeButton("Cancel") { _, _ -> }
create().apply {
setOnShowListener {
getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener {
//Validate and dismiss
dismiss()
}
}
}
}.show()
这段代码对你有用,因为我有一个类似的问题,这对我有用。 :)
1-覆盖片段对话框类中的 Onstart() 方法。
@Override
public void onStart() {
super.onStart();
final AlertDialog D = (AlertDialog) getDialog();
if (D != null) {
Button positive = (Button) D.getButton(Dialog.BUTTON_POSITIVE);
positive.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View arg0) {
if (edittext.equals("")) {
Toast.makeText(getActivity(), "EditText empty",Toast.LENGTH_SHORT).show();
} else {
D.dismiss(); //dissmiss dialog
}
}
});
}
}
为了防止对话框在单击时关闭,它应该只在互联网可用时关闭
我正在尝试做同样的事情,因为我不希望在连接互联网之前关闭对话框。
这是我的代码:
AlertDialog.Builder builder=new AlertDialog.Builder(MainActivity.this); builder.setTitle("Internet Not Connected");
if(ifConnected()){
Toast.makeText(this, "Connected or not", Toast.LENGTH_LONG).show();
}
else{
builder.setPositiveButton("Retry", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
if(!ifConnected())
{
builder.show();
}
}
}).setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
finish();
}
});
builder.show();
}
这是我的连接管理器代码:
private boolean ifConnected()
{
ConnectivityManager connectivityManager= (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo=connectivityManager.getActiveNetworkInfo();
return networkInfo!=null && networkInfo.isConnected();
}
The specified child already has a parent. You must call removeView() on the child's parent first
对于进度对话框
要防止对话框自动关闭,您必须在显示 ProgressDialog
后设置 OnClickListener
,如下所示:
connectingDialog = new ProgressDialog(this);
connectingDialog.setCancelable(false);
connectingDialog.setCanceledOnTouchOutside(false);
// Create the button but set the listener to a null object.
connectingDialog.setButton(DialogInterface.BUTTON_NEGATIVE, "Cancel",
(DialogInterface.OnClickListener) null )
// Show the dialog so we can then get the button from the view.
connectingDialog.show();
// Get the button from the view.
Button dialogButton = connectingDialog.getButton( DialogInterface.BUTTON_NEGATIVE);
// Set the onClickListener here, in the view.
dialogButton.setOnClickListener( new View.OnClickListener() {
@Override
public void onClick ( View v ) {
// Dialog will not get dismissed until you call dismiss() explicitly.
}
});
public class ComentarDialog extends DialogFragment{
private EditText comentario;
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
LayoutInflater inflater = LayoutInflater.from(getActivity());
View v = inflater.inflate(R.layout.dialog_comentar, null);
comentario = (EditText)v.findViewById(R.id.etxt_comentar_dialog);
builder.setTitle("Comentar")
.setView(v)
.setPositiveButton("OK", null)
.setNegativeButton("CANCELAR", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
}
});
return builder.create();
}
@Override
public void onStart() {
super.onStart();
//Obtenemos el AlertDialog
AlertDialog dialog = (AlertDialog)getDialog();
dialog.setCanceledOnTouchOutside(false);
dialog.setCancelable(false);//Al presionar atras no desaparece
//Implementamos el listener del boton OK para mostrar el toast
dialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(TextUtils.isEmpty(comentario.getText())){
Toast.makeText(getActivity(), "Ingrese un comentario", Toast.LENGTH_SHORT).show();
return;
}
else{
((AlertDialog)getDialog()).dismiss();
}
}
});
//Personalizamos
Resources res = getResources();
//Buttons
Button positive_button = dialog.getButton(DialogInterface.BUTTON_POSITIVE);
positive_button.setBackground(res.getDrawable(R.drawable.btn_selector_dialog));
Button negative_button = dialog.getButton(DialogInterface.BUTTON_NEGATIVE);
negative_button.setBackground(res.getDrawable(R.drawable.btn_selector_dialog));
int color = Color.parseColor("#304f5a");
//Title
int titleId = res.getIdentifier("alertTitle", "id", "android");
View title = dialog.findViewById(titleId);
if (title != null) {
((TextView) title).setTextColor(color);
}
//Title divider
int titleDividerId = res.getIdentifier("titleDivider", "id", "android");
View titleDivider = dialog.findViewById(titleDividerId);
if (titleDivider != null) {
titleDivider.setBackgroundColor(res.getColor(R.color.list_menu_divider));
}
}
}
您可以添加 builder.show();在返回之前验证消息之后;
像这样
public void login()
{
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setView(R.layout.login_layout);
builder.setTitle("Login");
builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener()
{
@Override
public void onClick(DialogInterface dialog, int id)
{
dialog.cancel();
}
});// put the negative button before the positive button, so it will appear
builder.setPositiveButton("Ok", new DialogInterface.OnClickListener()
{
@Override
public void onClick(DialogInterface dialog, int id)
{
Dialog d = (Dialog) dialog;
final EditText etUserName = (EditText) d.findViewById(R.id.etLoginName);
final EditText etPassword = (EditText) d.findViewById(R.id.etLoginPassword);
String userName = etUserName.getText().toString().trim();
String password = etPassword.getText().toString().trim();
if (userName.isEmpty() || password.isEmpty())
{
Toast.makeText(getApplicationContext(),
"Please Fill all fields", Toast.LENGTH_SHORT).show();
builder.show();// here after validation message before retrun
// it will reopen the dialog
// till the user enter the right condition
return;
}
user = Manager.get(getApplicationContext()).getUserByName(userName);
if (user == null)
{
Toast.makeText(getApplicationContext(),
"Error ethier username or password are wrong", Toast.LENGTH_SHORT).show();
builder.show();
return;
}
if (password.equals(user.getPassword()))
{
etPassword.setText("");
etUserName.setText("");
setLogged(1);
setLoggedId(user.getUserId());
Toast.makeText(getApplicationContext(),
"Successfully logged in", Toast.LENGTH_SHORT).show();
dialog.dismiss();// if every thing is ok then dismiss the dialog
}
else
{
Toast.makeText(getApplicationContext(),
"Error ethier username or password are wrong", Toast.LENGTH_SHORT).show();
builder.show();
return;
}
}
});
builder.show();
}
使用此代码,您可以防止在单击正按钮时关闭对话框。您也可以使用否定按钮实现相同的功能。
final AlertDialog alertDialog = alertDialogBuilder
.setCancelable(false)
.setTitle("TITLE");
.setPositiveButton("OK", null)
.setNegativeButton("CANCEL",
(dialog, id) -> {
dialog.cancel();
})
.show();
Button positiveButton = alertDialog.getButton(AlertDialog.BUTTON_POSITIVE);
positiveButton.setOnClickListener(v -> {
// check whatever you want
if(checkMyCondition())
dialog.cancel();
})
如果您使用的是 material design
,我建议您查看 material-dialogs。它为我修复了与当前打开的 Android 错误相关的几个问题(请参阅 78088),但最重要的是对于这张票它有一个 autoDismiss
标志,可以在使用 Builder
时设置。
为您的 DialogFragment
使用自定义布局,并在您的内容下添加一个 LinearLayout
,可以将其设置为无边框以匹配 Google Material Design。然后找到新创建的按钮并覆盖它们的 OnClickListener
。
例子:
public class AddTopicFragment extends DialogFragment {
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
// Get the layout inflater
LayoutInflater inflater = getActivity().getLayoutInflater();
final View dialogView = inflater.inflate(R.layout.dialog_add_topic, null);
Button saveTopicDialogButton = (Button) dialogView.findViewById(R.id.saveTopicDialogButton);
Button cancelSaveTopicDialogButton = (Button) dialogView.findViewById(R.id.cancelSaveTopicDialogButton);
final AppCompatEditText addTopicNameET = (AppCompatEditText) dialogView.findViewById(R.id.addTopicNameET);
final AppCompatEditText addTopicCreatedByET = (AppCompatEditText) dialogView.findViewById(R.id.addTopicCreatedByET);
saveTopicDialogButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// validate inputs
if(addTopicNameET.getText().toString().trim().isEmpty()){
addTopicNameET.setError("Topic name can't be empty");
addTopicNameET.requestFocus();
}else if(addTopicCreatedByET.getText().toString().trim().isEmpty()){
addTopicCreatedByET.setError("Topic created by can't be empty");
addTopicCreatedByET.requestFocus();
}else {
// save topic to database
Topic topic = new Topic();
topic.name = addTopicNameET.getText().toString().trim();
topic.createdBy = addTopicCreatedByET.getText().toString().trim();
topic.createdDate = new Date().getTime();
topic.save();
AddTopicFragment.this.dismiss();
}
}
});
cancelSaveTopicDialogButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
AddTopicFragment.this.dismiss();
}
});
// Inflate and set the layout for the dialog
// Pass null as the parent view because its going in the dialog layout
builder.setView(dialogView)
.setMessage(getString(R.string.add_topic_message));
return builder.create();
}
}
dialog_add_topic.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:padding="@dimen/activity_horizontal_margin"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:errorEnabled="true">
<android.support.v7.widget.AppCompatEditText
android:id="@+id/addTopicNameET"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Topic Name"
android:inputType="textPersonName"
android:maxLines="1" />
</android.support.design.widget.TextInputLayout>
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:errorEnabled="true">
<android.support.v7.widget.AppCompatEditText
android:id="@+id/addTopicCreatedByET"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Created By"
android:inputType="textPersonName"
android:maxLines="1" />
</android.support.design.widget.TextInputLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:text="@string/cancel"
android:layout_weight="1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/cancelSaveTopicDialogButton"
style="@style/Widget.AppCompat.Button.ButtonBar.AlertDialog" />
<Button
android:text="@string/save"
android:layout_weight="1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/saveTopicDialogButton"
style="@style/Widget.AppCompat.Button.ButtonBar.AlertDialog" />
</LinearLayout>
</LinearLayout>
科特林
val dialogView = LayoutInflater.from(requireContext()).inflate(R.layout.dialog_userinput, null)
val dialogBuilder = MaterialAlertDialogBuilder(requireContext(), R.style.AlertDialogTheme)
dialogBuilder.setView(dialogView)
dialogBuilder.setCancelable(false)
dialogBuilder.setPositiveButton("send",null)
dialogBuilder.setNegativeButton("cancel") { dialog,_ ->
dialog.dismiss()
}
val alertDialog = dialogBuilder.create()
alertDialog.show()
val positiveButton = alertDialog.getButton(AlertDialog.BUTTON_POSITIVE)
positiveButton.setOnClickListener {
val myInputText = dialogView.etxt_userinput.text.toString().trim()
if(myInputText.isNotEmpty()){
//Do something
}else{
//Prompt error
dialogView.etxt_userinput.error = "Please fill this"
}
}
我们只需使用 dialogBuilder
创建一个 AlertDialog
,然后根据需要设置肯定按钮
我找到了另一种方法来实现这一点......
第 1 步:将对话框打开代码放入方法 (或 C 中的函数)。
第 2 步:在 yes
(Your positiveButton) 的 onClick 内, 递归调用此对话框打开方法,如果您的条件不满足(通过使用 if...else...)。如下:
private void openSave() {
final AlertDialog.Builder builder=new AlertDialog.Builder(Phase2Activity.this);
builder.setTitle("SAVE")
.setIcon(R.drawable.ic_save_icon)
.setPositiveButton("Save", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
if((!editText.getText().toString().isEmpty() && !editText1.getText().toString().isEmpty())){
createPdf(fileName,title,file);
}else {
openSave();
Toast.makeText(Phase2Activity.this, "Some fields are empty.", Toast.LENGTH_SHORT).show();
}
})
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
dialogInterface.dismiss();
}
})
.setCancelable(false)
.create()
.show();
}
但这会使对话框消失片刻,它会立即再次出现。 :)
它可以用最简单的方法构建:
带有自定义视图和两个按钮(正和负)的警报对话框。
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()).setTitle(getString(R.string.select_period));
builder.setPositiveButton(getString(R.string.ok), null);
builder.setNegativeButton(getString(R.string.cancel), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// Click of Cancel Button
}
});
LayoutInflater li = LayoutInflater.from(getActivity());
View promptsView = li.inflate(R.layout.dialog_date_picker, null, false);
builder.setView(promptsView);
DatePicker startDatePicker = (DatePicker)promptsView.findViewById(R.id.startDatePicker);
DatePicker endDatePicker = (DatePicker)promptsView.findViewById(R.id.endDatePicker);
final AlertDialog alertDialog = builder.create();
alertDialog.show();
Button theButton = alertDialog.getButton(DialogInterface.BUTTON_POSITIVE);
theButton.setOnClickListener(new CustomListener(alertDialog, startDatePicker, endDatePicker));
Alert Dailog 正面按钮的 CustomClickLister:
private class CustomListener implements View.OnClickListener {
private final Dialog dialog;
private DatePicker mStartDp, mEndDp;
public CustomListener(Dialog dialog, DatePicker dS, DatePicker dE) {
this.dialog = dialog;
mStartDp = dS;
mEndDp = dE;
}
@Override
public void onClick(View v) {
int day1 = mStartDp.getDayOfMonth();
int month1= mStartDp.getMonth();
int year1 = mStartDp.getYear();
Calendar cal1 = Calendar.getInstance();
cal1.set(Calendar.YEAR, year1);
cal1.set(Calendar.MONTH, month1);
cal1.set(Calendar.DAY_OF_MONTH, day1);
int day2 = mEndDp.getDayOfMonth();
int month2= mEndDp.getMonth();
int year2 = mEndDp.getYear();
Calendar cal2 = Calendar.getInstance();
cal2.set(Calendar.YEAR, year2);
cal2.set(Calendar.MONTH, month2);
cal2.set(Calendar.DAY_OF_MONTH, day2);
if(cal2.getTimeInMillis()>=cal1.getTimeInMillis()){
dialog.dismiss();
Log.i("Dialog", "Dismiss");
// Condition is satisfied so do dialog dismiss
}else {
Log.i("Dialog", "Do not Dismiss");
// Condition is not satisfied so do not dialog dismiss
}
}
}
完毕
这可能是很晚的回复,但使用 setCancelable 可以解决问题。
alertDial.setCancelable(false);