Android过渡(Transition)动画解析源码

我们今天来聊聊系统是如何来处理过渡动画的。我们从一行最简单的代码开始分析:

Scene scene2 = Scene.getSceneForLayout(rootView, R.layout.scene2, context);
TransitionManager.go(Scene scene, Transition transition)

这里我们先通过布局定义了一个场景,然后通过TransitionManager进入场景,我们首先来看

Scene.getSceneForLayout:

  public static Scene getSceneForLayout(ViewGroup sceneRoot, int layoutId, Context context) {
    //缓存layout,避免同一个sence layout被多次的inflate        
    SparseArray<Scene> scenes = (SparseArray<Scene>) sceneRoot.getTag(
    com.android.internal.R.id.scene_layoutid_cache);

    if (scenes == null) {
        scenes = new SparseArray<Scene>();
        sceneRoot.setTagInternal(com.android.internal.R.id.scene_layoutid_cache, scenes);
    }
    Scene scene = scenes.get(layoutId);
    if (scene != null) {
        return scene;
    } else {
        scene = new Scene(sceneRoot, layoutId, context);
        scenes.put(layoutId, scene);
        return scene;
    }
}

产生一个Scene的代码比较简单,然后我们来看TransitionManager.go()go直接调用changeScene(Scene scene, Transition transition):

private static void changeScene(Scene scene, Transition transition) {
    //1\. 准备工作,保存当前视图树的状态
   sceneChangeSetup(sceneRoot, transitionClone);
    //2\. 将当前scene inflate到rootview
   scene.enter();
    //3\. 开启动画设置
   sceneChangeRunTransition(sceneRoot, transitionClone);
    }

这里我们可以看到启动一个Transition动画需要三步,下面一步步来分析。

1. 保存当前视图树的状态

我们在自定义Transiton动画时,曾经需要复写两个方法,captureStartValuescaptureEndValues来获取视图树的状态,那么这些方法具体是在那里被调用的呢?

首先我们来看一下sceneChangeSetup:

private static void sceneChangeSetup(ViewGroup sceneRoot, Transition transition) {
      //正在执行的动画,需要暂停
    ArrayList<Transition> runningTransitions = getRunningTransitions().get(sceneRoot);

    if (runningTransitions != null && runningTransitions.size() > 0) {
        for (Transition runningTransition : runningTransitions) {
            runningTransition.pause(sceneRoot);
        }
    }
      //这里赋值为true,表示start   不是一个很好的设计。。。
    if (transition != null) {
        transition.captureValues(sceneRoot, true);
    }
     // 如果当前有scene,执行回调
    Scene previousScene = Scene.getCurrentScene(sceneRoot);
    if (previousScene != null) {
        previousScene.exit();
    }
}

sceneChangeSetup先暂停了这个rootView上的所有Transition动画,然后调用captureValues开始记录视图树当前的状态,然后获取rootView当前的Scene,如果之前在这个rootViwe执行过Transition动画,那么这里就是上一次Transition动画之后最后的Scene

Transition.captureValues代码如下:

void captureValues(ViewGroup sceneRoot, boolean start) {
    if ((mTargetIds.size() > 0 || mTargets.size() > 0)
            && (mTargetNames == null || mTarge
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值