Comment empêcher une boîte de dialogue de se fermer quand un bouton est cliqué

j'ai un dialogue avec EditText pour la saisie. Lorsque je clique sur le bouton" Oui " de la boîte de dialogue, il valide l'entrée, puis ferme la boîte de dialogue. Cependant, si l'entrée est erronée, je veux rester dans le même dialogue. Chaque fois, quelle que soit l'entrée, la boîte de dialogue doit être automatiquement fermée lorsque je clique sur le bouton "Non". Comment je peux désactiver ça? Au fait, J'ai utilisé PositiveButton et NegativeButton pour le bouton sur dialog.

620
demandé sur Suragch 2010-04-12 11:18:29

18 réponses

EDIT: Cela ne fonctionne que sur l'API 8+ comme indiqué par certains commentaires.

c'est une réponse tardive, mais vous pouvez ajouter un onShowListener à L'AlertDialog où vous pouvez alors surcharger le onClickListener du bouton.

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();
805
répondu Tom Bollwitt 2017-12-04 20:23:23

voici quelques solutions pour tous les types de dialogues, y compris une solution pour AlertDialog.Constructeur qui fonctionnera sur tous les niveaux de L'API (fonctionne en dessous de L'API 8, ce que l'autre réponse ici ne fait pas). Il existe des solutions pour les AlertDialogs utilisant AlertDialog.Builder, DialogFragment, et DialogPreference.

ci-dessous sont les exemples de code montrant comment Outrepasser le gestionnaire de bouton commun par défaut et empêcher la boîte de dialogue de se fermer pour ces différentes formes de dialogues. Tous les les exemples montrent comment empêcher le bouton positif de fermer le dialogue.

Note: une description du fonctionnement de la fermeture de dialogue sous le capot pour les classes android de base et pourquoi les approches suivantes sont choisies suit après les exemples, pour ceux qui veulent plus de détails


AlertDialog.Builder-Change le gestionnaire de boutons par défaut immédiatement après l'affichage()

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-override 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 - override 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.
                }
            });
}

explication des approches:

recherche à travers le code source Android L'implémentation par défaut D'AlertDialog fonctionne en enregistrant un gestionnaire de boutons commun à tous les boutons actuels D'OnCreate(). Quand un bouton est cliqué, le gestionnaire de bouton commun transmet l'événement de clic à n'importe quel gestionnaire que vous avez passé dans setButton() appelle puis rejette la boîte de dialogue.

Si vous souhaitez empêcher une boîte de dialogue de fermeture lorsque l'un de ces boutons est pressé, vous devez remplacer la commune gestionnaire de bouton pour l'affichage du bouton. Comme il est assigné dans OnCreate(), vous devez le remplacer après que L'implémentation par défaut D'OnCreate() est appelée. OnCreate est appelé dans le processus de la méthode show (). Vous pouvez créer une classe de dialogue personnalisée et surcharger OnCreate() pour appeler le super.OnCreate () remplace alors les gestionnaires de boutons, mais si vous faites un dialogue personnalisé, vous ne recevez pas le Builder gratuitement, dans quel cas quel est le but?

ainsi, en utilisant un dialogue de la façon dont il est conçu, mais avec le contrôle quand il est rejeté, une approche est d'appeler dialogue.Show() d'abord, puis obtenir une référence sur le bouton aide de la boîte de dialogue.getButton() pour remplacer le clic manipulateur. Une autre approche consiste à utiliser setOnShowListener() et à implémenter la recherche de la vue de bouton et le remplacement du gestionnaire dans L'OnShowListener. La différence fonctionnelle entre les deux est' presque ' nill, en fonction du thread qui crée à l'origine l'instance de dialogue. En regardant à travers le code source, l'onShowListener est appelé par un message posté à un gestionnaire tournant sur le thread qui a créé ce dialogue. Donc, puisque votre OnShowListener est appelé par un message posté sur la file d'attente de message il il est techniquement possible que l'appel de votre auditeur soit retardé quelque temps après la fin du show.

