创建Material Design风格的Android应用--使用自定义动画

动画在Material Design设计中给用户反馈放用户点击时,并且在程序用户界面中提供连贯的视觉。Material主题为按钮(Button)和activity的转换提供了一些默认的动画,在android5.0(api 21)和更高的版本,你可以自定义这些动画和创建一个新动画:

  • Touch feedback(触摸反馈)
  • Circular Reveal(循环揭露效果)
  • Activity transitions(Activity转换效果)
  • Curved motion(曲线运动)
  • View state changes (视图状态改变)

自定义触摸反馈

触摸反馈在Material Design中在触摸点提供了一个即时视觉确认当用户作用在UI元素。按钮的默认触摸反馈动画是使用了新的RippleDrawable类,它会是波纹效果在不同状态间变换。

大多数情况下,我们可以使用这个功能通过在xml文件中定义背景:

?android:attr/selectableItemBackground 有界限的波纹

?android:attr/selectableItemBackgroundBorderless 可以超出视图区域的波纹

?android:attr/selectableItemBackgroundBorderless 是21新添加的api

另外,还以使用ripple元素定义RippleDrawable作为一个xml资源。

你可以给RippleDrawable对象分配一个颜色。使用主题的android:colorControlHighlight属性可以改变默认的触摸反馈颜色。

更多信息,查看RippleDrawable类的api指南。

使用揭露效果

揭露动画为用户提供视觉上的持续性挡显示或者隐藏一组界面元素。ViewAnimationUtils.createCircularReveal()方法使你可以使用动画效果来揭露或者隐藏一个视图。

这样揭露一个先前隐藏的视图:

?


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

//
previously invisible view

View
myView = findViewById(R.id.my_view);

//
get the center for the clipping circle

int

cx = (myView.getLeft() + myView.getRight()) /
2;

int

cy = (myView.getTop() + myView.getBottom()) /
2;

//
get the final radius for the clipping circle

int

finalRadius = Math.max(myView.getWidth(), myView.getHeight());

//
create the animator for this view (the start radius is zero)

Animator
anim =

    ViewAnimationUtils.createCircularReveal(myView,
cx, cy,
0,
finalRadius);

//
make the view visible and start the animation

myView.setVisibility(View.VISIBLE);

anim.start();

这样隐藏一个先前显示的视图:

?


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

//
previously visible view

final

View myView = findViewById(R.id.my_view);

//
get the center for the clipping circle

int

cx = (myView.getLeft() + myView.getRight()) /
2;

int

cy = (myView.getTop() + myView.getBottom()) /
2;

//
get the initial radius for the clipping circle

int

initialRadius = myView.getWidth();

//
create the animation (the final radius is zero)

Animator
anim =

    ViewAnimationUtils.createCircularReveal(myView,
cx, cy, initialRadius,
0);

//
make the view invisible when the animation is done

anim.addListener(new

AnimatorListenerAdapter() {

    @Override

    public

void

onAnimationEnd(Animator animation) {

        super.onAnimationEnd(animation);

        myView.setVisibility(View.INVISIBLE);

    }

});

//
start the animation

anim.start();

自定义activity转换效果

activity间转换在Material Design程序中提供不同状态间的视觉连接通过在公用元素上动作或者转换。你可以为进入或退出的转换自定义动画,共享元素在不同的activity之间的转换效果。

进入过渡决定activity中的视图怎样进入场景。比如在爆裂进入过渡效果中,视图从屏幕外面飞向屏幕中间进入场景。

退出过渡决定activity中的视图怎样退出场景。比如,在爆裂退出过渡效果中,视图从中间向远处退出场景。

共享元素过渡决定两个activity之间共享的视图怎么在两个activity之间过渡。比如,两个activity有一个相同的图片,在不同的位置和不同的大小,changeImageTransform(图片变换变化)让共享元素平滑的平移和缩放图片在两个activity之间。

android 5.0(api 21)提供以下进入和退出效果:

  • explode(爆裂) - 从场景中间移动视图进入或者退出
  • slide(滑动) - 视图从场景的一个边缘进入或者退出
  • fade(淡入淡出) - 从场景添加或者移除一个视图通过改变他的透明

所有过渡效果都继承Visibility类,因此支持作为一个进入或者退出过渡效果。

更多细节,看Transition类的api指南。

