2013-02-09 8 views
19

nicht aufgerufen. Ich habe eine einfache AlertDialog, die eine Liste einiger Elemente anzeigt, und nach dem Klicken auf eines der Elemente wird das angeklickte Element an die umschließende Activity zurückgegeben. Ich möchte auch einige Standardbehandlung durchführen, wenn der Benutzer den Dialog bricht (mit der Zurück-Taste) - genauer gesagt, ich möchte eine leere Zeichenfolge an die Aktivität in einem solchen Fall übergeben.OnCancelListener wird in DialogFragment

Wenn ich jedoch den Dialog in einem DialogFragment setzen (aus dem Kompatibilität Paket), die OnCancelListenernicht aufgerufen wird, wenn ich den Dialog mit der Zurück-Taste schließen. Was mache ich falsch?

public class SelectItemDialog extends DialogFragment { 

    public interface Callback { 
     void onItemSelected(String string); 
    } 

    private static final String ARG_ITEMS = "items"; 

    private Callback callback; 

    public static SelectItemDialog fromItems(Collection<String> items) { 
     SelectItemDialog fragment = new SelectItemDialog(); 
     fragment.setArguments(newArguments(items)); 
     return fragment; 
    } 

    private static Bundle newArguments(Collection<String> items) { 
     Bundle arguments = new Bundle(); 
     arguments.putStringArray(ARG_ITEMS, items.toArray(new String[items.size()])); 
     return arguments; 
    } 

    @Override 
    public void onAttach(Activity activity) { 
     super.onAttach(activity); 
     callback = (Callback) activity; 
    } 

    @Override 
    public Dialog onCreateDialog(Bundle savedInstanceState) { 
     final String[] items = getArguments().getStringArray(ARG_ITEMS); 
     return new AlertDialog.Builder(getActivity()) 
      .setTitle(R.string.dialog_select_email_title) 
      .setItems(items, new OnClickListener() { 
       @Override 
       public void onClick(DialogInterface dialog, int which) { 
        callback.onItemSelected(items[which]); 
       } 
      }) 
      .setOnCancelListener(new OnCancelListener() { 
       @Override 
       public void onCancel(DialogInterface dialog) { 
        // this code is not executed 
        callback.onItemSelected(""); 
        throw new RuntimeException("dialog cancelled"); 
       } 
      }) 
      .create(); 
    } 
} 

Antwort

42

Es könnte mit der Tatsache zu tun hat, dass es kein expliziter Aufruf aus dem Code zu cancel() ist. Die OnCancelListener Dokumentation sagt:

Dies wird nur aufgerufen, wenn der Dialog

aufgehoben wird, die wahrscheinlich einen expliziten cancel() Anruf benötigt.

Entweder eine positive/negative Schaltfläche mit einer OnClickListener erstellen, die DialogInterface#cancel() aufruft, oder eine OnDismissListener() mit einer zusätzlichen Prüfung verwenden, um zu sehen, ob auf ein Listenelement geklickt wurde.

, auch für eine Rück keypress zu hören und den Dialog abzubrechen, können Sie eine OnKeyListener einrichten, in this SO answer

Auch umrissen wie, sobald Sie den Dialog eingerichtet haben, wäre es auch eine gute Idee sein, Verwenden Sie Dialog#setCanceledOnTouchOutside(), wenn der Benutzer außerhalb des Dialogs tippt.

Bearbeiten: Der folgende Teil ist die einfache Möglichkeit, Ereignisse in einem DialogFragment abzubrechen.

Da Sie ein DialogFragment verwenden, hat diese Klasse eine sehr praktische Methode, DialogFragment#onCancel(), die, wenn die DialogFragment abgesagt aufgerufen wird. Mach deine Logik dort drin.

DialogFragments sind komplexer, mit einem etwas anderen Lebenszyklus als normale Dialoge. Überprüfen Sie daher zuerst die Dokumentation, wenn Sie eine bestimmte Dialog-basierte Methode haben, die Sie versuchen, auf eine DialogFragment zu portieren, einige Methoden existieren möglicherweise, die Ihrer neuen Implementierung erlauben, richtig zu funktionieren!