par conséquent, je crois que l'approche la plus sûre est la première: pour call show.Dialog (), puis immédiatement dans le même chemin d'exécution remplacer les gestionnaires de boutons. Puisque votre code que calls show () fonctionnera sur le thread GUI principal, cela signifie que quel que soit le code avec lequel vous suivez show() sera exécuté avant tout autre code sur ce thread, alors que le timing de L'OnShowListener la méthode est à la merci de la file d'attente de messages.

582
répondu Sogger 2017-03-17 16:32:23

j'ai écrit une classe simple (un AlertDialogBuilder) que vous pouvez utiliser pour désactiver la fonctionnalité de rejet automatique en appuyant sur les boutons de la boîte de dialogue.

il est compatible aussi avec Android 1.6, de sorte qu'il ne fait pas usage de L'OnShowListener (qui est disponible uniquement API >= 8).

donc, au lieu d'utiliser AlertDialog.Vous pouvez utiliser ce CustomAlertDialogBuilder. La partie la plus importante est que vous ne devez pas appeler créer() , mais seulement la méthode montre () . J'ai ajouté des méthodes comme setCanceledOnTouchOutside() et setOnDismissListener de sorte que vous pouvez toujours les placer directement sur le constructeur.

Je l'ai testé sur Android 1.6, 2.x, 3.x et 4.x donc ça devrait plutôt bien marcher. Si vous rencontrez des problèmes, veuillez les commenter ici.

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;
    }   
}

EDIT voici un petit exemple d'utilisation du 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();

Cheers,

Yuvi

32
répondu YuviDroid 2012-03-04 17:41:28

voici quelque chose si vous utilisez DialogFragment - qui est la façon recommandée de manipuler Dialogs de toute façon.

ce qui se passe avec la méthode setButton() D'AlertDialog (et j'imagine la même chose avec AlertDialogBuilder 's setPositiveButton() et setNegativeButton() ) est que le bouton que vous mettez (par exemple AlertDialog.BUTTON_POSITIVE ) avec elle va effectivement déclencher deux objets différents OnClickListener lorsqu'il est pressé.

le premier étant DialogInterface.OnClickListener , qui est un paramètre de setButton() , setPositiveButton() , et setNegativeButton() .

l'autre est View.OnClickListener , qui sera réglé pour rejeter automatiquement votre AlertDialog lorsque l'un de ses boutons est appuyé - et est réglé par AlertDialog lui-même.

Ce que vous pouvez faire est d'utiliser setButton() avec null comme le DialogInterface.OnClickListener , pour créer le bouton, et ensuite appeler votre méthode d'action personnalisée à l'intérieur de View.OnClickListener . Par exemple,

@Override
public Dialog onCreateDialog(Bundle savedInstanceState)
{
    AlertDialog alertDialog = new AlertDialog(getActivity());
    // set more items...
    alertDialog.setButton(AlertDialog.BUTTON_POSITIVE, "OK", null);

    return alertDialog;
}

alors, vous pouvez outrepasser la valeur par défaut AlertDialog 's buttons ' View.OnClickListener (qui autrement rejetterait la boîte de dialogue) dans le DialogFragment 's onResume() méthode:

@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
}

vous aurez besoin de définir cela dans la méthode onResume() parce que getButton() retournera null jusqu'à ce que le dialogue ait été affiché!

This devrait faire en sorte que votre méthode d'action personnalisée ne soit appelée qu'une seule fois, et la boîte de dialogue ne sera pas rejetée par défaut.

25
répondu Zhuiguang Liu 2012-05-19 21:57:16

une autre solution

je voudrais présenter une réponse alternative d'un point de vue UX.