Android5.0(api 21)也支持共享元素过渡效果:

  • changeBounds - 改变目标视图的布局边界
  • changeClipBounds - 裁剪目标视图边界
  • changeTransform - 改变目标视图的缩放比例和旋转角度
  • changeImageTransform - 改变目标图片的大小和缩放比例

当你在程序中开启activity间的过渡动画时,默认的交叉淡入淡出效果会在两个activity之间激活。

一个共享元素过渡效果

指定过渡效果

首先,使用在从material theme继承的样式中,使用android:windowContentTransitions属性开启窗口内内容过渡效果。也可以在样式定义中第一进入,退出,共享元素的效果:

?


1

2

3

4

5

6

7

8

9

10

11

12

13

14

<style

name
="BaseAppTheme"

parent
="android:Theme.Material">

  <!--
enable window content transitions -->

  <item

name
="android:windowContentTransitions">true</item>

  <!--
specify enter and exit transitions -->

  <item

name
="android:windowEnterTransition">@transition/explode</item>

  <item

name
="android:windowExitTransition">@transition/explode</item>

  <!--
specify shared element transitions -->

  <item

name
="android:windowSharedElementEnterTransition">

    @transition/change_image_transform</item>

  <item

name
="android:windowSharedElementExitTransition">

    @transition/change_image_transform</item>

</style>

示例中的过渡change_image_transform定义如下:

?


1

2

3

4

5

<!--
res/transition/change_image_transform.xml -->

<!--
(see also Shared Transitions below) -->

<transitionSet

xmlns:android
="http://schemas.android.com/apk/res/android">

  <changeImageTransform/>

</transitionSet>

changeImageTransform元素对应ChangeImageTransform类。更多信息,查看Transition的api指南。

在代码中启用窗口内容过渡效果,使用Window.requestFeature()方法:

?


1

2

3

4

5

//
inside your activity (if you did not enable transitions in your theme)

getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);

//
set an exit transition

getWindow().setExitTransition(new

Explode());

在代码中定义过渡效果,使用下面的方法,并传一个Transition对象:

  • Window.setEnterTransition()
  • Window.setExitTransition()
  • Window.setSharedElementEnterTransition()
  • Window.setSharedElementExitTransition()

setExitTransition()setSharedElementExitTransition()方法为调用的activity定义退出过渡效果,setEnterTransition()setSharedElementEnterTransition()方法为调用的activity定义进入过渡效果。

为了达到完整的过渡效果,必须在进入的和退出的两个activity上都启用window内容过渡。否则,正调用的activity会开始退出过渡,你就会看到窗口过渡效果(比如缩放,或者淡出)。

更快的开始一个进入过渡,使用Window.setAllowEnterTransitionOverlap()方法在被调用的activity。这让你有更加激动人心的进入过渡效果。

打开activity使用过渡

如果你为一个activity开启过渡并且设置了一个退出过渡效果,过渡效果会在你打开其他activity的时候激活,像这样:

?


1

2

startActivity(intent,

        ActivityOptions.makeSceneTransitionAnimation(this).toBundle());

如果你给第二个activity设置了进入过渡动画,过渡也会在第二个activity启动的时候激活。当你启动其他的activity时,如果需要禁用过渡效果,提供一个为null的bundle选项。

打开一个activity包含一个共享元素

使用一个场景过渡动画在两个activity之间包括一个共享元素:

  1. 在theme中开启窗口内容过渡效果
  2. 在style中指定一个共享元素过渡效果
  3. 在xml中定义过渡样式
  4. 在两个activity的样式文件中给共享元素分配一个相同的名字使用android:transitionName属性
  5. 使用ActivityOptions.makeSceneTransitionAnimation()方法。

?


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

//
get the element that receives the click event

final

View imgContainerView = findViewById(R.id.img_container);

//
get the common element for the transition in this activity

final

View androidRobotView = findViewById(R.id.image_small);

//
define a click listener

imgContainerView.setOnClickListener(new

View.OnClickListener() {

    @Override

    public

void

onClick(View view) {

        Intent
intent =
new

Intent(
this,
Activity2.
class);

        //
create the transition animation - the images in the layouts

        //
of both activities are defined with android:transitionName="robot"

        ActivityOptions
options = ActivityOptions

            .makeSceneTransitionAnimation(this,
androidRobotView,
"robot");

        //
start the new activity

        startActivity(intent,
options.toBundle());

    }

});

对于在代码中生成的动态共享视图,使用`View.setTransitionName()方法在两个activity中给指定相同的名字。

当完成第二个activity的时候,如果需要逆转该过渡动画,使用Activity.finishAfterTransition()方法代替Activity.finish()

打开一个activity包含多个共享元素

使用一个场景过渡动画在两个activity之间包括多于一个共享元素,在两个activity中定义所有的的共享元素使用android:transitionName属性(或使用View.setTransitionName()方法在所有的activity中),并且创建一个像下面这样的ActivityOptions对象:

?


1

2

3

ActivityOptions
options = ActivityOptions.makeSceneTransitionAnimation(
this,

        Pair.create(view1,
"agreedName1"),

        Pair.create(view2,
"agreedName2"));

使用曲线运动

Material Design中,动画依赖时间插值和空间移动模式曲线。在android5.0(api 21)和更高版本,你可以为动画自定义时间曲线和移动曲线。

PathInterpolator类是一个新的基于贝塞尔曲线或Path对象的插值器。这个插值器在1*1的正方形上定义了曲线运动,以(0,0)和(1,1)点作为锚点,根据够照参数控制点。你也可以使用xml文件的定义一个路径插值器,如:

?


1

2

3

4

5

<pathInterpolator

xmlns:android
="http://schemas.android.com/apk/res/android"

    android:controlX1="0.4"

    android:controlY1="0"

    android:controlX2="1"

    android:controlY2="1"/>

Material Design设计规范中,系统提供了三个基本曲线的xml资源:

  • @interpolator/fast_out_linear_in.xml
  • @interpolator/fast_out_slow_in.xml
  • @interpolator/linear_out_slow_in.xml

我们可以给Animator.setInterpolator()传一个PathInterpolator对象来设置。

ObjectAnimator类有新的构造方法,你可以一次使用两个或者属性使用path独立于坐标动画。比如,下面的动画使用一个Path对象去动作一个视图的x和y属性:

?


1

2

3

4

ObjectAnimator
mAnimator;

mAnimator
= ObjectAnimator.ofFloat(view, View.X, View.Y, path);

...

mAnimator.start();

视图状态改变动画

StateListAnimator定义动画当视图的状态改变的时候运行,下面的例子是怎么在xml中定义一个StateListAnimator动画:

?


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

<!--
animate the translationZ property of a view when pressed -->

<selector

xmlns:android
="http://schemas.android.com/apk/res/android">

  <item

android:state_pressed
="true">

    <set>

      <objectAnimator

android:propertyName
="translationZ"

        android:duration="@android:integer/config_shortAnimTime"

        android:valueTo="2dp"

        android:valueType="floatType"/>

        <!--
you could have other objectAnimator elements

             here
for "x" and "y", or other properties -->

    </set>

  </item>

  <item

android:state_enabled
="true"

    android:state_pressed="false"

    android:state_focused="true">

    <set>

      <objectAnimator

android:propertyName
="translationZ"

        android:duration="100"

        android:valueTo="0"

        android:valueType="floatType"/>

    </set>

  </item>

</selector>

给视图附加自定义的视图状态动画,使用selector元素在xml文件中定义一个动画祥例子中这样,给视图分配动画使用android:stateListAnimator属性。在代码中使用,使用AnimationInflater.loadStateListAnimator()方法,并且使用View.setStateListAnimator()方法。

当你的主题是继承的Material主题,按钮默认有一个Z动画。如果需要避免这个动画,设置android:stateListAnimator属性为@null 即可。

AnimatedStateListDrawable类让你创建可绘制图在相关联的视图状态改变。android5.0的一些系统组件默认使用这些动画。下面的例子是如何在xml文件中定义一个AnimatedStateListDrawable:

?


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

<!--
res/drawable/myanimstatedrawable.xml -->

<animated-selector

    xmlns:android="http://schemas.android.com/apk/res/android">

    <!--
provide a different drawable for each state-->

    <item

android:id
="@+id/pressed"

android:drawable
="@drawable/drawableP"

        android:state_pressed="true"/>

    <item

android:id
="@+id/focused"

android:drawable
="@drawable/drawableF"

        android:state_focused="true"/>

    <item

android:id
="@id/default"

        android:drawable="@drawable/drawableD"/>

    <!--
specify a transition -->

    <transition

android:fromId
="@+id/default"

android:toId
="@+id/pressed">

        <animation-list>

            <item

android:duration
="15"

android:drawable
="@drawable/dt1"/>

            <item

android:duration
="15"

android:drawable
="@drawable/dt2"/>

            ...

        </animation-list>

    </transition>

    ...

</animated-selector>

可绘矢量动画

可绘制矢量图在拉伸时不会失真。AnimatedVectorDrawable类让你可以在可绘制矢量图上面作用动画。

通常需要在三个xml文件中定义可动的矢量图:

一个矢量图使用<vector>元素,放在res/drawable/下。

一个可动的矢量图使用<animated-vector>元素,放在res/drawable/下。

一个或更多个动画对象使用<objectAnimator>元素,放在res/anim/下。

可动矢量图可以使用<group><path>元素。<group>元素定义一系列路径或者子组,<path>元素定义可绘图的路径。

当你定义了一个想要作用动画的矢量可绘制图,使用android:name属性给每个group和path指定一个唯一的名字,这样你可以从动画的定义中找到他们。比如:

?


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

<!--
res/drawable/vectordrawable.xml -->

<vector

xmlns:android
="http://schemas.android.com/apk/res/android"

    android:height="64dp"

    android:width="64dp"

    android:viewportHeight="600"

    android:viewportWidth="600">

    <group

        android:name="rotationGroup"

        android:pivotX="300.0"

        android:pivotY="300.0"

        android:rotation="45.0"

>

        <path

            android:name="v"

            android:fillColor="#000000"

            android:pathData="M300,70
l 0,-70 70,70 0,0 -70,70z"

/>

    </group>

</vector>

可动的矢量绘制通过刚刚说到定义的名字,来找到这些path和group:

?


1

2

3

4

5

6

7

8

9

10

<!--
res/drawable/animvectordrawable.xml -->

<animated-vector

xmlns:android
="http://schemas.android.com/apk/res/android"

  android:drawable="@drawable/vectordrawable"

>

    <target

        android:name="rotationGroup"

        android:animation="@anim/rotation"

/>

    <target

        android:name="v"

        android:animation="@anim/path_morph"

/>

</animated-vector>

动画的定义表现在ObjectAnimator和AnimatorSet对象中。第一个动画在这个例子中是让目标组旋转360度:

?


1

2

3

4

5

6

<!--
res/anim/rotation.xml -->

<objectAnimator

    android:duration="6000"

    android:propertyName="rotation"

    android:valueFrom="0"

    android:valueTo="360"

/>

第二个动画例子是把矢量可绘图从一个形状变成另一种。所有的路径必须兼容变换:他们必须有相同数量的命令,每个命令要有相同的参数。

?


1

2

3

4

5

6

7

8

9

<!--
res/anim/path_morph.xml -->

<set

xmlns:android
="http://schemas.android.com/apk/res/android">

    <objectAnimator

        android:duration="3000"

        android:propertyName="pathData"

        android:valueFrom="M300,70
l 0,-70 70,70 0,0   -70,70z"

        android:valueTo="M300,70
l 0,-70 70,0  0,140 -70,0 z"

        android:valueType="pathType"

/>

</set>

更多的信息,看AnimatedVectorDrawable的api指南。

PS后记

这个系列终于写完了,说实话基本上大部分都是翻译的谷歌的官方文档。因为时间问题,再加上自己的英语够烂,最近越来慢。不过,这样一下来,加上自己的一些代码练习,对于Material设计算是能够基本使用了。可惜,大部分的style还都不能向下兼容,只好等5了。

网上有一些大神进来已经开源了一些开源组件,大家可以借此曲线救国,下次有空在专门整理一下。

本文参考: http://developer.android.com/training/material/animations.html

原文地址:http://blog.isming.me/2014/11/13/creating-app-with-material-design-five-animations/,转载请注明出处。

时间: 2024-10-13 21:26:44

创建Material Design风格的Android应用--使用自定义动画的相关文章

创建Material Design风格的Android应用--应用主题

昨天正式发布了android 5,同时android developer网站也更新了,增加了创建Material Design风格的Android应用指南,也更新了Support Library,在support library增加了一些Material Design风格的控件和动画等,这里给大家简单介绍一下怎样开发material design风格的Android应用. android 5使用Material Design风格 android提供了三种Material Design风格Them

创建Material Design风格的Android应用--使用Drawable

以下Drawables的功能帮助你在应用中实现Material Design: 图片资源着色 在android 5.0(api 21)和更高版本,可以着色bitmap和.9 png 通过定义透明度遮盖.你可以着色通过使用颜色资源或者主题的属性去解析颜色资源(比如,?android:attr/colorPrimary).通常我们创建一次,然后资源自适应主题. 你可以给BitmapDrawable或NinePatchDrawable对象着色使用setTint()方法.你可以可以在布局文件中使用and

创建Material Design风格的Android应用--定义阴影和裁剪视图

之前已经写过通过应用主题和使用ListView, CardView,应用Material Design样式,同时都都可以通过support library向下兼容.今天要写的阴影和视图裁剪,无法向下兼容,请注意. ?Material Design 为用户界面元素引入了深度这个元素.深度帮助用户理解各个元素之间的重要关联和帮助用户关注他们手上的任务. 视图的高度(elevation),通过Z属性表现,通过他的阴影确定:z值更高的视图投影出更大的阴影.视图只在Z=0的平面上投影处阴影:他们不会投影阴

创建Material Design风格的Android应用--创建列表和卡片

本人所有文章首先发布于个人博客,欢迎关注,地址:http://blog.isming.me 上次说过使用主题,应用Material Design的样式,同时卡片布局也是Material Design的重要组成部分,今天来写写. 引言 在程序中创建复杂的Material Design 样式的 List和Card,可以使用RecyclerView和CardView组件,这两个组件是在最新的support v7包(version 21)中提供的.因此需要引入依赖包: dependencies { co

创建Material Design风格Android应用--自定义阴影和裁剪视图

之前已经写过通过应用主题和使用ListView, CardView,应用Material Design样式,同一时候都都能够通过support library向下兼容.今天要写的阴影和视图裁剪.无法向下兼容.请注意. ?Material Design 为用户界面元素引入了深度这个元素.深度帮助用户理解各个元素之间的重要关联和帮助用户关注他们手上的任务. 视图的高度(elevation).通过Z属性表现,通过他的阴影确定:z值更高的视图投影出更大的阴影.视图仅仅在Z=0的平面上投影处阴影:他们不会

Android控件使用 — 12个Material Design风格控件的使用

项目在GitHub上的地址: https://github.com/Hebin320/MaterialDesignUse 1.AppBarLayout.ToolBar AppBarLayout 是继承LinerLayout实现的一个ViewGroup容器组件,它是为了Material Design设计的App Bar,支持手势滑动操作. AppBarLayout必须作为Toolbar的父布局容器,也可以配合CoordinatorLayout一起使用. ToolBar是谷歌新推出的代替Action

Android开发实战之拥有Material Design风格的抽屉式布局

在实现开发要求中,有需要会使用抽屉式布局,类似于QQ5.0的侧滑菜单,实现的方式有很多种,可以自定义控件,也可以使用第三方开源库. 同样的谷歌也推出了自己的侧滑组件——DrawLayout,使用方式也很简单,配合着toolbar有着不一样的滑动效果,所以推荐大家使用. 如下是效果图,是不是更具交互性,更加酷炫? **首先是XML** drawlayout分为两部分:侧滑界面和内容界面,所以drawlayout中应该有两个布局,在侧滑的布局中设置属性:android:layout_gravity=

打造Material Design风格的TabBar

自从Material Design问世以来, 各种Material Design风格的控件层出不穷, 尤其是google家的几个APP更是将Material Design应用到了极致. 最近在使用google photos的时候发现这款软件的Tabbar做的非常不错, 内容突出, Material Design风味很浓, 再者, 我还没有做过一个Material Design风格的Tabbar, 所以萌生了仿照一个google photos这种tabbar的念想, 今天我们就来一步步的去实现一下

教你轻松实现Material Design风格的知乎主页(详解多种控件的综合使用)

本文讲主要来说说Toolbar.RecyclerView.CardView.DrawerLayout.以及SwiperefreshLayout的综合使用,其中Toolbar和RecyclerView在前几篇博客已经详细讲述其用法了,有兴趣的可以去看看.现在利用这几个控件实现Material Design风格的知乎主页(Android v3.3版 知乎),在讲到相关控件的时候,我也会提及一下这个控件的用法.那么,让我们开始控件之旅吧. 示例效果 在动手写代码之前,我们先要看看最终的实现效果是什么: