web-dev-qa-db-fra.com

Envoi de données de fragments imbriqués vers le fragment parent

J'ai un FragmentFR1 Qui contient plusieurs NestedFragments; FRa, FRb, FRc. Ces NestedFragments sont modifiés en appuyant sur Buttons sur la mise en page de FR1. Chacun des NestedFragments contient plusieurs champs de saisie; qui incluent des choses comme EditTexts, NumberPickers et Spinners. Lorsque mon utilisateur parcourt et remplit toutes les valeurs de NestedFragments, FR1 (Le fragment parent) a un bouton d'envoi.

Comment puis-je alors récupérer mes valeurs dans mon NestedFragments et les importer dans FR1.

  1. Tous les Views sont déclarés et gérés par programme dans chaque NestedFragment.
  2. Le parent Fragment, FR1 Gère la transaction du NestedFragments.

J'espère que cette question est suffisamment claire et je ne sais pas si le code est nécessaire à publier, mais si quelqu'un pense le contraire, je peux le faire.

MODIFIER 1:

Voici comment ajouter mon 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();
        }
    });

où ma méthode constructNewProfile() a besoin des valeurs de mon 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();

Ce qui précède fait référence aux champs du fragment parent; et comment ils sont initialement instanciés.

43
Tukajo

La meilleure façon est d'utiliser une interface:

  1. Déclarez une interface dans le fragment de nid

    // Container Activity or Fragment must implement this interface
    public interface OnPlayerSelectionSetListener
    {
        public void onPlayerSelectionSet(List<Player> players_ist);
    }
    
  2. Attachez l'interface au fragment parent

    // 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. Appelez l'auditeur en cliquant sur le bouton.

    // 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. Demandez à votre fragment parent d'implémenter l'interface.

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

Ajoutez une balise lorsque vous effectuez une transaction fragmentée afin de pouvoir la rechercher par la suite pour appeler sa méthode. FragmentTransaction

C'est la bonne façon de gérer la communication entre le fragment et le fragment d'imbrication, c'est presque la même chose pour l'activité et le fragment. http://developer.Android.com/guide/components/fragments.html#EventCallbacks

Il existe en fait une autre méthode officielle, qui utilise le résultat de l'activité, mais celle-ci est assez bonne et courante.

85
uDevel

Au lieu d'utiliser l'interface, vous pouvez appeler le fragment enfant via ci-dessous:

( (YourFragmentName) getParentFragment() ).yourMethodName();
29
Raja Jawahar

Vous pouvez utiliser getChildFragmentManager() et trouver des fragments imbriqués, les obtenir et exécuter certaines méthodes pour récupérer les valeurs d'entrée

3
michal.luszczuk

La meilleure façon de transmettre des données entre fragments est d'utiliser Interface. Voici ce que vous devez faire: Dans votre fragment imbriqué:

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

Dans votre fragment parent:

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

}
3
Dariush Malek

Vérifiez instanceOf avant d'obtenir le fragment parent, ce qui est mieux:

if (getParentFragment() instanceof ParentFragmentName) {
  getParentFragment().Your_parent_fragment_method();
}
3
Pankaj

Vous pouvez utiliser le partage de données entre fragments.

public class SharedViewModel extends ViewModel {
    private final MutableLiveData<Item> selected = new MutableLiveData<Item>();

    public void select(Item item) {
        selected.setValue(item);
    }

    public LiveData<Item> getSelected() {
        return selected;
    }
}


public class MasterFragment extends Fragment {
    private SharedViewModel model;
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        model = ViewModelProviders.of(getActivity()).get(SharedViewModel.class);
        itemSelector.setOnClickListener(item -> {
            model.select(item);
        });
    }
}

public class DetailFragment extends Fragment {
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        SharedViewModel model = ViewModelProviders.of(getActivity()).get(SharedViewModel.class);
        model.getSelected().observe(this, item -> {
           // Update the UI.
        });
    }
}

Plus d'informations ViewModel Architecture

2
Ahmad Aghazadeh