Android Transition框架介绍&使用

简介

简介
自KitKat起,Android加入了 Android Transition框架,可以帮助我们做一些Activity级别或View级别的动画效果,今天的内容就是如何在View上使用Transition。
有别于传统的Animation, Transition需要对动画前后设置不同布局,通过相应的API实现两个布局的切换动画。而传统Animation只会对应一个布局文件,动画结束时,即使设置了fillAfter(true)让画面停留在动画的最后一帧也不会对布局产生影响。现在,对于这种动画前后需要改变布局的场景,我们可以使用Transition。

1.创建应用程序:

第一步:

使用Android Studio创建一个新的工程。建一个空的Activity。由于本例使用了一些5.0加入的API,SDK版本请使用21.

第二步:

创建一些Demo中需要用到的Drawable。我们将使用Shape创建4个圆形,每一个都有不同的颜色与渐进效果。首先在drawable目录下新建一个文件:shape1.xml

<shape xmlns:android="http://schemas.android.com/apk/res/android"
       android:dither="true"
       android:shape="oval">

    <!--gradientRadius 很难理解,**%的形式在三星note机型上表现非常差!
  使用float值在5.0上的表现非常差! -->
    <!-- %意识是相对于自己的尺寸,%p是相对于自己Parent的-->
    <gradient
      android:endColor="#66ff0000"
      android:gradientRadius="75%"
      android:centerColor="#ffffcc00"
      android:startColor="#ffffcc00"
      android:type="radial"
      android:useLevel="false"/>

    <size
      android:height="100dp"
      android:width="100dp"/>

</shape>

以上代码构建出的是一个由渐变色填充而成的圆形图案。而四个图形在大小与样式方面完全相同,仅仅在色彩上有所区别。当然,大家可能需要为不同像素密度的设备分别准备多种不同版本的图形。利用以下代码创建shape2.xml:

<shape xmlns:android="http://schemas.android.com/apk/res/android"
       android:dither="true"
       android:shape="oval" >

    <gradient
      android:endColor="#66ffcc00"
      android:gradientRadius="75%"
      android:startColor="#ff00ff00"
      android:type="radial"
      android:useLevel="false" />

    <size
      android:height="100dp"
      android:width="100dp" />

</shape>

接着创建shape3.xml

<shape xmlns:android="http://schemas.android.com/apk/res/android"
       android:dither="true"
       android:shape="oval" >

    <gradient
      android:endColor="#6600ff00"
      android:gradientRadius="75%"
      android:startColor="#ff0000ff"
      android:type="radial"
      android:useLevel="false" />

    <size
      android:height="100dp"
      android:width="100dp" />

</shape>

最后创建shape4.xml

<shape xmlns:android="http://schemas.android.com/apk/res/android"
       android:dither="true"
       android:shape="oval" >

    <gradient
      android:endColor="#660000ff"
      android:gradientRadius="75%"
      android:startColor="#ffff0000"
      android:type="radial"
      android:useLevel="false" />

    <size
      android:height="100dp"
      android:width="100dp" />

</shape>

我们将把这些图形作为ImageButtons应用在两种布局场景之内。

2.创建布局

第一步

我们需要为每个动画创建两个布局,分别对应动画前的状态和动画后的状态。在Transition中,这两个状态被定义成Scene,Transition就是不同Scene之间的切换效果。不同Scene的布局文件可以有重名控件,并且往往看起来差不多,只是同一个控件的位置大小图片等属性不一样。

OK,现在我们创建布局文件,在res/layout目录下新建scene_1.xml。

首先我们添加一个RelativeLayout用来容纳我们后面的ImageButton:

<pre name="code" class="html"><RelativeLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:tools="http://schemas.android.com/tools"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:id="@+id/container"
  tools:context="xzy.demo.androidtestapi.transition.TestTransition">
</RelativeLayout>

接着向这个RelativeLayout中添加4个ImageButton,每个ImageButton会只用1个我们之前创建的shape.

