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

问题描述 投票:0回答:9

我有一个

Fragment
FR1
,其中包含多个
Nested
Fragments
FRa
FRb
FRc
。这些
Nested
Fragments
通过按
Buttons
布局上的
FR1
进行更改。每个
Nested
Fragments
中都有多个输入字段;其中包括
EditTexts
NumberPickers
Spinners
等内容。当我的用户浏览并填写
Nested
Fragments
的所有值时,
FR1
(父片段)有一个提交按钮。

我怎样才能从我的

Nested
Fragments
检索我的值并将它们带入
FR1

  1. 所有
    Views
    均在每个
    Nested
    Fragment
    中声明并以编程方式处理。
  2. 父级
    Fragment
    FR1
    处理
    Nested
    Fragments
    的交易。

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

编辑1:

这是我添加我的

Nested
Fragments
:

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

我的

constructNewProfile()
方法需要我的
Nested
Fragments
中的值。

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

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

android android-fragments parameter-passing android-nested-fragment navigation-architecture
9个回答
108
投票

最好的方法是使用界面:

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

在进行fragment交易时添加Tag,以便事后查找并调用其方法。 Fragment交易

这是处理fragment和nestfragment之间通信的正确方法,对于activity和fragment来说几乎是一样的。 http://developer.android.com/guide/components/fragments.html#EventCallbacks

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


35
投票

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

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

4
投票

在片段之间传递数据的最佳方式是使用接口。您需要执行以下操作: 在您嵌套的片段中:

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

在您的父片段中:

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

}

4
投票

您可以在片段之间使用共享数据。

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

更多信息 ViewModel 架构


3
投票

您可以使用

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


3
投票

在获取父片段之前检查

instanceOf
哪个更好:

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

3
投票

Fragment之间传递数据可以使用FragmentManager来完成。从Fragment 1.3.0-alpha04开始,我们可以使用setFragmentResultListener()和setFragmentResult() API在Fragment之间共享数据。

官方文档


0
投票

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

EditText tx;

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

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

现在在父片段中获取其引用。

EditText childedtx = bridge.text;

现在点击方法获取值

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

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


0
投票

我们可以使用 Result API 将子片段的数据共享到父片段。

在build.gradle.kts(模块:app)中添加:

implementation("androidx.fragment:fragment-ktx:1.3.0")

在您必须发送数据的子片段中:

override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val res = "Top Fragment returned from Child"
       setFragmentResult("Data", bundleOf("data" to res))
        return inflater.inflate(R.layout.fragment_top_child, container, false)
    }

在您必须接收数据的父片段中:

 private fun getChildData(): String{
        childFragmentManager.setFragmentResultListener("Data", this) {
                _, bundle ->
            result = bundle.getString("data").toString()
        }

        return result
}
© www.soinside.com 2019 - 2024. All rights reserved.