Android 5.0学习之动画

来源:互联网 发布:剑灵捏脸数据女 编辑:程序博客网 时间:2024/06/05 18:36

前言

用户跟你的App进行交互时,Material Design中的动画给予用户动作的反馈和提供视觉的一致感。

包括之前我学习过的:

Activity transitions(Activity过渡效果)

Animate Vector Drawables(可绘矢量动画)

除我们已经学习过的动画之外,Material Design还给我们提供了什么动画?

Touch feedback(触摸反馈)
Reveal effect(揭露效果)
Curved motion(曲线运动)
View state changes (视图状态改变)
Touch feedback(触摸反馈)

当用户与用户界面进行交互时,materialdesign中的触摸反馈在触摸点上提供了一种瞬时视觉确认。按钮的默认触摸反馈动画使用新的RippleDrawable类,它使用涟漪(波纹)效应在不同状态间转换。

在大多数情况下,你应该在你的布局XML文件中使用如下的方法去指定视图的背景:

?android:attr/selectableItemBackground (有界波纹)

?android:attr/selectableItemBackgroundBorderless (无界波纹)

注意:selectableItemBackgroundBorderless是API级别21上的新属性。

效果如下:


layout:

[html] view plaincopyprint?
  1. <Button android:layout_width="100dp" android:layout_height="100dp"  
  2.                android:background="?android:attr/selectableItemBackground"  
  3.                android:text="有界"  
  4.                android:textColor="@android:color/white"  
  5.                android:colorControlHighlight="@android:color/holo_red_dark"/>  
  6.        <Button android:layout_width="100dp" android:layout_height="100dp"  
  7.                android:background="?android:attr/selectableItemBackgroundBorderless"  
  8.                android:textColor="@android:color/white"  
  9.                android:text="无界"/>  

或者,你可以定义一个RippleDrawable作为波纹元素的XML资源

[html] view plaincopyprint?
  1. <ripple  
  2.     xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:color="@color/accent_dark">  
  4.     <item>  
  5.         <shape  
  6.             android:shape="oval">  
  7.             <solid android:color="?android:colorAccent" />  
  8.         </shape>  
  9.     </item>  
  10. </ripple>  

你可以给RippleDrawable对象指定一种颜色。要更改默认的触摸反馈颜色,使用主题的android:colorControlHighlight属性

Reveal effect揭示效果)

使用ViewAnimationUtils.createCircularReveal() 方法


[java] view plaincopyprint?
  1. public Animator createAnimation(View v, Boolean isFirst) {  
  2.   
  3.       Animator animator;  
  4.   
  5.       if (isFirst) {  
  6.           animator = ViewAnimationUtils.createCircularReveal(  
  7.                   v,// 操作的视图  
  8.                   0,// 动画开始的中心点X  
  9.                   0,// 动画开始的中心点Y  
  10.                   v.getWidth(),// 动画开始半径  
  11.                   0);// 动画结束半径  
  12.       } else {  
  13.           animator = ViewAnimationUtils.createCircularReveal(  
  14.                   v,// 操作的视图  
  15.                   0,// 动画开始的中心点X  
  16.                   0,// 动画开始的中心点Y  
  17.                   0,// 动画开始半径  
  18.                   v.getWidth());// 动画结束半径  
  19.       }  
  20.   
  21.       animator.setInterpolator(new DecelerateInterpolator());  
  22.       animator.setDuration(500);  
  23.       return animator;  
  24.   }  
  25.   static boolean isFirst = false;  
  26.   @Override  
  27.   public void onClick(View v) {  
  28.       createAnimation(myView, isFirst).start();  
  29.       isFirst = !isFirst;  
  30.   }  

Curved motion(曲线运动)

Material design中的动画依靠曲线,这个曲线适用于时间插值器和控件运动模式。

PathInterpolator类是一个基于贝塞尔曲线(Bézier curve)或路径(Path)对象上的新的插值器。

在materialdesign规范中,系统提供了三个基本的曲线:

@interpolator/fast_out_linear_in.xml

@interpolator/fast_out_slow_in.xml

@interpolator/linear_out_slow_in.xml

你可以传递一个PathInterpolator对象给Animator.setInterpolator()方法。

ObjectAnimator类有了新的构造方法,使你能够一次能同时使用两个或多个属性去绘制动画的路径。例如,下面的动画使用一个Path对象进行视图X和Y属性的动画绘制:

[java] view plaincopyprint?
  1. ObjectAnimator mAnimator;  
  2. mAnimator = ObjectAnimator.ofFloat(view, View.X, View.Y, path);  
  3. ...  
  4. mAnimator.start();  

在Android 5.0 提供的API Demos -》Animation/Path Animations 就有一个例子使用了曲线动画:


Path Animations 源码:

[java] view plaincopyprint?
  1. /* 
  2.  * Copyright (C) 2013 The Android Open Source Project 
  3.  * 
  4.  * Licensed under the Apache License, Version 2.0 (the "License"); 
  5.  * you may not use this file except in compliance with the License. 
  6.  * You may obtain a copy of the License at 
  7.  * 
  8.  *      http://www.apache.org/licenses/LICENSE-2.0 
  9.  * 
  10.  * Unless required by applicable law or agreed to in writing, software 
  11.  * distributed under the License is distributed on an "AS IS" BASIS, 
  12.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
  13.  * See the License for the specific language governing permissions and 
  14.  * limitations under the License. 
  15.  */  
  16. package com.example.android.apis.animation;  
  17.   
  18. import android.animation.ObjectAnimator;  
  19. import android.animation.TypeConverter;  
  20. import android.animation.ValueAnimator;  
  21. import android.app.Activity;  
  22. import android.content.Context;  
  23. import android.graphics.Canvas;  
  24. import android.graphics.Matrix;  
  25. import android.graphics.Paint;  
  26. import android.graphics.Path;  
  27. import android.graphics.Point;  
  28. import android.graphics.PointF;  
  29. import android.graphics.RectF;  
  30. import android.os.Bundle;  
  31. import android.util.AttributeSet;  
  32. import android.util.FloatMath;  
  33. import android.util.Log;  
  34. import android.util.Property;  
  35. import android.view.View;  
  36. import android.view.animation.Animation;  
  37. import android.view.animation.LinearInterpolator;  
  38. import android.widget.FrameLayout;  
  39. import android.widget.RadioGroup;  
  40.   
  41. import com.example.android.apis.R;  
  42.   
  43. /** This application demonstrates the use of Path animation. */  
  44. public class PathAnimations extends Activity implements  
  45.         RadioGroup.OnCheckedChangeListener, View.OnLayoutChangeListener {  
  46.   
  47.     final static Path sTraversalPath = new Path();  
  48.     final static float TRAVERSE_PATH_SIZE = 7.0f;  
  49.   
  50.     final static Property<PathAnimations, Point> POINT_PROPERTY  
  51.             = new Property<PathAnimations, Point>(Point.class"point") {  
  52.         @Override  
  53.         public Point get(PathAnimations object) {  
  54.             View v = object.findViewById(R.id.moved_item);  
  55.             return new Point(Math.round(v.getX()), Math.round(v.getY()));  
  56.         }  
  57.   
  58.         @Override  
  59.         public void set(PathAnimations object, Point value) {  
  60.             object.setCoordinates(value.x, value.y);  
  61.         }  
  62.     };  
  63.   
  64.     static {  
  65.         float inverse_sqrt8 = FloatMath.sqrt(0.125f);  
  66.         RectF bounds = new RectF(1133);  
  67.         sTraversalPath.addArc(bounds, 45180);  
  68.         sTraversalPath.addArc(bounds, 225180);  
  69.   
  70.         bounds.set(1.5f + inverse_sqrt8, 1.5f + inverse_sqrt8, 2.5f + inverse_sqrt8,  
  71.                 2.5f + inverse_sqrt8);  
  72.         sTraversalPath.addArc(bounds, 45180);  
  73.         sTraversalPath.addArc(bounds, 225180);  
  74.   
  75.         bounds.set(4163);  
  76.         sTraversalPath.addArc(bounds, 135, -180);  
  77.         sTraversalPath.addArc(bounds, -45, -180);  
  78.   
  79.         bounds.set(4.5f - inverse_sqrt8, 1.5f + inverse_sqrt8, 5.5f - inverse_sqrt8, 2.5f + inverse_sqrt8);  
  80.         sTraversalPath.addArc(bounds, 135, -180);  
  81.         sTraversalPath.addArc(bounds, -45, -180);  
  82.   
  83.         sTraversalPath.addCircle(3.5f, 3.5f, 0.5f, Path.Direction.CCW);  
  84.   
  85.         sTraversalPath.addArc(new RectF(1266), 0180);  
  86.     }  
  87.   
  88.     private CanvasView mCanvasView;  
  89.   
  90.     private ObjectAnimator mAnimator;  
  91.   
  92.     /** Called when the activity is first created. */  
  93.     @Override  
  94.     public void onCreate(Bundle savedInstanceState) {  
  95.         super.onCreate(savedInstanceState);  
  96.         setContentView(R.layout.path_animations);  
  97.         mCanvasView = (CanvasView) findViewById(R.id.canvas);  
  98.         mCanvasView.addOnLayoutChangeListener(this);  
  99.         ((RadioGroup) findViewById(R.id.path_animation_type)).setOnCheckedChangeListener(this);  
  100.     }  
  101.   
  102.     public void setCoordinates(int x, int y) {  
  103.         changeCoordinates((float) x, (float) y);  
  104.     }  
  105.   
  106.     public void changeCoordinates(float x, float y) {  
  107.         View v = findViewById(R.id.moved_item);  
  108.         v.setX(x);  
  109.         v.setY(y);  
  110.     }  
  111.   
  112.     public void setPoint(PointF point) {  
  113.         changeCoordinates(point.x, point.y);  
  114.     }  
  115.   
  116.     @Override  
  117.     public void onCheckedChanged(RadioGroup group, int checkedId) {  
  118.         startAnimator(checkedId);  
  119.     }  
  120.   
  121.     @Override  
  122.     public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft,  
  123.             int oldTop, int oldRight, int oldBottom) {  
  124.         int checkedId = ((RadioGroup)findViewById(R.id.path_animation_type)).getCheckedRadioButtonId();  
  125.         if (checkedId != RadioGroup.NO_ID) {  
  126.             startAnimator(checkedId);  
  127.         }  
  128.     }  
  129.   
  130.     private void startAnimator(int checkedId) {  
  131.         if (mAnimator != null) {  
  132.             mAnimator.cancel();  
  133.             mAnimator = null;  
  134.         }  
  135.   
  136.         View view = findViewById(R.id.moved_item);  
  137.         Path path = mCanvasView.getPath();  
  138.         if (path.isEmpty()) {  
  139.             return;  
  140.         }  
  141.   
  142.         switch (checkedId) {  
  143.             case R.id.named_components:  
  144.                 // Use the named "x" and "y" properties for individual (x, y)  
  145.                 // coordinates of the Path and set them on the view object.  
  146.                 // The setX(float) and setY(float) methods are called on view.  
  147.                 // An int version of this method also exists for animating  
  148.                 // int Properties.  
  149.                 mAnimator = ObjectAnimator.ofFloat(view, "x""y", path);  
  150.                 break;  
  151.             case R.id.property_components:  
  152.                 // Use two Properties for individual (x, y) coordinates of the Path  
  153.                 // and set them on the view object.  
  154.                 // An int version of this method also exists for animating  
  155.                 // int Properties.  
  156.                 mAnimator = ObjectAnimator.ofFloat(view, View.X, View.Y, path);  
  157.                 break;  
  158.             case R.id.multi_int:  
  159.                 // Use a multi-int setter to animate along a Path. The method  
  160.                 // setCoordinates(int x, int y) is called on this during the animation.  
  161.                 // Either "setCoordinates" or "coordinates" are acceptable parameters  
  162.                 // because the "set" can be implied.  
  163.                 mAnimator = ObjectAnimator.ofMultiInt(this"setCoordinates", path);  
  164.                 break;  
  165.             case R.id.multi_float:  
  166.                 // Use a multi-float setter to animate along a Path. The method  
  167.                 // changeCoordinates(float x, float y) is called on this during the animation.  
  168.                 mAnimator = ObjectAnimator.ofMultiFloat(this"changeCoordinates", path);  
  169.                 break;  
  170.             case R.id.named_setter:  
  171.                 // Use the named "point" property to animate along the Path.  
  172.                 // There must be a method setPoint(PointF) on the animated object.  
  173.                 // Because setPoint takes a PointF parameter, no TypeConverter is necessary.  
  174.                 // In this case, the animated object is PathAnimations.  
  175.                 mAnimator = ObjectAnimator.ofObject(this"point"null, path);  
  176.                 break;  
  177.             case R.id.property_setter:  
  178.                 // Use the POINT_PROPERTY property to animate along the Path.  
  179.                 // POINT_PROPERTY takes a Point, not a PointF, so the TypeConverter  
  180.                 // PointFToPointConverter is necessary.  
  181.                 mAnimator = ObjectAnimator.ofObject(this, POINT_PROPERTY,  
  182.                         new PointFToPointConverter(), path);  
  183.                 break;  
  184.         }  
  185.   
  186.         mAnimator.setDuration(10000);  
  187.         mAnimator.setRepeatMode(Animation.RESTART);  
  188.         mAnimator.setRepeatCount(ValueAnimator.INFINITE);  
  189.         mAnimator.setInterpolator(new LinearInterpolator());  
  190.         mAnimator.start();  
  191.     }  
  192.   
  193.     public static class CanvasView extends FrameLayout {  
  194.   
  195.         Path mPath = new Path();  
  196.   
  197.         Paint mPathPaint = new Paint();  
  198.   
  199.         public CanvasView(Context context) {  
  200.             super(context);  
  201.             init();  
  202.         }  
  203.   
  204.         public CanvasView(Context context, AttributeSet attrs) {  
  205.             super(context, attrs);  
  206.             init();  
  207.         }  
  208.   
  209.         public CanvasView(Context context, AttributeSet attrs, int defStyle) {  
  210.             super(context, attrs, defStyle);  
  211.             init();  
  212.         }  
  213.   
  214.         private void init() {  
  215.             setWillNotDraw(false);  
  216.             mPathPaint.setColor(0xFFFF0000);  
  217.             mPathPaint.setStrokeWidth(2.0f);  
  218.             mPathPaint.setStyle(Paint.Style.STROKE);  
  219.         }  
  220.   
  221.         @Override  
  222.         protected void onLayout(boolean changed, int left, int top, int right, int bottom) {  
  223.             super.onLayout(changed, left, top, right, bottom);  
  224.             if (changed) {  
  225.                 Matrix scale = new Matrix();  
  226.                 float scaleWidth = (right-left)/TRAVERSE_PATH_SIZE;  
  227.                 float scaleHeight= (bottom-top)/TRAVERSE_PATH_SIZE;  
  228.                 scale.setScale(scaleWidth, scaleHeight);  
  229.                 sTraversalPath.transform(scale, mPath);  
  230.             }  
  231.         }  
  232.   
  233.         public Path getPath() {  
  234.             return mPath;  
  235.         }  
  236.   
  237.         @Override  
  238.         public void draw(Canvas canvas) {  
  239.             canvas.drawPath(mPath, mPathPaint);  
  240.             super.draw(canvas);  
  241.         }  
  242.     }  
  243.   
  244.     private static class PointFToPointConverter extends TypeConverter<PointF, Point> {  
  245.         Point mPoint = new Point();  
  246.   
  247.         public PointFToPointConverter() {  
  248.             super(PointF.class, Point.class);  
  249.         }  
  250.   
  251.         @Override  
  252.         public Point convert(PointF value) {  
  253.             mPoint.set(Math.round(value.x), Math.round(value.y));  
  254.             return mPoint;  
  255.         }  
  256.     }  
  257. }  
