2012-10-16 13 views
38

Chciałbym zrobić dialog fragment, który zadaje pytanie "Czy na pewno?" z odpowiedzią "tak/nie".Najprostszy fragment dialogowy Tak/Nie

Spojrzałem na the documentation i jest naprawdę gadatliwy, rozchodząc się po całym miejscu, wyjaśniając, jak tworzyć zaawansowane okna dialogowe, ale bez żadnego kodu na temat tworzenia prostego okna dialogowego "Witaj świecie". Większość samouczków wykorzystuje przestarzały system okien dialogowych. Model official blog wydaje się niepotrzebnie skomplikowany i trudny do zrozumienia.

Jaki jest najprostszy sposób tworzenia i wyświetlania naprawdę podstawowego okna alarmowego? Dodatkowe punkty, jeśli używasz biblioteki pomocy technicznej.

+0

Spróbuj również http://stackoverflow.com/a/38500468/3496570 – Nepster

Odpowiedz

76

DialogFragment to tak naprawdę fragment, który otacza okno dialogowe. Możesz umieścić tam dowolne okno dialogowe, tworząc i zwracając okno dialogowe w metodzie onCreateDialog() w DialogFragment.

Herezje przykład DialogFragment:

class MyDialogFragment extends DialogFragment{ 
    Context mContext; 
    public MyDialogFragment() { 
     mContext = getActivity(); 
    } 
    @Override 
    public Dialog onCreateDialog(Bundle savedInstanceState) { 
     AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(mContext); 
     alertDialogBuilder.setTitle("Really?"); 
     alertDialogBuilder.setMessage("Are you sure?"); 
     //null should be your on click listener 
     alertDialogBuilder.setPositiveButton("OK", null); 
     alertDialogBuilder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() { 

      @Override 
      public void onClick(DialogInterface dialog, int which) { 
       dialog.dismiss(); 
      } 
     }); 


     return alertDialogBuilder.create(); 
    } 
} 

Aby utworzyć połączenie dialogowe:

new MyDialogFragment().show(getFragmentManager(), "MyDialog"); 

I aby zamknąć okno dialogowe skądś:

((MyDialogFragment)getFragmentManager().findFragmentByTag("MyDialog")).getDialog().dismiss(); 

Wszystko to kod będzie działać idealnie z biblioteką wsparcia, po prostu zmieniając importowanie, aby korzystać z klas biblioteki wsparcia.

+0

Dzięki, ale wydaje się powodować błąd "Nie można utworzyć wystąpienia fragmentu: upewnij się, że nazwa klasy istnieje, jest publiczna i ma pusty konstruktor, który jest publiczny 'jeśli wyjdę i ponownie wejdę do aplikacji, gdy okno dialogowe jest otwarte. Dodano pusty konstruktor, ale otrzymałem zerowy wskaźnik w mContext. – Muz

+8

@muz System Android wymaga klasy 'Fragment', aby mieć konstruktor z ** bez parametrów ** w celu utworzenia fragmentu, gdy jest to konieczne. W 'Fragment' masz odwołanie do działania, w którym ten fragment jest używany z metodą' getActivity() '(użyj go zamiast' mContext'). Również fragment musi być zadeklarowany w swoim własnym pliku java lub jako ** wewnętrzna statyczna klasa ** w innej klasie. W przeciwnym razie Android nie będzie mógł znaleźć twojego fragmentu, aby go utworzyć. – Luksprog

+0

@Luksprog Oh, ok, dzięki. Część 'getActivity()' naprawiła to. – Muz

12

Jaki jest najprostszy sposób na utworzenie i wyświetlenie naprawdę podstawowego okna dialogowego Alert ? Dodatkowe punkty, jeśli używasz biblioteki pomocy technicznej.

Wystarczy utworzyć DialogFragment (SDK lub biblioteki wsparcia) i zastąpić swoją metodę onCreateDialog do zwracania AlertDialog z pożądanym tekstu i zestaw przycisków na nim:

public static class SimpleDialog extends DialogFragment { 

    @Override 
    public Dialog onCreateDialog(Bundle savedInstanceState) { 
     return new AlertDialog.Builder(getActivity()) 
       .setMessage("Are you sure?").setPositiveButton("Ok", null) 
       .setNegativeButton("No way", null).create(); 
    } 

} 