pourquoi voudriez-vous empêcher un dialogue de se fermer quand un bouton est cliqué? Probablement c'est parce que vous avez un dialogue personnalisé dans lequel l'utilisateur n'a pas fait un choix ou n'a pas encore tout rempli complètement. Et s'ils ne sont pas finis, alors vous ne devriez pas leur permettre de cliquer le bouton positif du tout. Juste désactiver jusqu'à ce que tout est prêt.

les autres réponses ici donnent beaucoup de trucs pour passer outre le clic de bouton positif. Si C'était important à faire, Android n'aurait pas fait une méthode commode pour le faire? Ils ne l'ont pas fait.

à la place, le Dialogs design guide montre un exemple d'une telle situation. Le bouton OK est désactivé jusqu'à ce que l'utilisateur fasse un choix. Aucune justification astuces sont nécessaires à tous. Il est évident pour l'utilisateur que il faut encore faire quelque chose avant de continuer.

enter image description here

comment désactiver le bouton positif

voir la" documentation 1519340920 "Android pour créer une mise en page de dialogue personnalisé . Il est recommandé de placer votre AlertDialog dans un DialogFragment . Ensuite, tout ce que vous devez faire est de mettre les écouteurs sur les éléments de layout pour savoir quand activer ou désactiver le positif bouton.

Le positif bouton peut être désactivé comme ceci:

AlertDialog dialog = (AlertDialog) getDialog();
dialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(false);

voici un DialogFragment de travail entier avec un bouton désactivé positif tel que pourrait être utilisé dans l'image ci-dessus.

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);
    }
}

le dialogue personnalisé peut être exécuté à partir d'une activité comme celle-ci:

MyDialogFragment dialog = new MyDialogFragment();
dialog.show(getFragmentManager(), "MyTag");

Notes

  • par souci de brièveté, j'ai omis l'interface de communication pour passer l'utilisateur choix d'info retour à l'activité. La documentation montre comment cela se fait, cependant.
  • le bouton est toujours null dans onCreateDialog donc je l'ai désactivé dans onResume . Cela a l'effet indésirable de désactiver à nouveau la ti si l'utilisateur passe à une autre application et revient ensuite sans rejeter la boîte de dialogue. Cela pourrait être résolu en désélectionnant également tout choix d'utilisateur ou en appelant un Runnable de onCreateDialog à désactiver le bouton sur la boucle d'exécution suivante.

    view.post(new Runnable() {
        @Override
        public void run() {
            AlertDialog dialog = (AlertDialog) getDialog();
            dialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(false);
        }
    });
    

Liées

22
répondu Suragch 2017-09-02 15:45:25

inspiré par la réponse de Tom, je crois que l'idée ici est:

  • régler le onClickListener lors de la création du dialogue à null
  • définit ensuite un onClickListener après l'affichage de la boîte de dialogue.

vous pouvez outrepasser le onShowListener comme Tom. Alternativement, vous pouvez

  1. obtenir le bouton après l'appel de AlertDialog show()
  2. régler les boutons' onClickListener comme suit (légèrement plus lisible je pense).

Code:

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);
    }
});
16
répondu ericn 2016-06-10 05:19:52

pour Pre API 8 j'ai résolu le problème en utilisant un drapeau booléen, un écouteur de rejet et un dialogue d'appel.afficher à nouveau si le contenu de l'editText n'était pas correct. Comme ceci:

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;
8
répondu Steve 2012-05-12 11:06:39

La réponse à ce lien est une solution simple, et qui est compatible avec le droit de retour de l'API 3. C'est très similaire à la solution de Tom Bollwitt, mais sans utiliser le moins compatible OnShowListener.

Oui, vous pouvez. Vous avez essentiellement besoin de:

  1. créer le dialogue avec DialogBuilder
  2. afficher () le dialogue
  3. trouver les boutons dans le boîte de dialogue affichée et outrepasser leur onClickListener

j'ai fait des adaptations mineures au code de Kamen depuis que j'étendais une référence EditText.

@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)));
}

comme c'est amusant!

