android - studio - setcanceledontouchoutside
Evitar que DialogFragment se cierre cuando se hace clic en el botón (4)
Tengo un DialogFragment con una vista personalizada que contiene dos campos de texto donde el usuario debe ingresar su nombre de usuario y contraseña. Cuando se hace clic en el botón positivo, quiero validar que el usuario realmente ingresó algo antes de cerrar el diálogo.
public class AuthenticationDialog extends DialogFragment {
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
LayoutInflater inflater = getActivity().getLayoutInflater();
builder.setView(inflater.inflate(R.layout.authentication_dialog, null))
.setPositiveButton(getResources().getString(R.string.login), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// TODO
}
})
.setNegativeButton(getResources().getString(R.string.reset), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// TODO
}
});
return builder.create();
}
}
Entonces, ¿cómo puedo evitar que el diálogo se cierre? ¿Hay algún método que deba anular?
Esta es la solución "sweetspot" de las respuestas de Karakuri y Sogger. Karakuri estaba en el camino correcto, sin embargo, solo se puede obtener el botón de esa manera si ya se muestra (de lo contrario, es nulo, como se indica en los comentarios). Esta es la razón por la que la respuesta de Sogger funciona, sin embargo, prefiero la configuración en el mismo método, que es onCreateDialog
, y no adicionalmente en onStart
. La solución es envolver la búsqueda de los botones en OnShowListener
del diálogo.
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
// your dialog setup, just leave the OnClick-listeners empty here and use the ones below
final AlertDialog dialog = builder.create();
dialog.setOnShowListener(new DialogInterface.OnShowListener() {
@Override
public void onShow(final DialogInterface dialog) {
Button positiveButton = ((AlertDialog) dialog).getButton(DialogInterface.BUTTON_POSITIVE);
positiveButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(final View v) {
// TODO - call ''dismiss()'' only if you need it
}
});
Button negativeButton = ((AlertDialog) dialog).getButton(DialogInterface.BUTTON_NEGATIVE);
// same for negative (and/or neutral) button if required
}
});
return dialog;
}
Gracias a Luksprog, pude encontrar una solución.
AuthenticationDialog.java :
public class AuthenticationDialog extends DialogFragment implements OnClickListener {
public interface AuthenticationDialogListener {
void onAuthenticationLoginClicked(String username, String password);
void onAuthenticationResetClicked(String username);
}
private AuthenticationDialogListener mListener;
private EditText mUsername;
private EditText mPassword;
private Button mReset;
private Button mLogin;
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.authentication_dialog, container);
this.getDialog().setTitle(R.string.login_title);
mUsername = (EditText) view.findViewById(R.id.username_field);
mPassword = (EditText) view.findViewById(R.id.password_field);
mReset = (Button) view.findViewById(R.id.reset_button);
mLogin = (Button) view.findViewById(R.id.login_button);
mReset.setOnClickListener(this);
mLogin.setOnClickListener(this);
return view;
}
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 = (AuthenticationDialogListener) activity;
} catch (ClassCastException e) {
// The activity doesn''t implement the interface, throw exception
throw new ClassCastException(activity.toString()
+ " must implement AuthenticationDialogListener");
}
}
public void onClick(View v) {
if (v.equals(mLogin)) {
if (mUsername.getText().toString().length() < 1 || !mUsername.getText().toString().contains("@")) {
Toast.makeText(getActivity(), R.string.invalid_email, Toast.LENGTH_SHORT).show();
return;
} else if (mPassword.getText().toString().length() < 1) {
Toast.makeText(getActivity(), R.string.invalid_password, Toast.LENGTH_SHORT).show();
return;
} else {
mListener.onAuthenticationLoginClicked(mUsername.getText().toString(), mPassword.getText().toString());
this.dismiss();
}
} else if (v.equals(mReset)) {
mListener.onAuthenticationResetClicked(mUsername.getText().toString());
}
}
}
authentication_dialog.xml :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical" >
<EditText
android:id="@+id/username_field"
android:inputType="textEmailAddress"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:layout_marginLeft="4dp"
android:layout_marginRight="4dp"
android:layout_marginBottom="4dp"
android:hint="@string/username"
/>
<EditText
android:id="@+id/password_field"
android:inputType="textPassword"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:layout_marginLeft="4dp"
android:layout_marginRight="4dp"
android:layout_marginBottom="12dp"
android:fontFamily="sans-serif"
android:hint="@string/password"
/>
<View
android:layout_width="fill_parent"
android:layout_height="1dip"
android:background="?android:attr/dividerVertical"
/>
<LinearLayout
style="?android:attr/buttonBarStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingTop="0dp"
android:measureWithLargestChild="true" >
<Button
android:id="@+id/reset_button"
style="?android:attr/buttonBarButtonStyle"
android:layout_height="wrap_content"
android:layout_width="0dp"
android:layout_weight="1.0"
android:text="@string/reset"
/>
<Button
android:id="@+id/login_button"
style="?android:attr/buttonBarButtonStyle"
android:layout_height="wrap_content"
android:layout_width="0dp"
android:layout_weight="1.0"
android:text="@string/login"
/>
</LinearLayout>
</LinearLayout>
Reemplace los controladores de botones predeterminados en OnStart () para hacer esto.
@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();
}
@Override
public void onStart()
{
super.onStart(); //super.onStart() is where dialog.show() is actually called on the underlying dialog, so we have to do it after this point
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)
dismiss();
//else dialog stays open. Make sure you have an obvious way to close the dialog especially if you set cancellable to false.
}
});
}
}
Vea mi respuesta aquí https://.com/a/15619098/579234 para obtener más explicaciones y ejemplos en otros tipos de diálogo también.
Usted podría simplemente abrir el diálogo de nuevo. O bien, podría mantener el botón positivo deshabilitado hasta que haya entrada en ambos campos. Esto es bastante fácil si está creando el diseño en onCreateVew()
. Si está utilizando la clase AlertDialog.Builder
lugar, puede obtener un identificador para el botón así:
AlertDialog.Builder builder = new AlertDialog.Builder(context);
/* ... */
Dialog dialog = builder.create();
Button positiveButton = ((AlertDialog) dialog).getButton(DialogInterface.BUTTON_POSITIVE);
/* now you can affect the button */