+1

I edited meine Frage. Ich möchte, dass der Code im 'OnCancelListener' aufgerufen wird, wenn der Dialog mit der * Zurück-Taste * geschlossen wird. – Natix

+0

@Natix sehen [diese Antwort] (http://stackoverflow.com/a/7815342/1815485), es macht das gleiche. Sie müssen einen 'OnKeyListener' hinzufügen, um nach dem Zurück-Tastendruck zu suchen. –

+0

Nun, diese Lösung sollte wahrscheinlich funktionieren, aber wenn ich den Dialog direkt innerhalb einer Aktivität ohne 'DialogFragment' anlege, wird der' OnCancelListener' aufgerufen - sowohl wenn die Zurück-Taste gedrückt wird, oder wenn der Benutzer außerhalb des Dialogs klickt. Ich verstehe nicht, warum das DialogFragment das Verhalten ändert. – Natix

11

Wenn Sie mit DialogFragment und wollen Taste hört wieder diese dann nutzen -

this.getDialog().setOnKeyListener(new Dialog.OnKeyListener() { 
     @Override 
     public boolean onKey(DialogInterface dialog, int keyCode, 
       KeyEvent event) { 
      if (keyCode == KeyEvent.KEYCODE_BACK) { 
       if (****) { 
        your logic 
       } 
       return true; 
      } 
      return false; 
     } 
    }); 
+0

Vielen Dank für die Beantwortung der Frage! es war der Teil von getDialog, der mich rauswarf! –

1

Eigentlich DialogFragment wenn Sie verwenden möchten, können Sie nie OnCancelListener oder OnDismissListener, um es hinzuzufügen, da der Dialog Fragment besitzt Rückrufe zu diesen Methoden!

Sie haben 3 Möglichkeiten:

1- gehen mit regelmäßigen Dialogen.
2- Setzen Sie das Dialogfeldfragment auf "Abbrechen" (false) und fügen Sie dem Dialogfeld eine Schaltfläche zum Abbrechen hinzu.
3- Check @Nikhil Pingle Antwort.

ist dies aus der Dokumentation des Dialog Fragment

* <p><em>Note: DialogFragment own the {@link Dialog#setOnCancelListener 
* Dialog.setOnCancelListener} and {@link Dialog#setOnDismissListener 
* Dialog.setOnDismissListener} callbacks. You must not set them yourself.</em> 
* To find out about these events, override {@link #onCancel(DialogInterface)} 
* and {@link #onDismiss(DialogInterface)}.</p> 
-1

Listener Abbrechen oder Zuhörer in DialogFragment Entlassen von onDismiss erreichen

  DialogFragment newFragment = new DatePickerFragment(); 
      newFragment.show(getFragmentManager(), "datePicker"); 
      newFragment.onDismiss(new DialogInterface(){ 

       @Override 
       public void cancel() { 
        // TODO Auto-generated method stub 

       } 

       @Override 
       public void dismiss() { 
        // TODO Auto-generated method stub 

       } 

      }); 
+0

Dieser Code bewirkt, dass der Dialog angezeigt und sofort wegen des Aufrufs von DialogFragment.onDismiss (...) zurückgewiesen wird. Der Benutzer wird es nicht einmal sehen. –

7

Hinweis: DialogFragment die Dialog.setOnCancelListener und Dialog besitzen. setOnDismissListener Rückrufe. Sie dürfen sie nicht selbst einstellen.

Um diese Ereignisse zu ermitteln, überschreiben Sie onCancel (DialogInterface) und onDismiss (DialogInterface).

public class SelectItemDialog extends DialogFragment { 

    @Override 
    public void onDismiss(DialogInterface dialog) { 
     super.onDismiss(dialog); 
     //your code hear 
     dialog.cancel(); 
    } 
} 

Und Sie sollten .setOnCancelListener remove()

+0

vielen Dank, klar den Weg zu gehen – noloman