Verhindern, dass DialogFragment geschlossen wird, wenn auf die Schaltfläche geklickt wird

Lesezeit: 9 Minuten

Benutzeravatar von Groppe
Groppe

Ich habe ein DialogFragment mit einer benutzerdefinierten Ansicht, die zwei Textfelder enthält, in die der Benutzer seinen Benutzernamen und sein Passwort eingeben soll. Wenn auf die positive Schaltfläche geklickt wird, möchte ich überprüfen, ob der Benutzer tatsächlich etwas eingegeben hat, bevor der Dialog geschlossen wird.

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

Wie kann ich also verhindern, dass der Dialog geschlossen wird? Gibt es eine Methode, die ich überschreiben sollte?

  • Wie kann ich verhindern, dass der Dialog geschlossen wird? – Verwenden Sie nicht die Standardeinstellung des Dialogs Buttons(die, mit der Sie eingestellt haben setPositiveButton etc). Stellen Sie Ihre eigenen ein Buttons zum Schließen des Dialogs und Implementieren der gewünschten Logik in ihr OnClickListeners. Sie sollten den Code für Ihre posten DialogFragment.

    – Benutzer

    6. Dezember 2012 um 15:29 Uhr


  • @Luksprog Code gepostet. Als ich versucht habe, was Sie vorgeschlagen haben, gibt das Abrufen von Verweisen auf die Elemente meiner benutzerdefinierten Ansicht aus onCreateDialog immer null zurück.

    – Groppe

    6. Dezember 2012 um 18:25 Uhr

  • An diesem Punkt wird der Dialog nicht auf dem Bildschirm gerendert. Versuchen Sie stattdessen, das Layout aufzublasen R.layout.authentication_dialog in ein View Referenz und suchen Sie dann nach der Buttons: View v = inflater.inflate(R.layout.authentication_dialog); Button b = (Button) v.findviewById(R.id.the_btn_id);.

    – Benutzer

    6. Dezember 2012 um 18:36 Uhr


  • @Luksprog Basierend auf dem, was Sie vorgeschlagen haben, habe ich eine Lösung gefunden. Ich werde meinen Code in einer Antwort posten, aber wenn Sie eine Antwort posten und auf meine verweisen möchten, gebe ich Ihnen die richtige Antwort.

    – Groppe

    6. Dezember 2012 um 19:30 Uhr


  • Der Code aus dem obigen Kommentar hat nicht funktioniert?

    – Benutzer

    6. Dezember 2012 um 19:44 Uhr

Benutzeravatar von Sogger
Sogger

Überschreiben Sie dazu die standardmäßigen Schaltflächen-Handler in OnStart().

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

Siehe meine Antwort hier https://stackoverflow.com/a/15619098/579234 für weitere Erklärungen und Beispiele auch für andere Dialogtypen.

  • Das funktioniert bei mir nicht. d.getButton(Dialog.BUTTON_POSITIVE) gibt null zurück.

    – Travis Christian

    18. April 2013 um 18:04 Uhr

  • @Travis Christian Sie müssen auf eine ältere Version von Android abzielen. Ich bin auch früher darauf gestoßen, ich habe meine Antwort aktualisiert, damit sie jetzt auf älteren Versionen funktioniert. Sie müssen einen leeren Klick-Listener an den ersten Aufruf übergeben.

    – Sogger

    19. April 2013 um 15:46 Uhr

  • Interessant, danke. Ich ziele auf 15 ab, also muss dies eine kürzliche Änderung gewesen sein.

    – Travis Christian

    19. April 2013 um 19:38 Uhr

  • Ich schätze, ich gehe nur davon aus, dass es ein Problem mit alt und neu war, da es auf einem neueren Telefon funktionierte (ICS, glaube ich), aber ich hatte ein altes Giggerbread-Telefon, an dem es nicht funktionierte, ohne den leeren Hörer zu definieren. Unabhängig davon hat es seit dem Hinzufügen des leeren Listeners an beiden gearbeitet.

    – Sogger

    22. April 2013 um 16:29 Uhr

  • Es hat geholfen, 10x. Aber sehr merkwürdig. Ist es nicht ein Fehler?

    – trickbz

    7. Januar 2015 um 2:36 Uhr

