Android 将数据从嵌套片段发送到父片段

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/23142956/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 06:49:52  来源:igfitidea点击:

Sending data from nested fragments to parent fragment

androidandroid-fragmentsparameter-passingandroid-nested-fragment

提问by Tukajo

I have a FragmentFR1that contains several NestedFragments; FRa, FRb, FRc. These NestedFragmentsare changed by pressing Buttonson FR1's layout. Each of the NestedFragmentshave several input fields within them; which include things like EditTexts, NumberPickers, and Spinners. When my user goes through and fills in all the values for the NestedFragments, FR1(the parent fragment) has a submit button.

我有一个FragmentFR1包含几个NestedFragments; FRa, FRb, FRc. 这些NestedFragments是通过按ButtonsonFR1的布局来更改的。每个NestedFragments都有几个输入字段;其中包括像EditTextsNumberPickersSpinners。当我的用户完成并填写 的所有值时NestedFragmentsFR1(父片段)有一个提交按钮。

How can I then, retrieve my values from my NestedFragmentsand bring them into FR1.

那么我如何才能从 my 中检索我的值NestedFragments并将它们带入FR1.

  1. All Viewsare declared and programmatically handled within each NestedFragment.
  2. The parent Fragment, FR1handles the transaction of the NestedFragments.
  1. 所有Views都在每个NestedFragment.
  2. FragmentFR1处理 的事务NestedFragments

I hope this question is clear enough and I am not sure if code is necessary to post but if someone feels otherwise I can do so.

我希望这个问题足够清楚,我不确定是否需要发布代码,但如果有人觉得我可以这样做。

EDIT 1:

编辑 1:

Here is how I add my NestedFragments:

这是我添加我的方法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();
        }
    });

where my constructNewProfile()method needs the values from my NestedFragments.

我的constructNewProfile()方法需要我的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();

The above refers to the fields of the parent fragment; and how they are initially instantiated.

以上是指父片段的字段;以及它们最初是如何实例化的。

回答by uDevel

The best way is use an interface:

最好的方法是使用接口:

  1. Declare an interface in the nest fragment

    // Container Activity or Fragment must implement this interface
    public interface OnPlayerSelectionSetListener
    {
        public void onPlayerSelectionSet(List<Player> players_ist);
    }
    
  2. Attach the interface to parent fragment

    // 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. Call the listener on button click.

    // 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. Have your parent fragment implement the 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.
               }
          }
     }
    
  1. 在嵌套片段中声明一个接口

    // Container Activity or Fragment must implement this interface
    public interface OnPlayerSelectionSetListener
    {
        public void onPlayerSelectionSet(List<Player> players_ist);
    }
    
  2. 将接口附加到父片段

    // 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. 单击按钮时调用侦听器。

    // 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. 让您的父片段实现接口。

     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 when you do fragment transaction so you can look it up afterward to call its method. FragmentTransaction

做fragment事务的时候加Tag,这样以后就可以查到调用它的方法了。片段事务

This is the proper way to handle communication between fragment and nest fragment, it's almost the same for activity and fragment. http://developer.android.com/guide/components/fragments.html#EventCallbacks

这是处理片段和嵌套片段之间通信的正确方法,活动和片段几乎相同。 http://developer.android.com/guide/components/fragments.html#EventCallbacks

There is actually another official way, it's using activity result, but this one is good enough and common.

实际上还有另一种官方方式,它使用活动结果,但这种方式已经足够好且常见。

回答by Raja Jawahar

Instead of using interface, you can call the child fragment through below:

您可以通过以下方式调用子片段,而不是使用接口:

( (YourFragmentName) getParentFragment() ).yourMethodName();

回答by Dariush Malek

The best way to pass data between fragments is using Interface. Here's what you need to do: In you nested fragment:

在片段之间传递数据的最佳方式是使用接口。这是你需要做的:在你嵌套的片段中:

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

In your parent fragment:

在您的父片段中:

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

}

回答by michal.luszczuk

You can use getChildFragmentManager()and find nested fragments, get them and run some methods to retrieve input values

您可以使用getChildFragmentManager()和查找嵌套片段,获取它们并运行一些方法来检索输入值

回答by Pankaj

Check for instanceOfbefore getting parent fragment which is better:

instanceOf在获取父片段之前检查哪个更好:

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

回答by Ahmad Aghazadeh

You can use share data between 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.
        });
    }
}

More Info ViewModel Architecture

更多信息ViewModel 架构

回答by Rachit Vohera

Too late to ans bt i can suggest create EditText object in child fragment

太晚了,我可以建议在子片段中创建 EditText 对象

EditText tx;

in Oncreateview Initialize it. then create another class for bridge like

在 Oncreateview 中初始化它。然后为桥创建另一个类

public class bridge{
public static EditText text = null; 
}

Now in parent fragment get its refrence.

现在在父片段中得到它的引用。

EditText childedtx = bridge.text;

now on click method get value

现在点击方法获取价值

onclick(view v){
childedtx.getText().tostring();
}

Tested in my project and its work like charm.

在我的项目中进行了测试,它的工作就像魅力一样。