前言
兩層Fragment在某些情況下,內層Fragment會顯示空白,這是一個比較常見的問題,百度到的一些帖子的方法有幾種,但是在即的項目中,只有下面這種起了作用。最後附上在一篇帖子上看到的出現這種情況的原因(反正我看不懂)。
解法
Activity中使用replace切換:
private void initFirstFragment() {
course_fragment = new Fragment_main_course(); //雙層Fragment的第一層,自定義的Fragment
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.course_main, course_fragment);
transaction.commit();
}
第一層Fragment添加:
private void initView(View view) {
tabLayout = view.findViewById(R.id.course_tab); //TabLayout
viewPager = view.findViewById(R.id.course_view_pager); //ViewPager
fragmentList = new ArrayList<>();
Fragment fragment_my_course = new Fragment_my_course();
Fragment fragment_all_course = new Fragment_all_course();
fragmentList.add(fragment_my_course);
fragmentList.add(fragment_all_course);
//重點就是下面這句話,一定要使用getChildFragmentManager()
adapter = new MyAdapter(getChildFragmentManager()); //自定義的適配器
viewPager.setAdapter(adapter);
tabLayout.setupWithViewPager(viewPager);
}
下面的原因分析來源於:https://blog.csdn.net/bingospunky/article/details/51352400
原因剖析
產生空白的根本原因是往ViewGroup裏添加子View失敗。
概念
要解釋明白這個過程首先需要明確幾個概念,不知道各位看官是否明確,我先在這裏列出來:
Fragment有一個叫mView的屬性,就是這個Fragment對應的View,歸根結底來說,Fragment就是代表一個View,FragmentManager操作Fragment就是操作Fragment所包含的View的添加、刪除等,只是在他上面加了一些類似生命週期的控制。
FragmentManager這個類是管理Fragment的類,比如添加Fragment就是這個類來實現的,它添加一個Fragment的時候回讓一個字符串與一個Fragment,如果這個字符串存在,就不會再添加這個Fragment。
FragmentManager這個類是與Actiity相關的,就是 * 一個FragmentAativity *,這一點很重要。
如果Fragment結合ViewPager使用,那麼Fragment是被Adapter調用FragmentManager添加的,與Fragment對應的字符串是在Adapter裏決定的,有Fragment類名相關的一個字符串。
約定
下面我們做如下約定:一個Activity通過一個ViewPager包含4個Fragment,分別命名爲mFragment1,mFragment2,mFragment3,mFragment4,其中mFragment3通過ViewPager包含3個Fragment,分別命名爲mFragment31,mFragment32,mFragment33。
操作:
1、顯示mFragment1
2、顯示mFragment3
3、顯示mFragment1
4、顯示mFragment3
在第4步的時候,內層的Fragment就會不顯示。
解釋
執行完第2步:mFragment3的onCreateView返回的View顯示在屏幕上,裏面添加了幾個子View,子View就是Fragment對應的View,而且這幾個子View是通過FragmentManager添加的,有String與之對應。
執行完第3步:mFragment3的onDestroyView方法會執行,代表着mView將被廢棄,下次會通過onCreateView創建一個新的mView。在FragmentManager裏mFragment32對應的字符串還存在,因爲我們都知道FragmentPagerAdapter裏的destroyItem沒有被執行,至於destroyItem方法什麼時候被執行你應該懂的。
執行完第4步:mFragment3的onCreateView方法被執行,返回的rootView顯示在界面上,然後我們的代碼裏會通過FragmentPagerAdapter給這個rootView添加Fragment,也就是給這個rootView添加子View。在我們添加Fragment的過程中,因爲在前面的過程中mFragment32對應的字符串已經存在了,所以添加mFragment32是失敗的,即給rootView添加子View失敗,所以界面裏顯示的就是空白。