Android攻城狮属性动画赏析

 1 import android.support.v7.app.ActionBarActivity;
 2 import android.support.v7.app.ActionBar;
 3 import android.support.v4.app.Fragment;
 4 import android.animation.AnimatorSet;
 5 import android.animation.ObjectAnimator;
 6 import android.animation.PropertyValuesHolder;
 7 import android.os.Bundle;
 8 import android.view.LayoutInflater;
 9 import android.view.Menu;
10 import android.view.MenuItem;
11 import android.view.View;
12 import android.view.ViewGroup;
13 import android.view.animation.TranslateAnimation;
14 import android.widget.ImageView;
15 import android.widget.Toast;
16 import android.os.Build;
17 //显示animation的缺点
18 public class MainActivity extends ActionBarActivity {
19
20     @Override
21     protected void onCreate(Bundle savedInstanceState) {
22         super.onCreate(savedInstanceState);
23         setContentView(R.layout.fragment_main);
24
25
26     }
27
28     public void click(View view) {
29         Toast.makeText(MainActivity.this, "click", 0).show();
30
31     }
32     public void move(View view) {
33         //-------------------传统实现----图片在位移,监听的还在原地--
34
35 //    TranslateAnimation animation=new TranslateAnimation(0, 200, 0,0);
36 //    animation.setDuration(1000);
37 //    animation.setFillAfter(true);//停留在结束的位置
38     ImageView imageView=(ImageView) findViewById(R.id.imageView1);
39 //    imageView.startAnimation(animation);
40
41
42         //translationX:在X方向上位移;translationY:在Y方向上位移
43         //rotation:旋转
44     //动画是同时进行的
45     //-----------方式1-----------
46         ObjectAnimator.ofFloat(imageView,"translationX", 0F,200F).setDuration(1000).start();
47         ObjectAnimator.ofFloat(imageView,"rotation", 0F,360F).setDuration(1000).start();
48         ObjectAnimator.ofFloat(imageView,"translationY", 0F,200F).setDuration(1000).start();
49         //-----------方式2-----------
50         PropertyValuesHolder p1=PropertyValuesHolder.ofFloat("rotation", 0F,360F);
51         PropertyValuesHolder p2=PropertyValuesHolder.ofFloat("translationX", 0F,200F);
52         PropertyValuesHolder p3=PropertyValuesHolder.ofFloat("translationY", 0F,200F);
53         ObjectAnimator.ofPropertyValuesHolder(imageView, p1,p2,p3).setDuration(1000).start();
54
55         //-----------方式3-----------
56         ObjectAnimator animator1=ObjectAnimator.ofFloat(imageView,"translationX", 0F,200F);
57         ObjectAnimator animator2=ObjectAnimator.ofFloat(imageView,"rotation", 0F,360F);
58         ObjectAnimator animator3=ObjectAnimator.ofFloat(imageView,"translationY", 0F,200F);
59         AnimatorSet set=new AnimatorSet();
60         set.playTogether(animator1,animator2,animator3);//一起执行
61         set.playSequentially(animator1,animator2,animator3);//按顺序执行
62         set.play(animator1).with(animator3);//同时xy方向
63         set.play(animator2).after(animator1);//再旋转
64         set.setDuration(1000);
65         set.start();
66
67
68
69     }
70 }
Animator 的 set 方法为我们提供了非常丰富的动画控制效果。例如:playTogether()同时播放,playSequentially()按顺序播放。
set还可以做更详细的顺序控制,如图
set.play(animator2).with(animator3); // 动画animator2和animator3同时进行
set.play(animator1).after(animator2); // 动画animator1在animator2(也可以写3)之后进行

这种方式也是属性动画框架中使用最多的一种:通过 ObjectAnimator 进行更精确的属性动画设置,只控制一个对象的一个属性,同时多个 ObjectAnimator 组合到 AnimatorSet 中,形成一个完整的动画效果。而且 AnimatorSet 可以通过调用 play()、with()、after()、before()、playTogether()、playSequentially()等方法,实现更为丰富的动画效果。