layout:

[html] view plaincopyprint?
  1. <?xml version="1.0" encoding="utf-8"?>  
  2.   
  3. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  4.               android:orientation="vertical"  
  5.               android:layout_width="match_parent"  
  6.               android:layout_height="match_parent">  
  7.     <ScrollView android:layout_width="match_parent"  
  8.                 android:layout_height="wrap_content">  
  9.         <RadioGroup android:orientation="horizontal"  
  10.                     android:layout_width="wrap_content"  
  11.                     android:layout_height="wrap_content"  
  12.                     android:id="@+id/path_animation_type"  
  13.                 >  
  14.             <RadioButton android:id="@+id/named_components"  
  15.                          android:layout_width="wrap_content"  
  16.                          android:layout_height="wrap_content"  
  17.                          android:text="Named Components"/>  
  18.             <RadioButton android:id="@+id/property_components"  
  19.                          android:layout_width="wrap_content"  
  20.                          android:layout_height="wrap_content"  
  21.                          android:text="Property Components"/>  
  22.             <RadioButton android:id="@+id/multi_int"  
  23.                          android:layout_width="wrap_content"  
  24.                          android:layout_height="wrap_content"  
  25.                          android:text="Multi-int"/>  
  26.             <RadioButton android:id="@+id/multi_float"  
  27.                          android:layout_width="wrap_content"  
  28.                          android:layout_height="wrap_content"  
  29.                          android:text="Multi-float"/>  
  30.             <RadioButton android:id="@+id/named_setter"  
  31.                          android:layout_width="wrap_content"  
  32.                          android:layout_height="wrap_content"  
  33.                          android:text="Named Property"/>  
  34.             <RadioButton android:id="@+id/property_setter"  
  35.                          android:layout_width="wrap_content"  
  36.                          android:layout_height="wrap_content"  
  37.                          android:text="Property"/>  
  38.         </RadioGroup>  
  39.     </ScrollView>  
  40.     <view class="com.example.android.apis.animation.PathAnimations$CanvasView"  
  41.           android:id="@+id/canvas"  
  42.           android:layout_width="match_parent"  
  43.           android:layout_height="0px"  
  44.           android:layout_weight="1">  
  45.         <ImageView android:id="@+id/moved_item"  
  46.                    android:layout_width="wrap_content"  
  47.                    android:layout_height="wrap_content"  
  48.                    android:src="@drawable/frog"/>  
  49.     </view>  
  50. </LinearLayout>  


View state changes(视图状态改变)

StateListAnimator类可以让你定义动画集,能在view状态改变时工作。下面的实例显示了如何定义一个XML资源的StateListAnimator

使用步骤

1.定义一个XML资源的StateListAnimator

[html] view plaincopyprint?
  1. <?xml version="1.0" encoding="utf-8"?>  
  2.   
  3.   
  4. <selector xmlns:android="http://schemas.android.com/apk/res/android">  
  5. <item android:state_pressed="true">  
  6.     <set>  
  7.         <objectAnimator android:propertyName="translationZ"  
  8.                         android:duration="@android:integer/config_shortAnimTime"  
  9.                         android:valueTo="10"  
  10.                         android:valueType="floatType"/>  
  11.         <objectAnimator android:propertyName="rotationX"  
  12.                         android:duration="@android:integer/config_shortAnimTime"  
  13.                         android:valueTo="360"  
  14.                         android:valueType="floatType"/>  
  15.   
  16.     </set>  
  17. </item>  
  18. <item  
  19.       android:state_pressed="false"  
  20.       >  
  21.     <set>  
  22.         <objectAnimator android:propertyName="translationZ"  
  23.                         android:duration="10000"  
  24.                         android:valueTo="0"  
  25.                         android:valueType="floatType"/>  
  26.         <objectAnimator android:propertyName="rotationX"  
  27.                         android:duration="@android:integer/config_shortAnimTime"  
  28.                         android:valueTo="0"  
  29.                         android:valueType="floatType"/>  
  30.     </set>  
  31. </item>  
  32. </selector>  
