J'ai un DialogFragment avec une vue personnalisée qui contient deux champs de texte où l'utilisateur doit entrer son nom d'utilisateur et son mot de passe. Lorsque le bouton positif est cliqué, je veux valider que l'utilisateur a effectivement entré quelque chose avant de fermer la boîte de dialogue.
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();
}
}
Alors, comment puis-je empêcher la boîte de dialogue de se fermer? Y a-t-il une méthode que je devrais remplacer?
Grâce à Luksprog, j'ai pu trouver une solution.
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>
Remplacez les gestionnaires de boutons par défaut dans OnStart () pour ce faire.
@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.
}
});
}
}
Voir ma réponse ici https://stackoverflow.com/a/15619098/579234 pour plus d'explications et d'exemples sur d'autres types de dialogues aussi.
C'est la solution "sweetspot" des réponses de Karakuri et de Sogger. Karakuri était sur la bonne voie, mais vous ne pouvez obtenir le bouton de cette façon que s'il est déjà affiché (il est nul sinon, comme indiqué dans les commentaires). C'est pourquoi la réponse de Sogger fonctionne, mais je préfère la configuration dans la même méthode, qui est onCreateDialog
, et pas en plus dans onStart
. La solution consiste à encapsuler la récupération des boutons dans le OnShowListener
de la boîte de dialogue.
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;
}