2012-05-08 21 views
7

Mam fragment, który na kliknięciu komponentu wyskakuje okienko dialogowe Dialog. Ten fragment okna dialogowego zawiera listę opcji. Po wybraniu opcji z listy chcę powiadomić fragment, aby można było uruchomić procedurę aktualizacji pól. zrobiłem coś jak tenUaktualnienie fragmentu opcji wyboru fragmentu okna dialogowego

@Override 
public void onClick(DialogInterface dialog, int item) { 
    updateSharedPreference(item); 
    Log.e("ProfilePersonaListDialog", "Click on dialog, inside onClick"); 
    OnCloseListDialogListener act = (OnCloseListDialogListener) getActivity(); 
    act.onDialogListSelection(); 

    dismiss(); 
} 

jednak ten getActivity() wzywa FragmentActivity a nie fragment, który wywołał fragment dialogowe. Mogę zabić aktualnie otwarty/działający fragment i zadzwonić do nowej instancji, która otrzyma zaktualizowane pola, ale jest to brudne rozwiązanie, którego wolałbym uniknąć.

Wszelkie sugestie dotyczące tej aktualizacji fragmentu po wybraniu opcji w oknie dialogowym ?.

+0

Korzystanie FragmentManager można osiągnąć ten sam – Relsell

Odpowiedz

7

Właśnie wracamy z rozwiązaniem. Mój problem polegał na przekazywaniu bieżącego fragmentu getTag() jako parametru show() dla DialogFragment. Jeśli ktoś zainteresowany tutaj pracuje próbka.

Tworzenie prostego słuchacza

public interface OnCloseListDialogListener { 
    public void onDialogListSelection(); 
}

Utwórz nowe okno, które rozciągają DialogFragment



public class ListDialogFragment extends DialogFragment implements DialogInterface.OnClickListener { 

    private PersonaData[] mPersonaData; 
    private String[] mPersonaName; 
    private final String TAG; 

    public static ListDialogFragment newInstance(PersonaData[] personaData, String tag) { 
     ListDialogFragment dialog = new ListDialogFragment(personaData, tag); 
     Bundle bundle = new Bundle(); 
     dialog.setArguments(bundle); 
     return dialog; 
    } 

    private ListDialogFragment(PersonaData[] personaData, String tag) { 
     this.mPersonaData = personaData.clone(); 
     this.TAG = tag; 
    } 

    @Override 
    public void onCreate(Bundle bundle) { 
     super.onCreate(bundle); 
     setCancelable(true); 
     int style = DialogFragment.STYLE_NORMAL, theme = 0; 
     setStyle(style, theme); 
    } 

    @Override 
    public Dialog onCreateDialog(Bundle savedInstanceState) { 
     AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); 
     builder.setTitle(R.string.dialog_title); 
     mPersonaName = getData();//Your own implementation here 
     builder.setNegativeButton("Cancel", this); 
     builder.setSingleChoiceItems(mPersonaName, -1, new SingleChoiceListener()); 
     return builder.create(); 

    } 

    @Override 
    public void onClick(DialogInterface dialogInterface, int i) { 
    } 

    private class SingleChoiceListener implements DialogInterface.OnClickListener { 
     @Override 
     public void onClick(DialogInterface dialog, int item) { 
      updateSharedPreference(item); 
      OnCloseListDialogListener act = (OnCloseListDialogListener) getFragmentManager().findFragmentByTag(TAG); 
      act.onDialogListSelection(); 
      dismiss(); 
     } 
    } 
} 

a potem w fragmencie, z którego chcesz zadzwonić to dialog zrobić jak mieszka. DIALOG jest tylko String stałe umieścić tam tylko dialogowe


SOME_CLICKABLE.setOnClickListener(new OnClickListener() { 

    @Override 
    public void onClick(View v) { 
     FragmentManager manager = getFragmentManager(); 
     ListDialogFragment dialog = ListDialogFragment.newInstance(mPersona, getTag()); 
     dialog.show(manager, DIALOG); 
    } 
});
+0

getTag() domyślnie zwraca null, czy najpierw musisz je ustawić? to przetrwa rotację, podczas gdy fragment okna dialogowego znajduje się na ekranie? – Maxrunner

1

tylko sposób, w jaki zrobił to wyżej i dodać czegoś takiego w swojej działalności:

public void onDialogListSelection() { 
    AnotherFragment anotherFragment = (AnotherFragment) getSupportFragmentManager() 
      .findFragmentById(R.id.anotherFragment); 
    anotherFragment.customMethodToNotifyListHasBeenSelected(); 
} 

Oczywiście, jeśli nie używać biblioteki Wsparcia następnie wywołać getFragmentManager zamiast getSupportFragmentManager.

+0

