Activity & Fragment Transition学习概要--使用步骤

在这里我假设你已经看了我之前写的几篇关于Transition的文章(如果没有 请赶紧滚回去看Android Transition框架),并且对于Transition已经有了那么一丁点的了解。

从之前文章我们知道Transition是谷歌在4.4也就是KitKat版本新引入的API,主要实现view hierarchy之间的动画效果。15年在谷歌I/O大会上,谷歌又在Transition的基础上提高了一个逼格--Activity/Fragment Transition. 说白了也就是当你在不同Activity或者Fragment之间进行切换时,给用户一个略屌的动画效果,使你的App更加的高大上。这一节我们就来看看什么是Activity/Fragment Transition.


What is Activity/Fragment Transition ???

Activity/Fragment Transition是建立在与它类似的特征--Transition的基础之上的。在KitKat版本上,Transition框架给我们提供了很方便的API来实现在不同的UI进行动画切换。这个框架有两个核心概念:Scene和Transition。一个Scene描述了一个应用的UI的状态,而一个Transition定义了在两个不同的Scene之间进行过渡的动画效果。

当一个Scene发生改变时,Transition主要有以下两点职责需要去履行:

1)捕获起始Scene和终止Scene中每一个View的状态信息

2)创建一个动画对象--此动画对象是基于两个Scene中View状态的区别来被创建的

举一个很简单的例子,以下代码中的TransitionActivity.java中包含四个不同颜色的view区域,当用户点击最外层的LinearLayout时,会将这四个View通过Slide的Transition效果滑出屏幕。效果如下:


TransitionActivity.java

package material.danny_jiang.com.mytransitdemo;

import android.app.Activity;
import android.os.Bundle;
import android.transition.Fade;
import android.transition.TransitionManager;
import android.view.View;
import android.view.ViewGroup;

public class TransitionActivity extends Activity implements View.OnClickListener {
    private ViewGroup mRootView;
    private View mRedBox, mGreenBox, mBlueBox, mBlackBox;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.transition_activity);

        mRootView = (ViewGroup) findViewById(R.id.layout_root_view);
        mRootView.setOnClickListener(this);

        mRedBox = findViewById(R.id.red_box);
        mGreenBox = findViewById(R.id.green_box);
        mBlueBox = findViewById(R.id.blue_box);
        mBlackBox = findViewById(R.id.black_box);
    }

    @Override
    public void onClick(View v) {
        TransitionManager.beginDelayedTransition(mRootView, new Slide());
        toggleVisibility(mRedBox, mGreenBox, mBlueBox, mBlackBox);
    }

    private static void toggleVisibility(View... views) {
        for (View view : views) {
            boolean isVisible = view.getVisibility() == View.VISIBLE;
            view.setVisibility(isVisible ? View.INVISIBLE : View.VISIBLE);
        }
    }
}

transition_activity.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"
    android:id="@+id/layout_root_view"
    >

    <View
        android:id="@+id/red_box"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:background="#FF0000"/>

    <View
        android:id="@+id/green_box"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:background="#00FF00"/>

    <View
        android:id="@+id/blue_box"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:background="#0000FF"/>

    <View
        android:id="@+id/black_box"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:background="#000000"/>

</LinearLayout>

WTF!!!就这么几行代码??没有错 就是这么的神奇! 接下来我们看看幕后操盘手究竟是如何工作来实现Fade效果的。在transition_activity.xml文件中4个View视图默认都是可见状态。

1)当用户点击最外层的LinearLayout时,调用onClick方法,在此方法中我们调用了TransitionManager.beginDelayedTransition(mRootView, new  Slide())方法,并传入参数mRootView和Slide对象。在此方法中,系统会立即调用Transition对象(也就是传入的Slide对象)的captureValues方法,captureValues方法中遍历Scene中每一个View并记录下每一个View的visibility属性状态值。

2)当TransitionManager.beginDelayedTransition方法返回之后,我们主动将这4个View的visibility属性置为false状态。

3)紧接着,Transition框架会调用captureEndValues方法遍历Scene中所有的View,并记录下此时4个View的visibility属性值(此时所有的view已经被置为false状态)

4)当起始的状态和结束的状态都获取了之后,Transition(Slide)就需要根据这两个状态的区别创建一个Animator对象--createAnimator() : Transition(Slide)会分析出起始状态每一个View都是可见状态,当结束时每一个View都是不可见状态。Slide(transition的子类)会利用这些信息创建一个用于把view的alpha属性变为0的AnimatorSet,并且将此AnimatorSet对象返回。

5) framework会运行返回的Animator,导致所有的View都逐渐从屏幕中移出

上面这个简单的案例使我们了解了两个Transition框架的优势:

1)Transition框架抽象和封装了属性动画的概念,从而大大的减少了代码量(你可以意淫一下,如果使用属性动画实现上面的效果该是多少行代码 吼吼!)。我们猿类需要做的只是设置view的起始属性状态值,有了起始属性状态值,Transition框架就会自动创建相应的属性动画来演示这两个不同状态值得过渡效果

2)如果想修改在不同Scene之间执行的动画效果,只需要修改传入的Transition对象即可,上面案例中我们使用的是Slide Transition对象,如果将它替换成Fade对象 比如下面代码所示:

TransitionManager.beginDelayedTransition(mRootView, new Fade());
再执行此程序,则运行效果如下:






~~~~~~~~~~~以上是对Transition知识额回顾,接下来看看在5.0 Lollipop中Transition加入了哪些高逼格的特征~~~~~~~~~~~~~


Shared Element Transition

没错就是Shared Element Transition。从Android 5.0开始,Transition框架甚至可以让用户在不同Activity或者Fragment间进行切换时提供用户一些酷炫的动画效果(果然变态,不过我喜欢) 。实际上 我们也知道即使没有Transition,我们在Activity之间进行切换时也可以实现动画效果,比如如下代码:Activity.overridePendingTransition() / Fragment.setCustomAnimation()。

通过这两个方法确实也可以,但是存在一定的局限性:这两个动画效果都是将整个Activity或者Fragment的视图当做动画的对象。Lollipop在此基础上又更进了一步,让单独的view也可以在进入或者退出其布局容器中时发生动画效果,甚至还可以在不同的activity/Fragment中共享一个view。比如如下效果(我就问你屌不屌):


虽然我们无法查看它的源码,但是我敢打赌它用了以下的transition:

activity A 中exit和reenter transition是为null的,因为A中的非共享view在退出和再次进入的时候没有动画效果。

activity B中的enter content transition使用了自定义的slide-in变换。该变换使B中list的元素从下到上过度。

activity B中return content transition是一组TransitionSet,同时播放了两个子元素的变换:上半部分和下半部分的slide变换。看起来就像整个界面被从从中间分割成了两半。

enter and return 共享元素变换是用了ChangeImageTransform。让两个activity中的ImageView无缝切换。

Activity/Fragment Transition分类

Lollipop版本中提供了两种类型的Activity转换动画:Content Transition 和 Shared Element Transition。后续节我们就依次来介绍这两种Activity Transition

在开始讲解之前我们先做一些约定,虽然下面的约定是针对activity的,但是在Fragment中也是一样的约定。

A和B分别是两个Activity,假设activity A 调用activity B。将A代表调用Activity ,B代表被调用Activity。

Activity transition API围绕退出(exit),进入(enter),返回(return)和再次进入(reenter)四种transition。按照上面对A和B的约定,我这样描述这一过程。

Activity A的退出变换(exit transition)决定了在A调用B的时候,A中的View是如何播放动画的。

Activity B的进入变换(enter transition)决定了在A调用B的时候,B中的View是如何播放动画的。

Activity B的返回变换(return transition)决定了在B返回A的时候,B中的View是如何播放动画的。

Activity A的再次进入变换(reenter transition)决定了在B返回A的时候,A中的View是如何播放动画的。

Activity Transition API简介

使用5.0的API可以更快更简单的创建Transition。此篇文章作为一个引入篇,只对Activity Transition API做一个简单的介绍,其他的高逼格的用法会在后续章节中一一介绍。

下面几步是实现一个Activity Transition所必须经过的几个步骤:

1)设置caller Activity和called Activity的Window.FEATURE_ACTIVITY_TRANSITIONS属性为true,有如下两种方式:

    1.1 Activity.java:getWindow().requestFeature(Window.FEATURE_ACTIVITY_TRANSITIONS); 

    1.2 style.xml中配置主题样式:<item name="android:windowActivityTransition">true</item>

2)  分别在caller Activity和called Activity中设置exit Transition和enter Transition。注意:Material主题默认会将exit Transition设置为null,而将enterTransition设置为Fade(也就是说打开一个新的Activity时,会有一个渐入的效果)

3)如果要实现Shared Element Transition(共享元素切换), 则还需要分别设置caller Activity和called Activity间共享的Transition。同样,Material主题默认会将exit的共享元素设置为null,而将enter的共享元素设置为@android:transition/move

4) 在两个Activity间切换并实现共享元素时,需要使用两个参数的startActivity方法启动新的Activity:startActivity(Context, Bundle)。第二个Bundle参数可以通过下列代码的方式获取:

<span style="font-size:18px;">ActivityOptions.makeSceneTransitionAnimation(activity, pairs).toBundle();</span>
makeSceneTransitionAnimation的第二个参数Pairs是一个数组,Pairs<View,String>该数组列出了在不同Activity间需要共享的view和view名称--不要忘记给不同Activity间共享的元素设置唯一的标识符,否则代码运行之后可能不会有效果

5)在代码中通过调用finishAfterTransition()方法来启动返回动画。

  • 5
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值