Benutzeravatar von Blacklight
Schwarzlicht

Dies ist die “Sweetspot” -Lösung der Antworten von Karakuri und Sogger. Karakuri war auf dem richtigen Weg, aber Sie können den Button nur so bekommen, wenn er bereits angezeigt wird (andernfalls ist er null, wie in den Kommentaren angegeben). Aus diesem Grund funktioniert die Antwort von Sogger, ich bevorzuge jedoch die Einrichtung mit der gleichen Methode, nämlich onCreateDialogund nicht zusätzlich in onStart. Die Lösung besteht darin, das Abrufen der Schaltflächen in die einzubinden OnShowListener des Dialogs.

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

  • Ich entschuldige mich für die Ablehnung, aber diese Methode hat das neue onClick, das in setOnShowListener für mich definiert ist, nicht ausgelöst (bei Lollipop versucht). Hast du das getestet?

    – Abraham Philipp

    5. August 2015 um 22:30 Uhr

  • Natürlich habe ich das mehrfach getestet und verwendet, und offensichtlich hat es nicht nur bei mir funktioniert. Bevor Sie eine Monate alte Antwort ablehnen, sollten Sie vielleicht darüber nachdenken, dass dies lange vor der Veröffentlichung von Lollipop gepostet wurde …

    – Schwarzlicht

    6. August 2015 um 5:22 Uhr

  • Hmm. Interessanter Punkt. Nach einem Blick auf meta.stackoverflow.com/q/265749/3000919 und meta.stackoverflow.com/q/265749/3000919 scheint der Konsens zu sein, dass solche Antworten idealerweise bearbeitet werden sollten, wobei darauf hingewiesen wird, dass sie veraltet sind, aber intakt bleiben für die Unterstützung von Legacy-Systemen. In diesem Fall ist jedoch die Nützlichkeit dieser Antwort als “Legacy” -Lösung nicht klar, da die am häufigsten bewertete Antwort in allen Versionen (ab sofort) funktioniert. Wenn Sie oben einen Haftungsausschluss hinzugefügt haben, der besagt, dass dies auf späteren Android-Versionen nicht funktioniert, würde ich gerne meine Ablehnung entfernen, um Sie nicht abzulehnen (Fortsetzung)

    – Abraham Philipp

    8. August 2015 um 6:56 Uhr

  • (Fortsetzung vom vorherigen Kommentar) die Wertschätzung, die Sie verdient haben, dass Sie eine Antwort gegeben haben, die zu diesem Zeitpunkt funktioniert hat. Außerdem scheine ich den gleichen Link zweimal in meinem vorherigen Kommentar gepostet zu haben. Das ist die Frage, die ich meinte: meta.stackexchange.com/q/11705

    – Abraham Philipp

    8. August 2015 um 7:02 Uhr

  • @AbrahamPhilip Um meine Antwort überprüfen oder bearbeiten zu können, habe ich ausschließlich zu diesem Zweck ein Testprojekt eingerichtet. Meine Lösung funktioniert immer noch und diese Antwort ist auch auf dem neuesten SDK (API-Level 22) noch gültig. Bitte überprüfen Sie Ihre Lösung, denn anscheinend machen Sie etwas falsch.

    – Schwarzlicht

    10. August 2015 um 11:22 Uhr

Dank Luksprog konnte ich eine Lösung finden.

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>

Sie könnten den Dialog einfach erneut öffnen. Oder Sie können die positive Schaltfläche deaktiviert lassen, bis in beide Felder eine Eingabe erfolgt. Dies ist einfach genug, wenn Sie das Layout in erstellen onCreateVew(). Wenn Sie die verwenden AlertDialog.Builder Klasse stattdessen können Sie ein Handle für die Schaltfläche wie folgt erhalten:

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 */

1431630cookie-checkVerhindern, dass DialogFragment geschlossen wird, wenn auf die Schaltfläche geklickt wird

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy