美文网首页fragmentAndroid知识Android开发
V4包下Fragment替换为源码下Fragment的心路历程

V4包下Fragment替换为源码下Fragment的心路历程

作者: 被风扬起的沙 | 来源:发表于2017-01-10 18:08 被阅读1350次

    首先来看一下android.support.v4.app.Fragmentandroid.app.Fragment这两包的区别:

    1.最低支持版本不同
    android.app.Fragment 兼容的最低版本是android:minSdkVersion="11" 即3.0版
    android.support.v4.app.Fragment 兼容的最低版本是android:minSdkVersion="4" 即1.6版
    2.需要导jar包
    fragment 在定义的时候,要导入的包不同
    android.support.v4.app.Fragment 需要引入包android-support-v4.jar
    android.app.Fragment 需要导入的是android-app.jar
    3.继承的父类不同,在fragmentManager 在Activity中取的方法不同
    android.support.v4.app.Fragment使用 fragmentManager=getSupportFragmentManager()获得 ,并且当前的类必须继成FragmentActivity
    android.app.Fragment使用 fragmentManager=getFragmentManager() 获得 ,继承Activity即可。
    4.<fragment>标签问题
    app.fragment和v4.fragment都是可以使用<fragment>标签。
    只是在使用的时候如果是app.fragment则没有什么特殊的地方继承Activity即可。
    当v4.fragment使用<fragment>标签的时候就要特别注意了:
    当这个Activity的布局中有<fragment>标签的时候,这个Activity必须继承FragmentActivity,否则就会报错。

    关于这个<fragment>标签的问题要着重强调一下,app.fragment是可以使用<fragment>标签的,很多网上都得文章说是不支持,是错误的。

    综上所述,在安卓4.4 5.0 乃至6.0系统的今天,源码下的Fragment可以使用了。也许你会说,闲着没事改V4包下的Fragment干嘛啊,没办法这都是被被逼的啊,产品需求。。。如图:

    Paste_Image.png

    原先的关注按钮直接跳转一个Activity展示别的页面,而现在需求是点击选择展示成另一个界面,并且下面的四个按钮是仍然展示的。

    很显然原先的Activity现在不可行了,只能是Fragment了。老大找了开源的项目,也是Fragment翻转的,核心的代码就是:

    getFragmentManager() .beginTransaction().setCustomAnimations(
    R.animator.card_flip_horizontal_right_in, 
    R.animator.card_flip_horizontal_left_out, 
    R.animator.card_flip_horizontal_left_in, 
    R.animator.card_flip_horizontal_right_out)                     
    .replace(R.id.container, attentionFragment) 
    .commit();
    

    在Values文件夹下新建animator文件夹置代码里面的四个动画文件,内容如图所示:

    Paste_Image.png

    万事具备只欠东风,程序运行点击按钮,程序就崩溃了。报错为:
    Unknown animation name: objectAnimator异常,谷歌搜索答案很多,终于找到一个靠谱的,网址如下
    http://blog.csdn.net/xyz_fly/article/details/36179515
    总结一下就是,在使用V4包中Fragment时,使用的切换动画效果,其动画文件中不能包含objectAnimator,Animator这类标签。如果必须要使用,请将工程中使用的V4包中Fragment相关类,换成源码中的Fragment相关类。
    意思很明确,就是V4包下 的Fragment不支持属性动画,只支持位移动画,要做旋转的话只能用源码中的Fragment。。。。仔细看了看三方代码里面用的是android.app.Fragment。

    原先项目中的Fragment的初始化时放在XML的<fragment>标签中的,一开始上网搜索经不权威人士的文章误导,以为android.app.Fragment不支持<fragment>标签,这样一改就改大发了,遂想另一个办法:

    不对Fragment进行属性动画设置,改为设置成替换的布局的属性动画,即对布局进行单独的属性动画设置:

    ObjectAnimator ra = ObjectAnimator.ofFloat(view, "rotationY", 0, 360);
    ra.setDuration(1500);
    ra.start();
    

    效果的话就不尽人意了,可以理解为空中旋转一周,体验很差,我们的要求是一般旋转180度就好,改为180度后,旋转话画面直接就直接倒置了,谁让是对布局进行的动画呢。这一方案也破灭了。。。

    后来发现android.app.Fragment也支持<fragment>标签了,这告诉我们要理论联系实际啊。要把项目里的V4包下的Fragment全部换成android.app.Fragment,因为项目里面没有做一个基类的BaseFragment,这工作量你懂得。。。 不光Fragment的引用要改,
    getSupportFragmentManager()也要改为getFragmentManager(),少年你以为这些就够了吗?后面还有更大的坑呢。。。

    改到FragmentPageAdapter的时候就出问题了,因为源码里面没有这个类。。。没办法,继续谷歌,找到如下文章:
    http://www.xiufm.com/thread-14680-1-1.html

    大体意思就是,原先改的时候就是在V4包下的FragmentPageAdapter里面修改getSupportFragmentManager()为getFragmentManager(),不过后来谷歌意识到了这个问题在V13包里面添加了这个FragmentPageAdapter类,也可以直接在build里面添加V13包的引用,但是为了一个类把包全引用有点浪费,不如直接在源码里面直接把相对应的类及其相关的都拷贝出来放到代码里面。

    期间引用的三方项目里面也有引用V4包FragmentPageAdapter的地方没办法,去看源码,改依赖为直接粘贴代码到项目中。

    另一个展示的页面如下布局:


    Paste_Image.png

    这是一个Fragment,里面用的是Viewpager,栏目跟健康号可以来回切换,上面挂载的是两个Fragment,经过上面的操作,动画可以完美运行了,但是当第二次进入这个页面的时候,挂载的Fragment的数据不展示了,挺费解的,遂谷歌一番。找到如下网页:
    http://blog.csdn.net/u014452224/article/details/45920315?spm=5176.8246799.blogcont.4.nDyPzm

    大体意思就是第二次加载的时候重复调用了onCreateView()这个方法,重新new了一个pageadapter导致子fragment不显示,原因的话现在还有点费解,先解决问题上代码,在主Fragment里面做如下操作

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {   
       if (view != null) {        
        unbinder = ButterKnife.bind(this, view);        
       ViewGroup parent = (ViewGroup) view.getParent();       
       if (parent != null) {            
        parent.removeView(view);       
       }      
      return view;   
     }   
     view = inflater.inflate(R.layout.activity_my_attention, null);    
      unbinder = ButterKnife.bind(this, view);   
      initView();   
     return view;
    }
    

    请注意我里面用的是ButterKnife来初始化话控件,

    unbinder = ButterKnife.bind(this, view);   
    

    这句代码必须放在每个判断语句里面,不然的话会报错。

    这样的话我们就完成了Fragment的替换,真是一波三折啊,动画效果的话也完美实现

    前人铺路,后人共勉啊。。。。

    相关文章

      网友评论

      本文标题:V4包下Fragment替换为源码下Fragment的心路历程

      本文链接:https://www.haomeiwen.com/subject/kpbkbttx.html