Skip to content

Fragment的操纵

JingYeoh edited this page Dec 18, 2017 · 6 revisions

系统为使用Fragment提供了一系列的方法,如:add/show/replace/remove等,但是事务在提交的时候,我们会遇到一系列问题,并且针对不同的场景,遇到的问题也不同,本框架的存在就是为了让Fragment的使用更加简单~

1、replace方法的使用(ReplaceFragment.java

replace方法实际上是addshow方法的合并,可以保证在使用的时候,一个container中只存在一个Fragment
在使用该方法的时候原生也很少会遇到问题,这是Fragment在使用过程中的最简单的一个方法。

Rigger.getRigger(this).replaceFragment(fragment, R.id.fr_content);

在Rigger中需要传入的对象为添加了@PuppetActivity/Fragment类。
replaceFragment(@NonNull Fragment fragment, @IdRes int containerViewId)方法中有两个参数,第一个参数是需要替换的fragment,第二个参数是待添加的fragment需要显示位置的视图id。
使用该方法后,在containerView中已存在的所有fragment都会被remove,然后需要添加的fragment进行addshow的操作

2、show方法的使用(ShowFragment.java

show方法在本框架中有多种操作形式,可以对Fragment进行统一add,可以直接操纵Fragmenttag来操纵具体的fragment

方式一:统一添加,通过操纵具体对象显示

Fragment fragments[] = new Fragment[4];
Rigger.getRigger(this).addFragment(containerViewId, fragments);
Rigger.getRigger(this).show(fragments[0]);

方式二:统一添加,通过操纵tag显示

Fragment fragments[] = new Fragment[4];
Rigger.getRigger(this).addFragment(containerViewId, fragments);
String tag = Rigger.getRigger(fragment[0]).getFragmentTag();
Rigger.getRigger(this).show(tag);

方式三:单独添加并显示

Rigger.getRigger(this).addFragment(fragment, containerViewId);

show方法在使用过后,原本在container中的fragment只会进行hide操作,并不会remove掉,当需要显示原来的fragment的时候,只需要通过showFragment方法,传入要显示的fragment对象或者tag

3、hide方法的使用

hide方法和show方法对应,用法也比较类似,不同的是,hidefragment必须已经存在,有两种方式hide

方式一:通过具体对象

Rigger.getRigger(this).hideFragment(fragment);

方式二:通过对象的tag

Rigger.getRigger(this).hideFragment(tag);

4、fragment栈管理,多级嵌套(StartFragment.java

这是我们在使用过程中最容易遇到问题的一个场景,我们常常需要对Fragment进行多级嵌套,有时候还需要对其进行栈式管理,但是原生提供的方法在使用过程中会遇到很多问题,本框架对这个场景中可能遇到的一系列问题进行了处理并简化了使用的Api。

要使用本场景下的方法,我们需要用到@Puppet注解中的参数了,我们先对本框架支持的Api进行介绍,然后对其中一些需要注意的地方进行说明。

1、入栈并显示

 Rigger.getRigger(this).startFragment(fragment);

通过上面的代码,可以看出,使用的Api很简单,但是此时的Fragment是添加到哪里呢?此时我们前面提到的@Puppet注解就起作用了,在这个注解中有一个参数containerViewId

  • containerViewId值不为0时,会添加到本类的栈中,并显示在container view中。
  • containerViewId为0的时候,会遍历自己所在的持有类,直到找到containerViewId有效的类(暂称为host),并添加fragmenthost的栈中然后显示。

这样设计可以让你在已经添加过的Fragment中使用本方法,也可以通过自己的需求来选择是否嵌套或者嵌套到哪一层。

2、同级显示场景

假如有三个类,AActivity/BFragment/CFragment,三个类的声明如下。

@Puppet(containerViewId = R.id.cotainer)
public class AActivity extend AppcompatActivity
@Puppet
public class BFragment extend Fragment
@Puppet
public class CFragment extend Fragment

我们在Activity中对BFragment进行了操作,Rigger.getRigger(aActivity).startFragment(bFragment),我们在BFragment中又对C进行操作,Rigger.getRigger(bFragment).startFragment(cFragment),那么此时的CFragment是在哪里入栈的呢?

答案CFragmentBFragment都在AActivity中进行的入栈操作,并显示在AActivitycontainer视图中。因为在BFragmentCFragment@PuppetcontainerViewId都没有传入参数,所以默认值为0,此时在使用startFragmet方法的时候会进行遍历操作直到找到有效的container之后才会进行入栈处理。

3、多层嵌套显示场景

假设我们四个类AActivity/BFragment/CFragmentDFragmentAActivityBFragment的声明如上面的代码不变,CFragmentDFragment的声明如下:

@Puppet(containerViewId = R.id.cContainer)
public class CFragment extend Fragment
@Puppet
public class DFragment extend Fragment

我们在Activity中对BFragment进行了操作,Rigger.getRigger(aActivity).startFragment(bFragment),然后在BFragment中又对C进行操作,Rigger.getRigger(bFragment).startFragment(cFragment),接着在CFragment中对DFragment进行操作,Rigger.getRigger(cFragment).startFragment(dFragment),那么此时的几个Fragment分别是在哪里入栈的呢?

答案BFragmentCFragment都是在AActivity中进行入栈的,DFragment是在CFragment进行入栈的。

4、出栈

本框架为Fragment出栈提供了一些列支持,默认是按返回键进行出栈,除此之外,提供了close()方法专门用于出栈操作。
出栈默认的操作是remove当前的栈顶元素,并对宿主的下一个栈顶元素进行显示。

Rigger.getRigger(this).close();

因为Fragment作为宿主视图的一部分,所以当栈内元素只有一个的时候,我们需要控制是否对宿主进行关闭操作,所以此处需要用到@Puppet注解中的一个属性,bondContainerView

  • bondContainerView = true :onBackPressed被触发的时候,当栈内元素为空或者只剩一个,宿主会跟着出栈或者finish,此时最后一个栈顶元素不执行转场动画。
  • bondContainerView = falseonBackPressed被触发的时候,只有在栈内元素为空,宿主自己才会出栈或者finish,所有的栈内元素都会执行转场动画。

5、打印栈内元素

本框架提供了栈内成员的实时打印,并使用了树状图来使打印的栈成员更加醒目。
打印的每条记录都为该Fragment的tag。

Rigger.getRigger(this).printStack();