6
répondu lukeuser 2017-05-23 11:47:29

ce code fonctionnera pour vous, parce que j'ai eu un problème similaire et cela a fonctionné pour moi. :)

1 - Méthode Override Onstart () dans votre classe fragment-dialog.

@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
                }
            }
        });
    }
}
4
répondu Luis Nuñez 2013-04-25 04:50:46

Pour ProgressDialogs

pour empêcher le dialogue d'être automatiquement rejeté, vous devez définir le OnClickListener après le ProgressDialog est affiché, comme suit:

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.

    }

});
3
répondu Joshua Pinter 2014-07-29 01:38:37
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));
    }
}
}
3
répondu Eragonz91 2014-11-10 05:23:19

c'est probablement une réponse très tardive, mais utiliser setCancelable fera l'affaire.

alertDial.setCancelable(false);
3
répondu Navneeth T 2015-11-14 16:15:47

vous pouvez ajouter builder.show(); après la validation du message avant le retour;

comme ceci

    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();

}
3
répondu Person x Person212 2016-05-09 11:59:58

si vous utilisez material design je vous suggérerais de cocher material-dialogs . Il a corrigé plusieurs problèmes pour moi liés aux bogues Android actuellement ouverts (voir 78088 ), mais le plus important pour ce billet il a un drapeau autoDismiss qui peut être réglé en utilisant le Builder .

2
répondu theblang 2015-04-12 22:37:33

il pourrait être construit avec la manière la plus facile:

dialogue D'alerte avec Custom View et avec deux boutons (positif et négatif).

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));

CustomClickLister de Positif Bouton de Alerte Dailog :

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
        }

    }
}

fait

0
répondu Hiren Patel 2015-07-18 17:51:18

ma solution est simple, il suffit d'utiliser une mise en page personnalisée pour votre fragment de dialogue et d'ajouter un affichage en ligne sous votre contenu qui peut être considéré comme sans frontières pour correspondre à la conception de matériel Google, puis de trouver les boutons nouvellement créés et outrepasser leur OnClickListener: DialogFragment.code java:

    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>

C'est le résultat final:

0
répondu Ibrahim Hassan 2016-11-26 16:13:49

pour empêcher la boîte de dialogue de se fermer lorsque cliqué et il ne doit se fermer que lorsque l'internet est disponible

j'essaie de faire la même chose, car je ne veux pas que la boîte de dialogue soit fermée tant que l'internet n'est pas connecté.

Voici mon code

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();

    }

et voici mon code de gestionnaire de connectivité

 private boolean ifConnected()
{
    ConnectivityManager connectivityManager= (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo networkInfo=connectivityManager.getActiveNetworkInfo();
   return networkInfo!=null && networkInfo.isConnected();
}
0
répondu karan1.singh 2018-03-23 07:49:30

mettez ça dans votre classe utilitaire.

/*
     * Show Dialog with Title, Message, Button1, Button2 with Button1 and Button2 Listener
     */
    public AlertDialog showDialog(Context ctx, String title, String msg,
                                  String btn1, String btn2,
                                  OnClickListener listener1,
                                  OnClickListener listener2) {

        AlertDialog.Builder builder = new AlertDialog.Builder(ctx)
                .setTitle(title)
                .setMessage(msg)
                .setCancelable(true)
                .setPositiveButton(btn1, listener1);
        if (btn2 != null)
            builder.setNegativeButton(btn2, listener2);

        AlertDialog alert = builder.create();
        return alert;
    }

puis quand vous avez besoin d'afficher le dialogue

showDialog(getActivity(), "Title", "Message", "First button title", "Second button title",
                    new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            dialog.dismiss();
                            // TODO: 5/14/2018 first button clicked 
                        }
                    },
                    new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            dialog.dismiss();
                            // TODO: 5/14/2018 second button clicked
                        }
                    }).show();
0
répondu Khemraj 2018-05-13 18:34:11