在我的应用程序中,我试图用 ViewPager
创建 2 个 fragment 。这些 fragment 有 3 个选项卡/页面,每个选项卡/页面都有 RecyclerView
,它们应该由数据库支持,所以我将它们保存在 List
中。
class MainActivity : AppCompatActivity() {
val fragments = listOf(SwipeFragment(), SwipeFragment())
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
supportFragmentManager.beginTransaction().replace(R.id.placeholder, fragments[0]).commit()
button1.setOnClickListener {
supportFragmentManager.beginTransaction().replace(R.id.placeholder, fragments[0]).commit()
}
button2.setOnClickListener {
supportFragmentManager.beginTransaction().replace(R.id.placeholder, fragments[1]).commit()
}
}
}
问题是离开 SwipeFragment
并返回后, View 似乎是空的。然后,如果您导航到例如最左边的页面,最右边的页面“出现”(当您转到它时)。
这导致中间页面保持空白。 (原因是 FragmentStatePagerAdapter
默认只保留当前页面和 2 个相邻页面。中间页面在具有 3 个选项卡的布局中不会刷新 - 我也尝试过使用 5 个选项卡和我可以通过来回将它们全部带回来)。
经过一些调试后,我发现代表页面的 fragment 没有从 FragmentManager
中删除,但主要的 SwipeFragment
是。即使阅读了几乎所有的源代码,我也无法理解 FragmentManager
的真正工作原理。
如果我能够以某种方式安全地从 FragmentManager
中删除 fragment ,它可能会起作用。
我已经尝试了一些保存状态的技术,但框架会自动执行(这实际上可能是导致此问题的原因)。
我只是 Android 的初学者,所以无论如何可能有更好的方法来做到这一点。我会将其余文件留在这里以供引用。
activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.example.test.MainActivity">
<FrameLayout
android:id="@+id/placeholder"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="0"
android:orientation="horizontal">
<Button
android:id="@+id/button1"
style="?android:buttonBarButtonStyle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="button1" />
<Button
android:id="@+id/button2"
style="?android:buttonBarButtonStyle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="button2" />
</LinearLayout>
</LinearLayout>
SwipeFragment.kt
class SwipeFragment : Fragment() {
// TODO: set up and keep the database here
override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val view = inflater!!.inflate(R.layout.fragment_swipe, container, false)
view.tab_layout.setupWithViewPager(view.pager)
view.pager.adapter = DummyPagerAdapter(activity.supportFragmentManager, index)
return view
}
}
fragment_swipe.xml
<android.support.v4.view.ViewPager
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.test.SwipeFragment">
<android.support.design.widget.TabLayout
android:id="@+id/tab_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</android.support.v4.view.ViewPager>
ItemListFragment.kt
class ItemListFragment() : Fragment() {
// Or keep the database here?
// Probably not the best idea though
override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val view = inflater!!.inflate(R.layout.fragment_item_list, container, false)
if (view is RecyclerView) {
view.layoutManager = LinearLayoutManager(view.context)
view.adapter = MyItemRecyclerViewAdapter(DummyContent.ITEMS)
}
return view
}
}
DummyPagerAdapter.kt
class DummyPagerAdapter(manager: FragmentManager, val parentIndex: Int) :
FragmentStatePagerAdapter(manager) {
override fun getItem(position: Int): Fragment = ItemListFragment()
override fun getPageTitle(position: Int): CharSequence = "${ position + 1 }"
override fun getCount(): Int = 3
}
以及Android Studio生成的RecyclerView.Adapter
的基本实现
MyItemRecyclerViewAdapter.kt
class MyItemRecyclerViewAdapter(val values: List<DummyItem>) :
RecyclerView.Adapter<MyItemRecyclerViewAdapter.ViewHolder>() {
...
}
fragment_item_list.xml
<android.support.v7.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/list"
android:name="com.example.test.ItemListFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layoutManager="LinearLayoutManager"
tools:context="com.example.test.ItemListFragment"
tools:listitem="@layout/fragment_item" />
最佳答案
您应该在 SwipeFragment
中使用 childFragmentManager
而不是 activity.supportFragmentManager
。
view.pager.adapter = DummyPagerAdapter(childFragmentManager, index)
讨论了 getSupportFragmentManager()
和 getChildFragmentManager()
之间的区别 here .
Basically, the difference is that Fragment's now have their own internal FragmentManager that can handle Fragments. The child FragmentManager is the one that handles Fragments contained within only the Fragment that it was added to. The other FragmentManager is contained within the entire Activity.
关于android - 从另一个 fragment 返回到它后,带有 ViewPager 的 fragment 有空白页,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47842191/