//---------------------监听事件---------------------------------------
 1 public class MainActivity extends ActionBarActivity {
 2
 3     @Override
 4     protected void onCreate(Bundle savedInstanceState) {
 5         super.onCreate(savedInstanceState);
 6         setContentView(R.layout.fragment_main);
 7
 8
 9     }
10
11     public void click(View view) {
12         ObjectAnimator animator=ObjectAnimator.ofFloat(view, "alpha", 0F,1F);
13     animator.setDuration(1000);
14     //-----------------方式2-------------
15 //    animator.addListener(new AnimatorListenerAdapter() {
16 //        @Override
17 //        public void onAnimationEnd(Animator animation) {
18 //            // TODO Auto-generated method stub
19 //            super.onAnimationEnd(animation);
20 //        }
21 //    });
22
23     //-----------------方式1-------------
24     animator.addListener(new AnimatorListener() {
25
26         @Override
27         public void onAnimationStart(Animator animation) {
28             // TODO Auto-generated method stub
29
30         }
31
32         @Override
33         public void onAnimationRepeat(Animator animation) {
34             // TODO Auto-generated method stub
35
36         }
37
38         @Override
39         public void onAnimationEnd(Animator animation) {
40             // TODO Auto-generated method stub
41             Toast.makeText(MainActivity.this,"动画完咯", 1).show();
42         }
43
44         @Override
45         public void onAnimationCancel(Animator animation) {
46             // TODO Auto-generated method stub
47
48         }
49     });
50     animator.start();
51
52
53     }
54 }
这里列举了几种插值器(以下都只是前缀,例如Accelerate表示AccelerateInterpolator):
Accelerate 加速变化
Decelerate 减速变化
AccelerateDecelerate 先加速再减速
Overshoot 在结束之前会超出预定位置一点点,然后回到预定位置
Bounce 最常见的回弹动画,例如自由落体的小球的回弹效果就是通过这样一个插值器实现的。
//-------------------------菜单展开效果------------------------------
 1 public class MainActivity extends ActionBarActivity implements OnClickListener {
 2     private int[] res = { R.id.imageView8, R.id.imageView2, R.id.imageView3,
 3             R.id.imageView4, R.id.imageView5, R.id.imageView6, R.id.imageView7,
 4             R.id.imageView1 };
 5     private List<ImageView> imageViewlist = new ArrayList<ImageView>();
 6
 7     private boolean flag = true;
 8
 9     @Override
10     protected void onCreate(Bundle savedInstanceState) {
11         super.onCreate(savedInstanceState);
12         setContentView(R.layout.fragment_main);
13         for (int i = 0; i < res.length; i++) {
14             ImageView imageView = (ImageView) findViewById(res[i]);
15             imageView.setOnClickListener(this);
16             imageViewlist.add(imageView);
17         }
18
19     }
20
21     @Override
22     public void onClick(View v) {
23         // TODO Auto-generated method stub
24         switch (v.getId()) {
25         case R.id.imageView8:
26             if (flag) {
27                 startAnim();
28             } else {
29                 closeAnim();
30             }
31             break;
32
33         default:
34             Toast.makeText(MainActivity.this, "click" + v.getId(), 1).show();
35             break;
36         }
37     }
38
39     private void closeAnim() {
40         // TODO Auto-generated method stub
41         for (int i = 1; i < res.length; i++) {
42             ObjectAnimator animator = ObjectAnimator.ofFloat(
43                     imageViewlist.get(i), "translationY", 40 * i, 0F);
44             animator.setDuration(500);
45             animator.setInterpolator(new BounceInterpolator());
46             animator.setStartDelay(i * 300);// 依次弹出
47             animator.start();
48             flag = true;
49         }
50     }
51
52     private void startAnim() {
53         // TODO Auto-generated method stub
54         for (int i = 1; i < res.length; i++) {
55             ObjectAnimator animator = ObjectAnimator.ofFloat(
56                     imageViewlist.get(i), "translationY", 0F, 40 * i);
57             animator.setDuration(500);
58             animator.setInterpolator(new BounceInterpolator());
59             animator.setStartDelay(i * 300);// 依次弹出
60             animator.start();
61             flag = false;
62         }
63     }
64
65 }
(float) (Math.sin(Math.toRadians((i - 1) * 90 / (6 - 1))) * 200)
其中,6是要展开的图标数,200是半径。
按照上面程序加入translationX,和translationY中可以以扇形展开。//--------------------ValueAnimator------------------------
1. 之前学过ObjectAnimator是作用于某一控件的某一属性,而ValueAnimator本身不作用于任何属性,本身也不会提供任何动画,简单而言,ValueAnimator是一个数值发生器,可以产生任何你想要的数值,Android系统给它提供了很多数值计算方法。
2. 那么,产生这些数值有什么用呢?其实,在属性动画中,如何产生每一步的具体动画效果,都是通过 ValueAnimator 计算出来的。比如要实现一个0到100的位移动画,随着时间的持续,数值也从0到100递增,有这些值,就可以作用这些属性,让它产生动画效果。
3. 那么,ValueAnimator 是如何产生这些值的呢?
首先,ValueAnimator 会根据动画已经进行的时间和总时间的比值,产生一个0到1的时间因子,有了这样的时间因子,经过相应的变换,就可以根据你的StartValue和EndValue,来生成中间的相应的值。同时,通过插值器的使用,我们还可以进一步控制每一个时间因子的产生值的变化速度,比如我们使用线性插值器,生成数值的时候就是一个线性变化,只要时间相同,增量就相同。
由于 ValueAnimator 本身不响应任何一个动画,也不能控制任何一个属性,所以它并没有 ObjectAnimator 使用得那么广泛。
4. 查看源码,我们可以发现 ObjectAnimator 是继承了 ValueAnimator。之前也说过了,正是由于 ValueAnimator 产生的动画变化的变化值,ObjectAnimator 才可以将它应用于我们的属性。因此,ObjectAnimator 实际上是对ValueAnimator的封装。
5. 那么,如何通过 ValueAnimator 去实现动画效果呢?这就需要使用动画监听事件了,我们可以监听ValueAnimator每一步所产生的值,通过这个值去实现相应的动画效果。

案例:使用ValueAnimator实现计数器:
如图所示的例子中,先使用ValueAnimator.ofInt(0,100)获取0到100之间的所有数字,并设置一个时间为5秒,然后,通过监听器(调用addUpdateListener())的监听事件,获取 ValueAnimator每一步变化所产生的值,通过这些值去设置Button的显示文字。至此,就实现了一个简单的计数器。
 1 public class MainActivity extends ActionBarActivity {
 2
 3     @Override
 4     protected void onCreate(Bundle savedInstanceState) {
 5         super.onCreate(savedInstanceState);
 6         setContentView(R.layout.fragment_main);
 7
 8     }
 9
10     public void click(View view) {
11
12         ValueAnimator animator1=ValueAnimator.ofObject(new TypeEvaluator<PointF>() {
13
14
15             @Override
16             public PointF evaluate(float fraction, PointF startValue,
17                     PointF endValue) {
18                 // TODO Auto-generated method stub
19                 return null;
20             }
21         });
22
23
24     //----------------------------------------------------------------
25         // 计时器的效果:5秒内从0变到100
26         final Button button = (Button) view;
27         ValueAnimator animator = ValueAnimator.ofInt(0, 100);
28         animator.setDuration(5000);
29         animator.addUpdateListener(new AnimatorUpdateListener() {
30
31             @Override
32             public void onAnimationUpdate(ValueAnimator animation) {
33                 // TODO Auto-generated method stub
34
35                 Integer value = (Integer) animation.getAnimatedValue();
36                 button.setText("" + value);
37
38             }
39         });
40         animator.start();
41     }
42 }
除了ValueAnimator.ofInt(),还有其他类型的数字生成器,其中ValueAnimator.ofObject()可以实现自定义的数字生成器。
参数中的fraction就是时间因子(0到1之间变化的数值)。通过fraction、startValue、endValue,通过各种各样的计算方式,就可以生成所有想要产生的值,不光能产生普通数据结构,通过泛型还可以定义更为复杂的数据结构。
ValueAnimator animator = ValueAnimator.ofObject(new TypeEvaluator() {
   @Override
   public Object evaluate(float fraction, Object startValue, Object endValue) {
      return null;
   }
});
生成泛型PointF(float类型的点坐标):
ValueAnimator animator = ValueAnimator.ofObject(new TypeEvaluator<PointF>() {
   @Override
   public PointF evaluate(float fraction, PointF startValue, PointF endValue) {
      return null;
   }
});
在方法evaluate()中可以添加各种各样的计算方式。
----------
第二重境界学无止境,ValueAnimator不仅仅可以应用于动画,也可以应用于Android的其他领域。
总结——常用属性
我们通过 ObjectAnimator 可以调用各种属性,只要这个属性具有get/set方法,我们就可以操纵它,如果这个属性没有提供get/set方法,或者我们想自定义一个属性,来让它进行一些改变,那么我们就要定义一个Property(属性),去实现它的set/get方法,就可以操作这样一个属性。
ObjectAnimator常用的一些操作属性:
1. translationX\translationY
2. rotation、rotationX\rotationY,这里的rotation是指3D的旋转。rotationX是水平方向的旋转,rotationY是垂直方向的旋转。
3. scaleX\scaleY  水平、垂直方向的缩放。
4. X\Y  具体会移动到的某个点。
5. alpha  透明度
属性动画框架执行的效率更高、效果更好。

总结——常用方法、类
1. ValueAnimator 数值发生器,可以实现很多很灵活的动画效果
2. ObjectAnimator 是ValueAnimator的一个子类,它封装了ValueAnimator,让我们更轻松地使用属性动画框架。我们通过ObjectAnimator来操作一个对象的属性,让对象产生一个动画效果。
3. AnimatorUpdateListener 监听事件
4. AnimatorListenerAdapter 监听事件
5. PropertyValuesHolder 控制动画集合的显示效果、顺序和流程控制
6. AnimatorSet 控制动画集合的显示效果、顺序和流程控制
7. TypeEvaluators  值计算器
8. Interpolators  插值器
值计算器和插值器用来控制具体产生的数值的一个变化规律以及变化状态。
				
时间: 2024-12-25 20:02:46

Android攻城狮属性动画赏析的相关文章

Android攻城狮基础动画

Android基础动画 1. Tween Animation 变换动画 2. Frame Animation 帧动画 3. Layout Animation 布局动画 4. Property Animation 属性动画 Tween Animation(变换动画)在Android中又被分为四种: Alpha:渐变透明度动画 Scale:渐变尺寸缩放动画 Translate:位置移动动画 Rotate:旋转动画 Tween Animation共同属性: 1. Duration:动画持续时间(单位:

Android攻城狮布局动画

LayoutAnimation(布局动画) 为View Groups添加动画 使用LayoutAnimationController 如图,给一个listView设置动画,使用了新的方法:setLayoutAnimation(). setOrder(LayoutAnimationController.XXXX)是设置动画的顺序,例如 ORDER.RANDOM 表示一个随机的顺序. listView就相当于一个View Groups,是一个容纳了很多View的(集合)视图组.然后我们通过布局动画把

创业公司求IOS、Android攻城狮一枚

地点:北京CBD附近(地铁1号线大望路) 魅力值:送珍贵期权 你要会: 1. IOS或者Android开发 2.能够处理类似微视/秒拍的视频录制功能 3.熟悉json 4.做过第三方登录 5.爱学习 6.no zuo 7.工作经验不限 如果你适合,就别再犹豫,发简历到[email protected](饶先生),或者加TA QQ随便骚扰,TA正在求骚扰 创业公司求IOS.Android攻城狮一枚,布布扣,bubuko.com

Android攻城狮CheckBox&amp;RadioGroup&amp;AutoCompleteTextView&amp;MultiAutoCompleteTextView&amp;ToggleButton

给子类加构造函数Source----Generate constractor from superclass 跑马灯效果的实现(Textview 循环): 1.定义textView标签的4个属性: android:singleLine="true"//使其只能单行 android:ellipsize="marquee"//去掉省略号 android:focusable = "true"//得到焦点 android : focusableInTou

Android攻城狮四种基础动画

AlphaAnimation(透明动画) 1.xml文件 <set xmlns:android="http://schemas.android.com/apk/res/android"> <!-- 渐变动画,表示从透明度10%到100%,持续时间为1秒 --> <alpha android:fromAlpha="0.1" android:toAlpha="1" android:duration="1000&

Android攻城狮动画组合

组合动画 案例一(续播1): 两个动画A和B,先播放动画A,设置A的AnimationListener(会重写3个方法),当其中一个方法onAnimationEnd()触发,也就是当A播放完毕的时候,开始播放B.核心代码如下: Animation loadAnimation = AnimationUtils.loadAnimation( this, R.anim.translate ); image.startAnimation(loadAnimation); // 开启动画A Animatio

Android攻城狮GridView(主菜单)

GridView布局文件声明GridViewjava里创建GridView 配置 1.准备数据源 2.新建适配器(SimpleAdapter) 3.GridView加载适配器 4.GridView配置监听器(OnItemClickListener) gridView实现过程: 1.准备数据源 dataList=new ArrayList<Map<String,Object>>(); 2.新建适配器(SimpleAdapter) adapter=new SimpleAdapter(t

Android攻城狮布局优化

Android常用的布局样式 1.LinearLayout(线性布局) 线性的 垂直的 水平的 2.RelativeLayout(相对布局) 最灵活的 3.TableLayout(表格布局) 现在被 GridView代替 4.AbsoluteLayout(绝对布局) 已淘汰 5.FrameLayout(帧布局) 布局叠加时使用 现在基本使用线性布局和相对布局,特殊情况会使用帧布局(视频暂停.缓冲文件等). Android布局原则 1.尽量多使用LinearLayout(线性布局)和Relativ

Android攻城狮Gallery和ImageSwitcher制作图片浏览器

使用Gallery 和 ImageSwitcher 制作图片浏览器 Gallery介绍 我们有时候在手机上或者PC上看到动态的图片,可以通过鼠标或者手指触摸来移动它,产生动态的图片滚动效果,还可以根据你的点击或者触摸来触发其他事件响应.同样的,在Android中也提供这种实现,这就是通过Gallery在UI上实现缩略图浏览器. ------------------------- 谷歌已经将Gallery列为过期的控件,建议使用HorizonScrollView或者ViewPager. -----