coś zrobić, gdy użytkownik korzysta z jednego przycisku musisz podać instancję DialogInterface.OnClickListener zamiast referencji z mojego kodu.

2

powodu aktywny/Fragment cyklu@athor & podejście @lugsprog może zawieść, bardziej elegancki sposób to ** dostać kontekstu aktywności od sposobu onAttach i zapisać go jako słabego odniesienia ** (& unikać domyślny konstruktor w DialogFragment!, Aby przechodzić żadnego argumentu na dialog argumentów ruchu) tak:

public class NotReadyDialogFragment extends DialogFragment { 

    public static String DIALOG_ARGUMENTS = "not_ready_dialog_fragment_arguments"; 

    private WeakReference<Context> _contextRef; 

    public NotReadyDialogFragment() { 
    } 

    @Override 
    public Dialog onCreateDialog(Bundle savedInstanceState) { 

     /** example pulling of arguments */ 
     Bundle bundle = getArguments(); 
     if (bundle!=null) { 
      bundle.get(DIALOG_ARGUMENTS); 
     } 

     // 
     // Caution !!! 
     // check we can use contex - by call to isAttached 
     // or by checking stored weak reference value itself is not null 
     // or stored in context -> example allowCreateDialog() 
     // - then for example you could throw illegal state exception or return null 
     // 
     AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(_contextRef.get()); 
     alertDialogBuilder.setMessage("..."); 
     alertDialogBuilder.setNegativeButton("Przerwij", new DialogInterface.OnClickListener() { 

      @Override 
      public void onClick(DialogInterface dialog, int which) { 
       dialog.dismiss(); 
      } 
     }); 
     return alertDialogBuilder.create(); 
    } 

    @Override 
    public void onAttach(Activity activity) { 
     super.onAttach(activity); 
     _contextRef = new WeakReference<Context>(activity); 
    } 

    boolean allowCreateDialog() { 
     return _contextRef !== null 
       && _contextRef.get() != null; 
    } 

EDIT: & Jeśli chcesz odrzucić okno następnie:

  1. postarać się o to
  2. sprawdzić, czy to istnieje
  3. Sprawdź, czy jest wyświetlane:
  4. odrzucenie

coś takiego:

 NotReadyDialogFragment dialog = ((NotReadyDialogFragment) getActivity().getFragmentManager().findFragmentByTag("MyDialogTag")); 
    if (dialog != null) { 
     Dialog df = dialog.getDialog(); 
     if (df != null && df.isShowing()) { 
      df.dismiss(); 
     } 
    } 

EDIT2: & jeśli u chcą ustawić okno jako nieodwołalną u należy zmienić onCreatweDialog return takiego:

/** convert builder to dialog */ 
    AlertDialog alert = alertDialogBuilder.create(); 
    /** disable cancel outside touch */ 
    alert.setCanceledOnTouchOutside(false); 
    /** disable cancel on press back button */ 
    setCancelable(false); 

    return alert; 
+0

Rozumiem, że wywoływanie funkcji 'getActivity()' w konstruktorze może się nie powieść, ale dlaczego rozwiązanie zaproponowane przez Luksproga się nie powiedzie? Wywołanie 'getActivity()' w 'onCreateDialog()' jest dokładnie tym, co robi domyślna implementacja, przechowywanie mojego własnego odniesienia do dźwięków kontekstu, jak przeciwieństwo tego, co chcę robić. – Thorbear

+0

@ Thorbear getActivity() może zwrócić wartość null, gdy fragment nie jest dołączony do działania - możesz go użyć, ale powinieneś to sprawdzić - sam na przykład używając getResources() w fragmencie, gdy fragment nie jest dołączony – ceph3us

+0

Tak, i zwykle (zawsze) fragment nie jest dołączany podczas wywoływania konstruktora. Ale czy jest jakaś sytuacja, w której 'onCreateDialog()' zostanie wywołany, gdy fragment nie zostanie dołączony? Znowu, domyślna implementacja (biblioteka wsparcia) wywołuje 'getActivity()' w 'onCreateDialog()' bez sprawdzania, czy null, czy mówisz, że powinno? – Thorbear

2

Dla tych kodowania z Kotlin i Anko, teraz możesz wykonywać dialogi w 4 liniach kodu:

alert("Order", "Do you want to order this item?") { 
    positiveButton("Yes") { processAnOrder() } 
    negativeButton("No") { } 
}.show()