<ImageButton
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:id="@+id/btn1"
      android:src="@drawable/shape1"
      android:background="#00000000"
      android:contentDescription="shape"
      android:layout_alignParentLeft="true"
      android:layout_alignParentTop="true"
      android:scaleType="centerInside"
      />

    <ImageButton
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:id="@+id/btn2"
      android:src="@drawable/shape2"
      android:background="#00000000"
      android:contentDescription="shape"
      android:layout_alignParentRight="true"
      android:layout_alignParentTop="true"
      android:scaleType="centerInside"
      />

    <ImageButton
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:id="@+id/btn3"
      android:src="@drawable/shape3"
      android:background="#00000000"
      android:contentDescription="shape"
      android:layout_alignParentLeft="true"
      android:layout_alignParentBottom="true"
      android:scaleType="centerInside"
      />

    <ImageButton
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:id="@+id/btn4"
      android:src="@drawable/shape4"
      android:background="#00000000"
      android:contentDescription="shape"
      android:layout_alignParentRight="true"
      android:layout_alignParentBottom="true"
      android:scaleType="centerInside"
      />

注意,需要对scene中的每个控件单独设置ID和事件,即使不同scene中的控件ID相同,也许要单独设置事件。
在IDE中,我们的布局预览效果如下:

这里写图片描述
接下来,我们创建scene_2.xml:

<RelativeLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:tools="http://schemas.android.com/tools"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:id="@+id/container"
  tools:context="xzy.demo.androidtestapi.transition.TestTransition">

    <ImageButton
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:id="@+id/btn1"
      android:src="@drawable/shape1"
      android:background="#00000000"
      android:contentDescription="shape"
      android:layout_alignParentRight="true"
      android:layout_alignParentBottom="true"
      android:scaleType="centerInside"
      android:onClick="changeScene"/>

    <ImageButton
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:id="@+id/btn2"
      android:src="@drawable/shape2"
      android:background="#00000000"
      android:contentDescription="shape"
      android:layout_alignParentLeft="true"
      android:layout_alignParentBottom="true"
      android:scaleType="centerInside"
      android:onClick="changeScene"/>

    <ImageButton
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:id="@+id/btn3"
      android:src="@drawable/shape3"
      android:background="#00000000"
      android:contentDescription="shape"
      android:layout_alignParentRight="true"
      android:layout_alignParentTop="true"
      android:scaleType="centerInside"
      android:onClick="changeScene"/>

    <ImageButton
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:id="@+id/btn4"
      android:src="@drawable/shape4"
      android:background="#00000000"
      android:contentDescription="shape"
      android:layout_alignParentLeft="true"
      android:layout_alignParentTop="true"
      android:scaleType="centerInside"
      android:onClick="changeScene"/>

</RelativeLayout>

最后是scene_3.xml

<RelativeLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:tools="http://schemas.android.com/tools"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:id="@+id/container"
  tools:context="xzy.demo.androidtestapi.transition.TestTransition">

    <ImageButton
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:id="@+id/btn1"
      android:src="@drawable/shape1"
      android:background="#00000000"
      android:contentDescription="shape"
      android:layout_alignParentRight="true"
      android:layout_alignParentBottom="true"
      android:scaleType="centerInside"
      android:onClick="changeScene"/>

    <ImageButton
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:id="@+id/btn2"
      android:src="@drawable/shape2"
      android:background="#00000000"
      android:contentDescription="shape"
      android:layout_alignParentRight="true"
      android:layout_alignParentBottom="true"
      android:scaleType="centerInside"
      android:onClick="changeScene"/>

    <ImageButton
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:id="@+id/btn3"
      android:src="@drawable/shape3"
      android:background="#00000000"
      android:contentDescription="shape"
      android:layout_alignParentRight="true"
      android:layout_alignParentBottom="true"
      android:scaleType="centerInside"
      android:onClick="changeScene"/>

    <ImageButton
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:id="@+id/btn4"
      android:src="@drawable/shape4"
      android:background="#00000000"
      android:contentDescription="shape"
      android:layout_alignParentRight="true"
      android:layout_alignParentBottom="true"
      android:scaleType="centerInside"
      android:onClick="changeScene"/>
    <TextView
      android:id="@+id/info"
      android:text="序列动画,会在球动完后出来"
      android:layout_centerInParent="true"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"/>

</RelativeLayout>

现在我们回头看一下三个scene,除了ImageButton的位置,这三个布局基本相同。

3.不同场景使用Transition进行过渡:

第一步:

打开创建的主Activity,在onCreate()之前做如下申明:

private Scene mScene1, mScene2, mScene3;

    private RelativeLayout mBaseLayout;

    private TransitionManager mCustomTransitionManager;

第二步:

编写一些初始化代码,在onCreate()中自动创建的代码后面添加以下代码:

setContentView(R.layout.base_transition_layout);

  //得到容器ViewGroup
  mBaseLayout = (RelativeLayout) findViewById(R.id.base);

  //创建三个场景
  mScene1 = new Scene(mBaseLayout, mBaseLayout.findViewById(R.id.container));
  mScene2 = Scene.getSceneForLayout(mBaseLayout, R.layout.scene_2, this);
  mScene3 = Scene.getSceneForLayout(mBaseLayout, R.layout.scene_3, this);

  //create transition, set properties
  TransitionInflater inflater = TransitionInflater.from(this);
  mCustomTransitionManager = inflater.inflateTransitionManager(R.transition.transition_mgr,
    mBaseLayout);

首先,我们要对容器ViewGroup进行定义,后面的每个scene都是添加到这个容器中的。然后我们初始化不同的scene,每个Transition会对应两个Scene,通过这种方式,Android将能够根据我们的需要在两个场景之间进行过渡、并将不同场景下具备相同ID的任意视图元素作为同一对象加以处理,这样场景切换时就能显示出动画式的变化效果。

第三步:

设置点击事件,触发不同的Transition动画:

public void changeScene(View v) {

    if (v.getId() == R.id.anim_1) {
      //简单的写法,直接用TransitionManager,使用默认动画效果
      TransitionManager.go(mScene1);
    } else if (v.getId() == R.id.anim_2) {
      TransitionManager.go(mScene2);
    } else if (v.getId() == R.id.anim_3) {
      mCustomTransitionManager.transitionTo(mScene3);
    } else if (v.getId() == R.id.anim_4) {
      //在下一帧进行动画,可以继续设置属性等
      TransitionManager.beginDelayedTransition(mBaseLayout);

      //可以继续设置View的属性,不会影响动画
      ImageView btn4 = (ImageView) mBaseLayout.findViewById(R.id.btn4);
      ViewGroup.LayoutParams params = btn4.getLayoutParams();
      if (params.width > dip2px(this, 51)) {
        params.width = dip2px(this, 51);
        params.height = dip2px(this, 50);
      } else {
        params.width = dip2px(this, 100);
        params.height = dip2px(this, 100);
      }
      btn4.setLayoutParams(params);
    }
  }

Android提供了一系列过渡类型可供选择,大家可以根据自己需要的场景变化方式采用其中的不同动画效果。在今天的Demo中,我们使用

TransitionManager.go(mScene2);

来触发默认的动画效果,采用:

mCustomTransitionManager.transitionTo(mScene3);

来触发我们自定义的动画效果。
Android会计算如何根据我们设置的Transition属性在两个Scene间实现基过渡。感兴趣的朋友也可以 点击此处 查看更多与Transition引用相关的选项。

程序主Activity代码如下:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#ff000000"
    tools:context="xzy.demo.androidtestapi.transition.TestTransition">
    <Button
      android:id="@+id/anim_1"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:onClick="changeScene"
      android:text="演示1"
      />
    <Button
      android:id="@+id/anim_2"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_toRightOf="@id/anim_1"
      android:onClick="changeScene"
      android:text="演示2"
      />
    <Button
      android:id="@+id/anim_3"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_toRightOf="@id/anim_2"
      android:onClick="changeScene"
      android:text="演示3"
      />
    <Button
      android:id="@+id/anim_4"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_toRightOf="@id/anim_3"
      android:onClick="changeScene"
      android:text="演示4"
      />
    <RelativeLayout
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      android:id="@+id/base"
      android:layout_below="@id/anim_1">

  <include layout="@layout/scene_1"
    />
    </RelativeLayout>
</RelativeLayout>

现在大家可以运行自己的程序,点击不同的Button查看不同Transition的动画效果。
这里写图片描述

总结:
在今天的文章中,我们事实上还只是初步了解了自己能够利用Android Transition框架实现怎样的设计方案与过渡效果。要在自己的应用程序中引入更多过渡机制,大家可以 点击此处 查看TransitionManager类当中的其它方法,其中包括beginDelayedTransition与transitionTo。此外,大家也不妨尝试利用 TransitionSet 将多种过渡机制结合在一起,例如同时使用来自不同过渡机制的渐变与移动效果。根据过渡机制复杂程度的不同,大家可能还需要用到 TransitionValues 类,它能够提供与对应过渡相关的数据值引用能力。如果各位还想了解更多与场景处理相关的技术手段,也可以 点击此处 查看 Scene 类的相关说明。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值