定义了翻转的效果的xml,

配置两种方式:

1.layout:android:stateListAnimator属性将其分配给你的视图,

2.代码:使用AnimationInflater.loadStateListAnimator()方法,并且通过View.setStateListAnimator()方法分配动画到你的视图上。

效果如下:


当然动画任你自己定义,如果只定义Z轴的话也可以轻松的实现此效果:


AnimatedStateListDrawable类让你去创建drawable资源,该资源在相关联的视图的状态更改时展示动画。一些Android5.0中的系统控件使用这些默认的动画。下面的例子显示了如何定义一个AnimatedStateListDrawable作为XML资源:

[html] view plaincopyprint?
  1. <!-- res/drawable/myanimstatedrawable.xml -->  
  2. <animated-selector  
  3.     xmlns:android="http://schemas.android.com/apk/res/android">  
  4.   
  5. <!-- provide a different drawable for each state-->  
  6.     <item android:id="@+id/pressed" android:drawable="@drawable/drawableP"  
  7.         android:state_pressed="true"/>  
  8.     <item android:id="@+id/focused" android:drawable="@drawable/drawableF"  
  9.         android:state_focused="true"/>  
  10.     <item android:id="@id/default"  
  11.         android:drawable="@drawable/drawableD"/>  
  12.   
  13. <!-- specify a transition -->  
  14.     <transition android:fromId="@+id/default" android:toId="@+id/pressed">  
  15.         <animation-list>  
  16.             <item android:duration="15" android:drawable="@drawable/dt1"/>  
  17.             <item android:duration="15" android:drawable="@drawable/dt2"/>  
  18.             ...  
  19.         </animation-list>  
  20.     </transition>  
  21.     ...  
  22. </animated-selector> 
4 0
原创粉丝点击