ViewPager从另一个片段返回后具有空白页面的片段

Jak*_*bek 3 android android-fragments android-viewpager kotlin fragmentmanager

在我的应用程序中,我试图用ViewPagers 创建2个片段.这些片段有3个标签/页面,每个标签都带有RecyclerViews,它们应该由数据库支持,所以我将它们保存在一个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()
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

问题是,在远离SwipeFragment和返回之后,视图似乎是空的.然后,如果你导航到例如最左边的页面,最右边的一个"出现"(当你去它时).这导致中间页面保持空白.(它是说,之所以FragmentStatePagerAdapter在默认情况下只能保存当前页面和2点相邻的中间一个不与3个标签得到刷新的布局-我试了一下还与5个标签页,我能够把所有的他们来回走动).

经过一些调试后,我看到代表页面的片段没有被删除FragmentManager,但主要SwipeFragment是.FragmentManager即使在阅读了几乎所有的源代码之后,我也无法理解它是如何工作的.

如果我能以某种方式安全地从中删除碎片FragmentManager,它可能会起作用.
我已经尝试了一些保存状态的技术,但框架会自动执行(实际上可能是导致此问题的原因).
我只是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>
Run Code Online (Sandbox Code Playgroud)

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
    }
}
Run Code Online (Sandbox Code Playgroud)

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>
Run Code Online (Sandbox Code Playgroud)

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
    }
}
Run Code Online (Sandbox Code Playgroud)

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
}
Run Code Online (Sandbox Code Playgroud)

并且是RecyclerView.AdapterAndroid Studio生成 的基本实现

MyItemRecyclerViewAdapter.kt

class MyItemRecyclerViewAdapter(val values: List<DummyItem>) : 
        RecyclerView.Adapter<MyItemRecyclerViewAdapter.ViewHolder>() {
    ...
}
Run Code Online (Sandbox Code Playgroud)

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" />
Run Code Online (Sandbox Code Playgroud)

Bak*_*aii 6

你应该使用childFragmentManager而不是activity.supportFragmentManager内部SwipeFragment.

view.pager.adapter = DummyPagerAdapter(childFragmentManager, index)
Run Code Online (Sandbox Code Playgroud)

这里讨论getSupportFragmentManager()和之间的区别.getChildFragmentManager()

基本上,区别在于Fragment现在有自己的内部FragmentManager可以处理Fragments.子FragmentManager是处理仅包含在其中的片段中的片段的片段.另一个FragmentManager包含在整个Activity中.