当前位置: 首页 > news >正文

Android编程之Fragment动画加载方法源码详解

上次谈到了Fragment动画加载的异常问题,今天再聊聊它的动画加载loadAnimation的实现源代码:

Animation loadAnimation(Fragment fragment, int transit, boolean enter,
            int transitionStyle) {

接下来具体看一下里面的源码部分,我将一部分一部分的讲解,首先是:

        Animation animObj = fragment.onCreateAnimation(transit, enter,
                fragment.mNextAnim);
        if (animObj != null) {
            return animObj;
        }
开始的这部分,会调用Fragment的onCreateAnimation这个方法,在Fragment类中,这个方法为空,并没有现实:
    /**
     * Called when a fragment loads an animation.
     */
    public Animation onCreateAnimation(int transit, boolean enter, int nextAnim) {
        return null;
    }

如果你写的Fragment子类在继承Fragment后重写了这个方法内容,就可以在这里面得到动画。

如果你没有重写这个方法,那就会往下继续:

        if (fragment.mNextAnim != 0) {
            Animation anim = AnimationUtils.loadAnimation(mActivity, fragment.mNextAnim);
            if (anim != null) {
                return anim;
            }
        }
fragment.mNextAnim这个就是在我们添加或者替换fragment的时候,用的FragmentTransaction设置的那个动画,如上篇文章中后面附的那个例子:

        FragmentTransaction ft = getFragmentManager().beginTransaction();
        ft.setCustomAnimations(R.animator.fragment_rotate_enter,
                R.animator.fragment_rotate_exit,
                R.animator.fragment_rotate_pop_enter,
                R.animator.fragment_rotate_pop_exit);
具体是进入动画,还是退出动画,就要看当时的具体情况了,这个是不需要开发者操心的。

如果我们之前也没定义切换动画,那好吧,就要看我们是否设置transit和transitionStyle参数了:

        if (transit == 0) {
            return null;
        }
        
        int styleIndex = transitToStyleIndex(transit, enter);
        if (styleIndex < 0) {
            return null;
        }
再看一下transitToStyleIndex方法:

    public static int transitToStyleIndex(int transit, boolean enter) {
        int animAttr = -1;
        switch (transit) {
            case FragmentTransaction.TRANSIT_FRAGMENT_OPEN:
                animAttr = enter ? ANIM_STYLE_OPEN_ENTER : ANIM_STYLE_OPEN_EXIT;
                break;
            case FragmentTransaction.TRANSIT_FRAGMENT_CLOSE:
                animAttr = enter ? ANIM_STYLE_CLOSE_ENTER : ANIM_STYLE_CLOSE_EXIT;
                break;
            case FragmentTransaction.TRANSIT_FRAGMENT_FADE:
                animAttr = enter ? ANIM_STYLE_FADE_ENTER : ANIM_STYLE_FADE_EXIT;
                break;
        }
        return animAttr;
    }
所以,transit的值只能是:FragmentTransaction.TRANSIT_FRAGMENT_OPEN,FragmentTransaction.TRANSIT_FRAGMENT_CLOSE,FragmentTransaction.TRANSIT_FRAGMENT_FADE。然后,会根据这个值,调用系统自己的动画文件:

        switch (styleIndex) {
            case ANIM_STYLE_OPEN_ENTER:
                return makeOpenCloseAnimation(mActivity, 1.125f, 1.0f, 0, 1);
            case ANIM_STYLE_OPEN_EXIT:
                return makeOpenCloseAnimation(mActivity, 1.0f, .975f, 1, 0);
            case ANIM_STYLE_CLOSE_ENTER:
                return makeOpenCloseAnimation(mActivity, .975f, 1.0f, 0, 1);
            case ANIM_STYLE_CLOSE_EXIT:
                return makeOpenCloseAnimation(mActivity, 1.0f, 1.075f, 1, 0);
            case ANIM_STYLE_FADE_ENTER:
                return makeFadeAnimation(mActivity, 0, 1);
            case ANIM_STYLE_FADE_EXIT:
                return makeFadeAnimation(mActivity, 1, 0);
        }


根据之前这些逻辑,代码运行到这里,就应该算是结束了。但该方法,后面还有一些代码:

        if (transitionStyle == 0 && mActivity.getWindow() != null) {
            transitionStyle = mActivity.getWindow().getAttributes().windowAnimations;
        }
        if (transitionStyle == 0) {
            return null;
        }

对比了一样原始包中的FragmentManager,后面这段代码在那边还是有些差异的:
        int styleIndex = transitToStyleIndex(transit, enter);
        if (styleIndex < 0) {
            return null;
        }
        
        if (transitionStyle == 0 && mActivity.getWindow() != null) {
            transitionStyle = mActivity.getWindow().getAttributes().windowAnimations;
        }
        if (transitionStyle == 0) {
            return null;
        }
        
        TypedArray attrs = mActivity.obtainStyledAttributes(transitionStyle,
                com.android.internal.R.styleable.FragmentAnimation);
        int anim = attrs.getResourceId(styleIndex, 0);
        attrs.recycle();
        
        if (anim == 0) {
            return null;
        }
        
        return AnimatorInflater.loadAnimator(mActivity, anim);

所以,transitionStyle这个参数,在V4包这里是没有意义的。


好了,Fragment这个动画加载的方法内容就这些了。

相关文章:

  • Android编程之LayoutInflater的inflate方法详解
  • Android编程之LayoutInflater的inflate方法实例
  • Unity3D中目标相对自身的前后左右方位判断
  • 如何利用 WebBrowser 控件,显示 .GIF 动画?
  • FinalCode Group..C#代码规范V0.1
  • 这两段代码是不同的
  • using class in c#(simple)
  • OpenPOP.NET和Mail Monitor(邮件监测器)最新版本预发布
  • 新增两个Skin
  • 今天剪了头发
  • 笑话一则--相亲
  • CM Tools and CM Companies
  • 【EXLIBRIS】随笔记 005
  • 试考完了,不过工作又开始了。
  • 祝各位MM们节日快乐!
  • JavaScript 如何正确处理 Unicode 编码问题!
  • JS 中的深拷贝与浅拷贝
  • Android框架之Volley
  • Android组件 - 收藏集 - 掘金
  • JavaScript学习总结——原型
  • Linux编程学习笔记 | Linux IO学习[1] - 文件IO
  • PAT A1050
  • php的插入排序,通过双层for循环
  • PHP面试之三:MySQL数据库
  • vue从创建到完整的饿了么(11)组件的使用(svg图标及watch的简单使用)
  • Work@Alibaba 阿里巴巴的企业应用构建之路
  • 快速构建spring-cloud+sleuth+rabbit+ zipkin+es+kibana+grafana日志跟踪平台
  • 探索 JS 中的模块化
  • MPAndroidChart 教程:Y轴 YAxis
  • ​Spring Boot 分片上传文件
  • ​软考-高级-系统架构设计师教程(清华第2版)【第12章 信息系统架构设计理论与实践(P420~465)-思维导图】​
  • #HarmonyOS:基础语法
  • (Java实习生)每日10道面试题打卡——JavaWeb篇
  • (python)数据结构---字典
  • (转)【Hibernate总结系列】使用举例
  • (转载)CentOS查看系统信息|CentOS查看命令
  • (转载)Linux 多线程条件变量同步
  • .gitignore
  • .helper勒索病毒的最新威胁:如何恢复您的数据?
  • .net core 调用c dll_用C++生成一个简单的DLL文件VS2008
  • .NET下的多线程编程—1-线程机制概述
  • @PreAuthorize注解
  • @RequestMapping用法详解
  • @Transactional注解下,循环取序列的值,但得到的值都相同的问题
  • [ 蓝桥杯Web真题 ]-布局切换
  • [17]JAVAEE-HTTP协议
  • [20150321]索引空块的问题.txt
  • [3D基础]理解计算机3D图形学中的坐标系变换
  • [Angular] 笔记 16:模板驱动表单 - 选择框与选项
  • [Bada开发]初步入口函数介绍
  • [BUUCTF 2018]Online Tool
  • [BZOJ1089][SCOI2003]严格n元树(递推+高精度)
  • [C#]猫叫人醒老鼠跑 C#的委托及事件
  • [C++] 多线程编程-thread::yield()-sleep_for()
  • [iOS]把16进制(#871f78)颜色转换UIColor