在 ViewPager 内的片段之间传递参数
Passing arguments between Fragments that are inside a ViewPager
我正在处理由 ViewPager 托管的不同片段。
这样做的主要目的是因为我需要将纸质表格转换为数字表格,为了方便用户,我决定让用户在所有片段之间滑动并完成每个片段,直到表格结束。
我的目标是在最新滑动片段的末尾构造一个对象,因此,那时我将拥有来自以下片段的所有数据。
我已经研究并发现我可以使用 setArguments()
将一束数据从每个片段传递到下一个片段直到结束,这是一个好主意,因为如果用户想回来,他们可以更改一些参数并将滑动过程保持到最后,并且在最后一个片段中,我将使用所有片段中的所有参数来创建一个包含代表整个表单的所有数据的唯一对象。
这是我试过的
首先,我创建了一个简单的 ViewPager
适配器,用于在滑动时在不同片段之间切换
MyPagerAdapter
class MyPagerAdapter(fm:FragmentManager): FragmentStatePagerAdapter(fm) {
override fun getItem(position: Int): Fragment {
return when(position){
0 -> FragmentA.newInstance()
1 -> FragmentB.newInstance()
2 -> FragmentC.newInstance()
else -> {
FragmentA()
}
}
}
override fun getCount(): Int {
return 3
}
}
然后我在我的 MainActivity
中将此适配器与我的 viewpager 一起使用
主要活动
class MainActivity : FragmentActivity(), MainContract.MainView {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
setupViewPager()
}
override fun setupViewPager() {
viewPager.adapter = MyPagerAdapter(supportFragmentManager)
viewPager.disableScroll(true)
selectIndex(0)
}
override fun selectIndex(newIndex: Int) {
viewPager.currentItem = newIndex
}
override fun getFragment(position: Int): Fragment {
return MyPagerAdapter(supportFragmentManager).getItem(position)
}
}
这就是我需要将参数从 FragmentA 传递到 FragmentB
的地方
片段A
class FragmentA : Fragment() {
companion object {
fun newInstance(): FragmentA = FragmentA()
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_A, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
fab_continue.setOnClickListener {
val name = etxt_name.text.toString().trim()
val phone = etxt_phone.text.toString().trim()
val bundle = Bundle()
bundle.putString("name",name)
bundle.putString("phone",phone)
(activity as MainActivity).getFragment(1).arguments = bundle
(activity as MainActivity).selectIndex(1)
}
}
这里我假设
(activity as MainActivity).getFragment(1).arguments = bundle
获取并膨胀下一个片段,这个片段是FragmentB并将参数传递给它
同时
(activity as MainActivity).selectIndex(1)
只需使用FragmentB
滑动到下一页
问题
现在,问题是当应用程序启动时,getArguments 来自 FragmentB 会立即执行,但我什至没有滑动到它,或从 FragmentA 传递参数,然后生成 null 到 getArguments。
使用上面的代码,我认为从 FragmentA 按下我的 fab 按钮后,getFragment(1)
方法将实例化我的 FragmentB,但似乎没有做它应该做的事。
所以在我的 FragmentB
class FragmentB: Fragment() {
companion object {
fun newInstance(): FragmentB = FragmentB()
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Log.d("Argumentos:",""+arguments?.getString("name")) //This returns null
}
arguments?.getString("name")
returns 空
我认为您应该使用默认的 Factory Method 模板。创建 Fragment
时选中这些复选框
之后就可以看到带有构造函数的模板了newInstance()
像这样在 activity 中创建片段
BlankFragment.newInstance("First Thing", "Second String")
并且对于Fragment
,生成了访问方式
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
arguments?.let {
param1 = it.getString(ARG_PARAM1)
param2 = it.getString(ARG_PARAM2)
}
}
现在您可以获得这些值 param1
和 param2
。
如果要使用构造器方式:
public class BlankFragment extends Fragment {
public BlankFragment()
{} // Empty Constructor required
public BlankFragment(int someParam)
{
// your constructor
}
}
这也有效,但您将有 2 个构造函数,而您只能使用一个工厂方法(它由 AndroidStudio 自动生成!)
推荐的简单解决方案是使用 ViewModel
,如 View Model guide 中所述。喜欢的东西:
MyViewModel model = ViewModelProviders.of(yourActivity).get(MyViewModel.class); // in your activity
// in your fragments
model = ViewModelProviders.of(getActivity()).get(MyViewModel.class);
model.yourFunctionToChangeData(yourData);
// observer result in other fragments
model.getSelected().observe(this, { yourData ->
// Update the UI.
});
通过使用 ViewModel
,模型在 Activity 中创建一次,并在 Activity
中的所有片段之间共享。
我正在处理由 ViewPager 托管的不同片段。
这样做的主要目的是因为我需要将纸质表格转换为数字表格,为了方便用户,我决定让用户在所有片段之间滑动并完成每个片段,直到表格结束。
我的目标是在最新滑动片段的末尾构造一个对象,因此,那时我将拥有来自以下片段的所有数据。
我已经研究并发现我可以使用 setArguments()
将一束数据从每个片段传递到下一个片段直到结束,这是一个好主意,因为如果用户想回来,他们可以更改一些参数并将滑动过程保持到最后,并且在最后一个片段中,我将使用所有片段中的所有参数来创建一个包含代表整个表单的所有数据的唯一对象。
这是我试过的
首先,我创建了一个简单的 ViewPager
适配器,用于在滑动时在不同片段之间切换
MyPagerAdapter
class MyPagerAdapter(fm:FragmentManager): FragmentStatePagerAdapter(fm) {
override fun getItem(position: Int): Fragment {
return when(position){
0 -> FragmentA.newInstance()
1 -> FragmentB.newInstance()
2 -> FragmentC.newInstance()
else -> {
FragmentA()
}
}
}
override fun getCount(): Int {
return 3
}
}
然后我在我的 MainActivity
中将此适配器与我的 viewpager 一起使用主要活动
class MainActivity : FragmentActivity(), MainContract.MainView {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
setupViewPager()
}
override fun setupViewPager() {
viewPager.adapter = MyPagerAdapter(supportFragmentManager)
viewPager.disableScroll(true)
selectIndex(0)
}
override fun selectIndex(newIndex: Int) {
viewPager.currentItem = newIndex
}
override fun getFragment(position: Int): Fragment {
return MyPagerAdapter(supportFragmentManager).getItem(position)
}
}
这就是我需要将参数从 FragmentA 传递到 FragmentB
的地方片段A
class FragmentA : Fragment() {
companion object {
fun newInstance(): FragmentA = FragmentA()
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_A, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
fab_continue.setOnClickListener {
val name = etxt_name.text.toString().trim()
val phone = etxt_phone.text.toString().trim()
val bundle = Bundle()
bundle.putString("name",name)
bundle.putString("phone",phone)
(activity as MainActivity).getFragment(1).arguments = bundle
(activity as MainActivity).selectIndex(1)
}
}
这里我假设
(activity as MainActivity).getFragment(1).arguments = bundle
获取并膨胀下一个片段,这个片段是FragmentB并将参数传递给它
同时
(activity as MainActivity).selectIndex(1)
只需使用FragmentB
滑动到下一页问题
现在,问题是当应用程序启动时,getArguments 来自 FragmentB 会立即执行,但我什至没有滑动到它,或从 FragmentA 传递参数,然后生成 null 到 getArguments。
使用上面的代码,我认为从 FragmentA 按下我的 fab 按钮后,getFragment(1)
方法将实例化我的 FragmentB,但似乎没有做它应该做的事。
所以在我的 FragmentB
class FragmentB: Fragment() {
companion object {
fun newInstance(): FragmentB = FragmentB()
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Log.d("Argumentos:",""+arguments?.getString("name")) //This returns null
}
arguments?.getString("name")
returns 空
我认为您应该使用默认的 Factory Method 模板。创建 Fragment
时选中这些复选框
之后就可以看到带有构造函数的模板了newInstance()
像这样在 activity 中创建片段
BlankFragment.newInstance("First Thing", "Second String")
并且对于Fragment
,生成了访问方式
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
arguments?.let {
param1 = it.getString(ARG_PARAM1)
param2 = it.getString(ARG_PARAM2)
}
}
现在您可以获得这些值 param1
和 param2
。
如果要使用构造器方式:
public class BlankFragment extends Fragment {
public BlankFragment()
{} // Empty Constructor required
public BlankFragment(int someParam)
{
// your constructor
}
}
这也有效,但您将有 2 个构造函数,而您只能使用一个工厂方法(它由 AndroidStudio 自动生成!)
推荐的简单解决方案是使用 ViewModel
,如 View Model guide 中所述。喜欢的东西:
MyViewModel model = ViewModelProviders.of(yourActivity).get(MyViewModel.class); // in your activity
// in your fragments
model = ViewModelProviders.of(getActivity()).get(MyViewModel.class);
model.yourFunctionToChangeData(yourData);
// observer result in other fragments
model.getSelected().observe(this, { yourData ->
// Update the UI.
});
通过使用 ViewModel
,模型在 Activity 中创建一次,并在 Activity
中的所有片段之间共享。