31

I have a FragmentFR1 che contiene più NestedFragments; FRa, FRb, FRc. Questi NestedFragments vengono modificati premendo Buttons nel layout di FR1. Ciascuno del NestedFragments ha diversi campi di input al loro interno; che includono cose come EditTexts, NumberPickers e Spinners. Quando il mio utente passa e inserisce tutti i valori per lo NestedFragments, FR1 (il frammento principale) ha un pulsante di invio.Invio di dati da frammenti nidificati a frammento padre

Come posso dunque, recuperare i miei valori dalla mia NestedFragments e portarli in FR1.

  1. Tutti Views sono dichiarati e di programmazione gestita all'interno di ogni NestedFragment.
  2. Il genitore Fragment, FR1 gestisce la transazione del NestedFragments.

Spero che questa domanda è abbastanza chiara e non sono sicuro se il codice è necessario inviare, ma se qualcuno si sente altrimenti posso farlo.

EDIT 1:

Ecco come aggiungo la mia NestedFragments:

tempRangeButton.setOnClickListener(new View.OnClickListener() { 

     @Override 
     public void onClick(View v) { 

      getChildFragmentManager().beginTransaction() 
        .add(R.id.settings_fragment_tertiary_nest, tempFrag) 
        .commit(); 

     } 
    }); 

    scheduleButton.setOnClickListener(new View.OnClickListener() { 

     @Override 
     public void onClick(View v) { 

      getChildFragmentManager().beginTransaction() 
        .add(R.id.settings_fragment_tertiary_nest, scheduleFrag) 
        .commit(); 
     } 
    }); 

    alertsButton.setOnClickListener(new View.OnClickListener() { 

     @Override 
     public void onClick(View v) { 

      getChildFragmentManager().beginTransaction() 
        .add(R.id.settings_fragment_tertiary_nest, alertsFrag) 
        .commit(); 

     } 
    }); 

    submitProfile.setOnClickListener(new View.OnClickListener() { 

     @Override 
     public void onClick(View v) { 
      constructNewProfile(); 
     } 
    }); 

dove il mio metodo constructNewProfile() ha bisogno dei valori dalla mia NestedFragments.

public Fragment tempFrag = fragment_profile_settings_temperature 
     .newInstance(); 
public Fragment scheduleFrag= fragment_profile_settings_schedules 
      .newInstance(); 
public Fragment alertsFrag = fragment_profile_settings_alerts 
     .newInstance(); 

Quanto sopra si riferisce ai campi del frammento principale; e come sono inizialmente istanziati.

risposta

64

Il modo migliore è quello di utilizzare un'interfaccia:

  1. Dichiarare un'interfaccia nel frammento del nido

    // Container Activity or Fragment must implement this interface 
    public interface OnPlayerSelectionSetListener 
    { 
        public void onPlayerSelectionSet(List<Player> players_ist); 
    } 
    
  2. Collegare l'interfaccia al frammento genitore

    // In the child fragment. 
    public void onAttachToParentFragment(Fragment fragment) 
    { 
        try 
        { 
         mOnPlayerSelectionSetListener = (OnPlayerSelectionSetListener)fragment; 
    
        } 
        catch (ClassCastException e) 
        { 
          throw new ClassCastException(
           fragment.toString() + " must implement OnPlayerSelectionSetListener"); 
        } 
    } 
    
    
    @Override 
    public void onCreate(Bundle savedInstanceState) 
    { 
        Log.i(TAG, "onCreate"); 
        super.onCreate(savedInstanceState); 
    
        onAttachToParentFragment(getParentFragment()); 
    
        // ... 
    } 
    
  3. chiamata l'ascoltatore in clic del pulsante.

    // In the child fragment. 
    @Override 
    public void onClick(View v) 
    { 
        switch (v.getId()) 
        { 
         case R.id.tv_submit: 
          if (mOnPlayerSelectionSetListener != null) 
          {     
           mOnPlayerSelectionSetListener.onPlayerSelectionSet(selectedPlayers); 
          } 
          break; 
         } 
        } 
    
  4. avere il vostro frammento genitore implementa l'interfaccia.

    public class Fragment_Parent extends Fragment implements Nested_Fragment.OnPlayerSelectionSetListener 
    { 
         // ... 
         @Override 
         public void onPlayerSelectionSet(final List<Player> players_list) 
         { 
          FragmentManager fragmentManager = getChildFragmentManager(); 
          SomeOtherNestFrag someOtherNestFrag = (SomeOtherNestFrag)fragmentManager.findFragmentByTag("Some fragment tag"); 
          //Tag of your fragment which you should use when you add 
    
          if(someOtherNestFrag != null) 
          { 
           // your some other frag need to provide some data back based on views. 
           SomeData somedata = someOtherNestFrag.getSomeData(); 
           // it can be a string, or int, or some custom java object. 
          } 
         } 
    } 
    

