前言
几个月前做的公司项目中一个需求,在使用 ViewPager+TabLayout+Fragment
情况下需要往其中Fragment
中添加两个Fragment
实现逻辑互动。这并不是头条中那种 Fragment 嵌套,问了下同学朋友并没有得到好的解决方案,下面是我的处理方法。
因为项目需求变动,这个功能可能要被替换,这里分享出来,希望能帮到需要的人
效果图
分析需求
这里我直接用项目来看需求
别嫌弃ui,非互联网公司只要求功能不怎么管界面美观 hahah
整个界面非常清楚,如果将画红框中模块去掉就是个简单的需求。点击该模块如下图,这是一个 Fragment
,为了区分,这里称作 FragmentA
再次点击箭头,切换到如下,也是个Fragment
,叫做FragmentB
最后点击箭头,切换显示下一个Fragment
,叫作FragmentC
这时候我们点击其他模块切换,显示都是此Fragment,所以不能简单的用 FragmentA 来包含 B、C。这里产生如下两个疑问。
Fragment
的布局不能动态替换,所以这里要创建几个Fragment
?- 这里
Activity FragmentAdapter
中到底添加多少个Fragment
作为数据适配?
这里我选择将 A、B、C当作三个平等的 Fragment,另外再创建个空白的 Fragment 用来放在 FragmentAdapter
中当作数据配合 ViewPager 显示。将 A、B、C 三个Fragment当作空白Fragment的子Fragment,嵌套在里面。然后在空白 Fragment 中写个控制类来控制显示切换这三个 Fragment 。
所以如上两个问题的答案是,一共要创建 4 个 Fragment。其中包含一个空白 Fragment 和三个 A、B、C Fragment。而 FragmentAdapter 中只添加 空白 Fragment。
这里并没有将其他模块 Fragment 算进去
关键代码
最外层 Activity 容器中代码,这里很简单,我只提取相关代码。比较容易看懂,都是 ViewPager+TabLayout+Fragment 相关内容
private HomeFragment homeFragment;
private DeviceListFragment deviceListFragment;
private PowerListFragment powerListFragment;
private MineFragment mineFragment;
//空白
public BlankFragment blankFragment;
/**
* 初始化碎片
*/
private void initFragment(Bundle savedInstanceState) {
if (savedInstanceState != null) {
homeFragment = (HomeFragment) getSupportFragmentManager().findFragmentByTag("powerObservaFragment");
deviceListFragment = (DeviceListFragment) getSupportFragmentManager().findFragmentByTag("deviceListFragment");
powerListFragment = (PowerListFragment) getSupportFragmentManager().findFragmentByTag("powerListFragment");
mineFragment = (MineFragment) getSupportFragmentManager().findFragmentByTag("mineFragment");
blankFragment = (BlankFragment) getSupportFragmentManager().findFragmentByTag("blankfragment");
} else {
homeFragment = new HomeFragment();
deviceListFragment = new DeviceListFragment();
powerListFragment = new PowerListFragment();
mineFragment = new MineFragment();
blankFragment = new BlankFragment();
}
mFragmentList.add(homeFragment);
mFragmentList.add(powerListFragment);
mFragmentList.add(deviceListFragment);
//空白
mFragmentList.add(blankFragment);
mFragmentList.add(mineFragment);
}
BlankFragment 的代码及布局,里面代码有两点要注意。
首先因为它里面包含了三个子Fragment,所以我们需要一个标识用来直到当前显示的是哪一个。
其次,需要用一个方法来控制切换 子 Fragment
代码如下,里面一些无关代码,比如懒加载等可根据实际情况来使用。
public class BlankFragment extends BaseFragment {
private BlankByFragmentController blankByFragmentController;
public int index = 0;
public int getIndex() {
return index;
}
public void setIndex(int index) {
this.index = index;
}
public BlankFragment(){
}
@Override
protected int getLayoutResource() {
return R.layout.frag_blank;
}
@Override
public void initPresenter() {
}
@Override
protected void lazyLoad() {
super.lazyLoad();
blankByFragmentController = BlankByFragmentController.getInstance(this, R.id.id_fragment);
showIndexFragment();
}
public void showIndexFragment(){
blankByFragmentController.showFragment(getIndex());
}
}
Fragment_blank.xml布局如下
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:id="@+id/id_fragment"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>
</LinearLayout>
BlankByFragmentController
里面都是 Fragment 切换显示 隐藏 的基础代码,可以直接复制使用。注意嵌套中的Fragment获取 FragmentManager 采用的方法。
public class BlankByFragmentController {
private int containerId;
private FragmentManager fm;
private ArrayList<Fragment> fragments;
private static BlankByFragmentController controller;
public static BlankByFragmentController getInstance(Fragment parentFragment, int containerId) {
if (controller == null) {
controller = new BlankByFragmentController(parentFragment, containerId);
}
return controller;
}
private BlankByFragmentController(Fragment fragment, int containerId) {
this.containerId = containerId;
//fragment嵌套fragment,调用getChildFragmentManager
fm = fragment.getChildFragmentManager();
initFragment();
}
private void initFragment() {
fragments = new ArrayList<Fragment>();
fragments.add(new BluetoothConnFragment());
fragments.add(new BluetoothListFragment());
fragments.add(new MyConnectBuletoothFragment());
FragmentTransaction ft = fm.beginTransaction();
for(Fragment fragment : fragments) {
ft.add(containerId, fragment);
}
ft.commitAllowingStateLoss();
}
public void showFragment(int position) {
hideFragments();
Fragment fragment = fragments.get(position);
FragmentTransaction ft = fm.beginTransaction();
ft.show(fragment);
ft.commitAllowingStateLoss();
}
public void hideFragments() {
FragmentTransaction ft = fm.beginTransaction();
for(Fragment fragment : fragments) {
if(fragment != null) {
ft.hide(fragment);
}
}
ft.commitAllowingStateLoss();
}
public Fragment getFragment(int position) {
return fragments.get(position);
}
public static void destoryController(){
controller = null;
}
}
操作切换 Fragment A、B、C 三个界面时记得修改标识值。比如在 FragmentA 中点击某个按钮切换到 FragmentB ,我们需要获取最外层容器的对象,然后通过它来获取 BlankFragment 对象修改 标识 index 值。
这样,BlankByFragmentController 才能控制显示最新的 index。
private MainActivity mainActivity;
mainActivity = (MainActivity) getActivity();
mainActivity.blankFragment.setIndex(1);
//关键代码
mainActivity.blankFragment.showIndexFragment();
完
ok 基本没什么问题。虽然这个功能我们最后没被使用,希望能帮到有需要的人吧。
文章原创自 guozh.net 。
本文由老郭种树原创,转载请注明:https://guozh.net/anlishijianviewpagertablayout-fragment-qiantaochuli/