nie działa, w dół na fakt, że ten fragment jest sub-fragment zwany/sterted poprzez kliknięcie przycisku z innego fragmentu tak Nie jestem w stanie uzyskać identyfikatora, również próbowałem z tagiem, ale się nie udało :( –

+0

@peter_budo: Jeśli utworzysz wyskakujący fragment w środowisku wykonawczym w swoim kodzie, możesz zachować do niego odniesienie do późniejszego wykorzystania. –

+0

Przepraszam, czy możesz wyjaśnić, w jaki sposób? Dziękuję –

6

Konieczne jest w większości przypadków, aby było świadome, że działa w kontekście Activity jakiegoś opisu i dopuszczalnego dla fragmentu podrzędnego, aby wywołać metodę na interfejsie niejawnie zaimplementowanym przez działanie macierzyste (jak pokazano przez obsadę we fragmencie kodu). Kiedy dostaniesz swoje referencje działające tak, jak zauważy Tomasz, będziesz złoty.

Jednak, aby pomóc w ponownym użyciu fragmentu okna, sugerowałbym, aby wykorzystać BroadcastReceiver s. BroadcastReceiver po prostu nadaje komunikat: Zrobiłem "x". Aktywność nadrzędna lub w jakimkolwiek innym komponencie najwyższego poziomu może wtedy zadeklarować . Słucham "x". Gdy zdarzenie zostało wywołane w komponencie okna dialogowego, to wydarzenie zostanie zebrane przez nadrzędną aktywność użytkownika onReceive, gdzie można uruchomić niezbędny kod, aby zaktualizować swoje pola.

Na poziomie osobistym wolę to luźne sprzężenie niż podejście do interfejsu rzutowania, ponieważ zmusza mnie to do zastanowienia się nad przeznaczeniem każdego fragmentu i zachowania jego modułowości.

Jeśli chcesz zrobić zdjęcie, przeczytaj sekcję przewodnika programisty BroadcastReceivers i postępuj zgodnie z poniższymi instrukcjami;

  1. Zaimplementuj BroadcastReceiver w aktywności nadrzędnej. Zauważ, że wymagana jest implementacja metody onReceive.

  2. Zastąp metodę nadrzędnej aktywności onResume i zarejestruj działanie jako odbiorcę zdarzenia z zamierzonym działaniem "bla". Coś jak;

    @Override 
    protected void onResume() { 
    super.onResume(); 
    registerReceiver(this, new IntentFilter("blah")); 
    } 
    
  3. Zastąp metoda nadrzędnego Activity dodatkowych wyrejestrować działalność jako odbiornik, tak aby uniknąć „odbiorniki wyciekły” (dowiesz się).

    @Override 
    protected void onPause() { 
    super.onPause(); 
    unregisterReceiver(deleteSpotReceiver); 
    } 
    
  4. W swoim ogniem DialogFragmentonClick wydarzenie, które swoją aktywność rodzic jest „słuchanie” dla.

    @Override 
    public void onClick(DialogInterface dialog, int item) { 
        updateSharedPreference(item); 
        Log.e("ProfilePersonaListDialog", "Click on dialog, inside onClick"); 
        final Intent intent = new Intent(); 
        intent.setAction("blah"); 
        getActivity().sendBroadcast(intent); 
        dismiss(); 
    } 
    

Aktywność rodzic odbierze komunikat i można kontynuować przetwarzanie. Daj mi znać, jeśli zdecydujesz się przyjąć tę metodę.

+0

Doskonały mini przewodnik! Właśnie tego szukałem. – Mgamerz

+0

Świetny przewodnik! Nadal nie jestem pewien, czy wywołanie zwrotne jest wysyłane do działania. W moim przypadku mam szufladę nawigacji zawierającą kilka "głównych" fragmentów. Posiadanie aktywności przekazuje informacje o kliknięciu okna dialogowego, które wydaje się nieco zepsute. Czy nie byłoby lepiej zarejestrować słuchacza podczas tworzenia okna dialogowego? – Sam

+0

Witaj Sam, pod warunkiem, że ukryte Fragmenty nie rozumieją, gdzie znajdują się w hierarchii widoku, podejście pozostaje niezmienne. Jeśli Fragment A bezpośrednio komunikuje się z Fragmentem B/Aktywnością B jako konkretne typy, to są one niewłaściwie sprzężone. Alternatywa oddzwaniania jest popularna tam, gdzie Fragment A nie "wie" o tym, kto jest zainteresowany, po prostu kimś jest - może to być zakończone przez wywołanie zwrotne interfejsu typu słuchacza lub podejście EventBus.Jeśli chodzi o Androida, tak długo, jak nigdy nie piszesz ((MySoooperActivityOrFragment) getActivity()). InvokeMySooperMethod() Z nim wszystko jest w porządku;) – OceanLife

Powiązane problemy