Add Tag quando si esegue un'operazione frammento in modo da poter guardare in su in seguito per chiamare il suo metodo. FragmentTransaction

questo è il modo corretto di gestire la comunicazione tra i frammenti e frammento nido, è quasi la stessa per l'attività e frammento. http://developer.android.com/guide/components/fragments.html#EventCallbacks

C'è in realtà un altro modo ufficiale, sta usando il risultato dell'attività, ma questo è abbastanza buono e comune.

+1

getParentFragment() funziona solo in API 17+, quindi questo la risposta dovrebbe essere esplicita o non è abbastanza chiara – cesards

+0

@uDevel Cosa fa 'onAttachFragment (getParentFragment());' (nel passaggio 2)? È nel 'Attività'? –

+0

@antonio, no, è nel frammento annidato. Il punto è controllare se il frammento genitore ha implementato il listener in modo che sia possibile interagire con il frammento genitore dal frammento annidato chiamando il metodo definito nell'interfaccia del listener. – uDevel

2

È possibile utilizzare getChildFragmentManager() e trovare frammenti nidificati, farli correre e alcuni metodi per recuperare i valori di ingresso

+0

Uso già childFragmentManager per inviare le transazioni inizialmente nel mio frammento principale; tuttavia quando provo a chiamare getChildFragmentManager() in alcuni dei metodi dei miei frammenti parent restituisce un errore. – Tukajo

+0

Che tipo di errori? –

+0

quindi FR1 ha il metodo "constructFRaProfile()"; che chiamo dopo aver premuto invio in FR1. Devo chiamare childFragmentManager(). FindFragmentByTag ("FRa") ;? e quindi iniziare a recuperare i valori? – Tukajo

2

Il modo migliore per passare i dati tra i frammenti sta usando Interface. Ecco cosa dovete fare: In te frammento nidificato:

public interface OnDataPass { 
    public void OnDataPass(int i); 
} 

OnDataPass dataPasser; 

@Override 
public void onAttach(Activity a) { 
    super.onAttach(a); 
    dataPasser = (OnDataPass) a; 
} 

public void passData(int i) { 
    dataPasser.OnDataPass(i); 
} 

Nel frammento genitore:

public class Fragment_Parent extends Fragment implements OnDataPass { 
... 

    @Override 
    public void OnDataPass(int i) { 
     this.input = i; 
    } 

    btnOk.setOnClickListener(new OnClickListener() { 

     @Override 
     public void onClick(View v) { 
      Fragment fragment = getSupportFragmentManager().findFragmentByTag("0"); 
      ((Fragment_Fr1) fragment).passData(); 
     } 
    } 

} 
24

Invece di usare l'interfaccia, è possibile chiamare il frammento bambino attraverso di seguito:

((YourFragmentName) getparentFragment()).yourMethodName(); 
+3

Questa dovrebbe essere la risposta accettata IMHO. È una riga di codice e fa esattamente ciò che è necessario. Vorrei poterlo sorvolare di più –

+23

Se possibile, evitare questa soluzione. L'intero punto di un frammento è che è una sezione riutilizzabile dell'interfaccia utente. Se il frammento figlio contiene un riferimento codificato al frammento padre, si perde la riutilizzabilità del frammento figlio. Ecco perché le interfacce sono grandi, il genitore sceglierà come implementarle. –

+0

Non c'è un caso questa è una buona soluzione se non quella di essere pigri e di non usare il frammento correttamente. Se il frammento figlio sa quale classe è il frammento padre, probabilmente non si dovrebbe creare il frammento figlio e semplicemente inserire il codice nel frammento genitore. – uDevel

-4

nel mio caso (new Fragment()).hello(); lavorare bene per che chiami di un'altra funzione frammento

1

Controllare instanceOf prima di ottenere frammento madre che è migliore:

if (getParentFragment() instanceof ParentFragmentName) { 
    getParentFragment().Your_parent_fragment_method(); 
} 
Problemi correlati