zoukankan      html  css  js  c++  java
  • 【Android】属性动画

    转载请注明出处:http://blog.csdn.net/h28496/44338669


    属性动画的原理

    通过不断的设置一个View的属性让其出现动画效果。比如,不断地设置一个Button的x值。这个button就会在y轴上运动。

    假设学过flash或者其它动画制作的话。应该能理解“补间动画”的意思。属性动画类似于属性上的补间动画。

    设置一个View的初始值和结束值,属性动画会随着时间的变化,逐渐地把View的属性从初始值变化到结束值。


    实现属性动画的条件

    由属性动画的原理可知,要实如今某个方面的动画。首先这个View得有这个属性。即,要有 set属性名() 和 get属性名()方法。

    比如:setWidth(), getWidth()。

    注意:button自带的getWidth() 和 setWidth()在这里是没有效果的。回忆一下在代码中设置一个button的宽度是怎么设置的?

    在代码中设置宽度:

    button.getLayoutParams().width = 100;
    它相应于xml文件里的是
    android:layout_width
    而不是

    android:width
    至于width有什么用,我感觉没什么用……看过其它大牛写的博客。也是不太清楚android:width有什么用。


    一个简单的样例

    效果:点击了Button之后按x轴翻转。

    Button的布局文件非常普通。不贴了。

    	public void onClick(View view) {
    		ObjectAnimator
    		.ofFloat(view, "rotationX", 0f, 360f)
    		.setDuration(1000)
    		.start();
    	}
    解释一下:由于Button这个类存在 setRotationX(float p)这种方法。所以第三行的第二个參数 “rotationX” 是有效的。

    假设写的是一个不存在的參数,或者设置的參数和画面无关,那么画面是没有动画的。

    另外,因为setRotationX(float p)的參数类型是float型的,所以第三行用的是 ofFloat(...) 而不是 ofInt(...)或者其它。

    setDuration(int p)是动画的时长。单位毫秒。


    我在看任玉刚大牛写的博客时他写道,假设没有set属性名()这种方法会导致程序崩溃。但我实測时没有崩溃,仅仅是在logcat报了一条错误,程序继续执行。


    假设条件不满足怎么办

    假设你想给某个View设置一个动画,可是它没有相应的设置属性的方法怎么办?比如:

    我们想给button设置一个宽度逐渐变宽的动画,可是button的setWidth()不能设置显示宽度。

    解决的办法:

    ① 加上set属性()、get属性()方法;(除非是你自己定义的控件,否则一般没有权限这么做,以下就不讨论这样的情况了)

    ② 用一个类去包装原始的对象。间接的提供get、set方法;

    ③ 採用ValueAnimation获得每个时刻的属性值,然后通过AnimatorUpdateListener监听器依据获得的属性值设置View的状态。

    包装原始对象

    用这样的方式为一个不存在某种方法的类加入方法非经常见。考虑到多态,通常包装比继承要好得多。

    以下是用MyView包装View的样例:

    class MyView{
    	View view;
    	
    	public MyView(View view){
    		this.view = view;
    	}
    	
    	public int getWidth(){
    		return view.getLayoutParams().width;
    	}
    	
    	public void setWidth(int width){
    		this.view.getLayoutParams().width = width;
    		this.view.requestLayout();	// 这句话用来又一次设置view的位置
    	}	
    }
    有了包装类。我们就来实现一个让Button(它是继承自View的)宽度变宽的动画吧。

    效果:在300毫秒内,view的宽度先变成4倍,再恢复到原来的样子。

    	public void onClick(View v) {
    		MyView view = new MyView(v);// 先包装一下
    		int startWidth = v.getWidth();
    		ObjectAnimator.ofInt(view, "width", startWidth, startWidth * 4, startWidth)
    		.setDuration(300)
    		.start();
    	}

    使用ValueAnimator和AnimatorUpdateListener自己实现

    效果:在一秒的时间内,view从y = 0,移动到 y  = 500的地方。

    	public void onClick(final View view){
    		final ValueAnimator anim = ValueAnimator.ofFloat(0, 500);
    		anim.setDuration(1000);
    		anim.start();
    		
    		anim.addUpdateListener(new AnimatorUpdateListener() {
    			
    			@Override
    			public void onAnimationUpdate(ValueAnimator animation) {
    				float value = (Float) animation.getAnimatedValue();
    				view.setTranslationY(value);
    			}
    		});
    	}

    先定义一个值动画(ValueAnimator,中文名个人是意译的)。从名称能够看出,它仅仅是一个“值”的变化,并不涉及到详细的视图。
    然后再对这个值动画设置一个监听器。每次值有变化的时候。都将这个值应用到视图的属性上去。

    比如。值每变化一次,都要又一次设置一下位置。

    尽管看起来麻烦了一点。但灵活性更高了。



    多个动画同一时候运行

    上面的三个样例中。动画都是单独一个。假设我想要在它移动的同一时候还要改变它的透明度怎么办呢?

    和上面的类似。能够利用AnimatorUpdateListener实现。

    ② 利用PropertyValuesHolder实现;

    ③ 利用AnimatorSet实现。


    利用AnimatorUpdateListener实现

    上一个样例中仅仅设置了视图的位置,但实际上能够同一时候将视图的多个属性设置为那个值。

    仅仅需多加几个.set属性()。

    这里为了避免反复,不使用ValueAnimator,而是使用ObjectAnimator。


    效果:被点击的视图在1秒内。先变小同一时候颜色减淡到无,之后再恢复到原状。(建议使用一个ImageView而不是Button,效果更好)

    	public void onClick(final View v){
    		ObjectAnimator anim = ObjectAnimator.ofFloat(v, "", 1, 0, 1)
    				.setDuration(1000);
    		anim.start();
    		
    		anim.addUpdateListener(new AnimatorUpdateListener() {
    			
    			@Override
    			public void onAnimationUpdate(ValueAnimator animation) {
    				float currentValue = (Float) animation.getAnimatedValue();
    				v.setScaleX(currentValue);
    				v.setScaleY(currentValue);
    				v.setAlpha(currentValue);
    			}
    		});		
    	}
    ObjectAnimator和ValueAnimator一样,也是能够加入监听器的。


    利用PropertyValuesHolder实现

    这样的实现方式代码非常简洁,一看便懂。

    效果:被点击的视图在1秒内,先变小、颜色减淡到无,之后再恢复到原状,同一时候整个过程视图旋转了360度。(建议使用一个ImageView而不是Button,效果更好)

    	public void onClick(View view){		
    		PropertyValuesHolder x = PropertyValuesHolder.ofFloat("scaleX", 1, 0, 1);
    		PropertyValuesHolder y = PropertyValuesHolder.ofFloat("scaleY", 1, 0, 1);
    		PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha", 1, 0, 1);
    		PropertyValuesHolder rotation = PropertyValuesHolder.ofFloat("rotation", 0, 360);
    		
    		ObjectAnimator.ofPropertyValuesHolder(view, x, y, alpha, rotation).setDuration(1000).start();
    	}

    利用AnimatorSet实现

    从名字能够看出。这是一个动画的集合。AnimatorSet能够让多个动画同一时候执行、先后执行

    同一时候执行

    效果:被点击的视图在X方向变大的同一时候。Y方向也变大。之后又同一时候缩小(建议使用一个ImageView而不是Button,效果更好)

    	public void togetherRun(View view){
    		// 感觉和PropertyValuesHolder差点儿相同
    		ObjectAnimator x = ObjectAnimator.ofFloat(view, "scaleX", 1, 2, 1);
    		ObjectAnimator y = ObjectAnimator.ofFloat(view, "scaleY", 1, 2, 1);
    		
    		AnimatorSet animSet = new  AnimatorSet();
    		animSet.setDuration(1000);
    		
    		animSet.playTogether(x, y);
    		animSet.start();		
    	}

    playTogether(Animator... items)能够让多个动画同一时候运行。除此之外。还有playWidth(Animator item)能够让两个动画同一时候运行。


    先后执行

    效果:被点击的视图在X、y方向变大又缩小,之后再平移到右边并返回(建议使用一个ImageView而不是Button。效果更好)

    	public void playAfter(View view){
    		ObjectAnimator scaleX = ObjectAnimator.ofFloat(ball, "scaleX", 1, 2, 1);
    		ObjectAnimator scaleY = ObjectAnimator.ofFloat(ball, "scaleY", 1, 2, 1);
    		
    		ObjectAnimator x = ObjectAnimator.ofFloat(ball, "x", ball.getX(), ball.getX() + 200, ball.getX());
    		
    		AnimatorSet animSet = new AnimatorSet();
    		// 支持链式编程
    		animSet.play(scaleX).with(scaleY);
    		animSet.play(x).after(scaleY);
    		animSet.setDuration(1000);
    		animSet.start();
    	}	
    }
    在先后运行的时候,还能够调用animSet.play(x).after(延迟时间); 使得下一个动画延迟播放。

    这里使用的是animSet.play(x).after(scaleY); 即在还有一个动画播放完之后再播放,也能够使用

    animSet.play(x).before(anim1); 
    让一个动画在还有一个动画播放前播放。


    怎样监听动画的结束

    animation有三种监听器:

    ① AnimatorUpdateListener(监听在动画运行过程中的数据或其他情况)

    ② AnimatorListener(监听动画的‘生命周期’)

    ③ AnimatorPauseListener(监听动画的暂停与恢复)


    有时我们须要在动画结束之后做点事。比如:在点击一个button结束后跳转到还有一个Activity。

    这时我们仅仅需让动画加入一个AnimatorListener监听器。

    anim.addListener(new AnimatorListener() {
    			
    			@Override
    			public void onAnimationStart(Animator animation) {
    				// TODO Auto-generated method stub
    				
    			}
    			
    			@Override
    			public void onAnimationRepeat(Animator animation) {
    				// TODO Auto-generated method stub
    				
    			}
    			
    			@Override
    			public void onAnimationEnd(Animator animation) {
    				// TODO Auto-generated method stub
    				// 在这里加入动画结束后要做的事
    			}
    			
    			@Override
    			public void onAnimationCancel(Animator animation) {
    				// TODO Auto-generated method stub
    				
    			}
    		});

    如上所看到的,动画共同拥有四个状态。有时我们并不须要实现全部的方法,仅仅须要当中一个状态就能够了。那我们能够使用AnimatorListenerAdapter。它继承了AnimatorListener接口。

    空实现了全部方法。

    演示样例:

    anim.addListener(new AnimatorListenerAdapter() {
    			@Override
    			public void onAnimationEnd(Animator animation) {
    				view.setY(startY);
    			}			
    		});


    安卓的属性动画大致就讲完了。



    參考资料:

    http://blog.csdn.net/lmj623565791/article/details/38067475

    http://blog.csdn.net/singwhatiwanna/article/details/17841165

  • 相关阅读:
    shutil使用
    python解压压缩包
    python配置主机名
    ansible加速不管用
    重启sshd服务
    shell脚本安装python、pip-----非交互式的--批量执行函数
    查看日志
    etcd安全集群三节点扩容至四个节点
    ssh免密登录
    行为型模式之状态模式
  • 原文地址:https://www.cnblogs.com/blfshiye/p/5094369.html
Copyright © 2011-2022 走看看