Android属性动画(Animator)
来源:互联网 发布:淘宝图片怎么搜索引擎 编辑:程序博客网 时间:2024/05/22 06:56
传统的Animation
动画虽然使用方便,但是不适合做具有交互性的动画效果,仅仅适合做展示性的动画,而Animator
,属性动画,是改变了该view
的内部属性,适合有交互功能的动画。
1.ObjectAnimator
代码:
//第一个参数,动画的对象,第二个参数,需要改变的动画属性,后边参数,变化的具体值(像素)//若写多个,则动画会同时实行,此例中即旋转360°的同时向x轴和y轴平移ObjectAnimator.ofFloat(iv, "rotation", 0f, 360f).setDuration(1000).start();ObjectAnimator.ofFloat(iv, "translationX", 0f, 200f).setDuration(1000).start();ObjectAnimator.ofFloat(iv, "translationY", 0f, 200f).setDuration(1000).start();
可用的属性有
2.PropertyValuesHolder
代码:
//效果同上,但动画效果做了优化,而且更有效率PropertyValuesHolder p1 = PropertyValuesHolder.ofFloat("rotation", 0f, 360f);PropertyValuesHolder p2 = PropertyValuesHolder.ofFloat("translationX", 0f, 200f);PropertyValuesHolder p3 = PropertyValuesHolder.ofFloat("translationY", 0f, 200f);//调用ofPropertyValuesHolder方法传入要动画的控件和PropertyValuesHolderObjectAnimator.ofPropertyValuesHolder(iv, p1, p2, p3).setDuration(1000).start();
3.AnimatorSet
提供了更多的动画控制效果
代码:
ObjectAnimator animator1 = ObjectAnimator.ofFloat(iv, "rotation", 0f, 360f);ObjectAnimator animator2 = ObjectAnimator.ofFloat(iv, "translationX", 0f, 200f);ObjectAnimator animator3 = ObjectAnimator.ofFloat(iv, "translationY", 0f, 200f);AnimatorSet set = new AnimatorSet();set.playTogether(animator1, animator2, animator3);//同时执行// set.playSequentially(animator1, animator2, animator3); //按顺序执行set.setDuration(1000);set.start();
还可以先x轴和y轴同时平移,最后才旋转
代码:
//将set.playTogether()替换为如下代码set.play(animator2).with(animator3);//with表示同时一起执行set.play(animator1).after(animator2);//after 2 或者 3 都可以
4.Animator监听事件
代码:
ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(iv, "alpha", 0f, 1f);objectAnimator.setDuration(1000);//添加adapter来只监听某个事件或者如下注释的全部监听objectAnimator.addListener(new AnimatorListenerAdapter() {@Overridepublic void onAnimationEnd(Animator animation) { super.onAnimationEnd(animation); Toast.makeText(getApplicationContext(), "别点了!", Toast.LENGTH_LONG).show(); }});// objectAnimator.addListener(new Animator.AnimatorListener() {// @Override// public void onAnimationStart(Animator animation) {//// }//// @Override// public void onAnimationEnd(Animator animation) {// Toast.makeText(getApplicationContext(), "别点了!", Toast.LENGTH_LONG).show();// }//// @Override// public void onAnimationCancel(Animator animation) {//// }//// @Override// public void onAnimationRepeat(Animator animation) {//// }// });objectAnimator.start();
5.ValueAnimator的使用
ValueAnimator
可以当做数值发生器,生产具有一定规律的数字,从而来控制动画的过程。
例如:
代码:按钮的点击事件中,设置ValueAnimator
ValueAnimator animator = ValueAnimator.ofInt(0, 100);animator.setDuration(5000);animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { //获取动画过程中的value(上边定义的0~100),用以其他逻辑,例如设置文字 Integer value = (Integer) animation.getAnimatedValue(); bt.setText("" + value); }});animator.start();
6.View的animate方法
View
直接就有animate()
方法,用以直接驱动简单的属性动画
代码:
bt_time.animate() .alpha(0). setDuration(1000). withStartAction(new Runnable() { @Override public void run() { } }) .withEndAction(new Runnable() { @Override public void run() { } }) .start();
7.ObjectAnimator可改变的属性
属性动画中,可改变的属性,都是对象中对该属性提供了set和get
方法的属性,若没有提供set和get
方法,则无法正常使用,例如Button
的width和height
属性,虽然有bt.setWidth()和bt.setHeight()
方法,但是源码里即可看到,该方法是改变了Button
的最大宽度和高度,并不是改变了该Button
的属性,即没有本质上改变,所以使用属性动画改变Button
的width和height
方法是无效的,即使用语句
// bt = findViewById(R.id.xxx);ObjectAnimator.ofFloat(bt, "height", 0f, 360f).setDuration(1000).start();
无法达到想要的效果,有两种解决办法。
方法一:使用包装类对要操作的对象属性进行控制,例如
代码:(新建的Wrapper包装类)
public class Wrapper { private TextView tv; private int width; private int height; // 对宽和高的真实值进行设置,属性有width和height,必须实现他们的get和set方法 public int getHeight() { return this.tv.getHeight(); } public void setHeight(int height) { ViewGroup.LayoutParams params = tv.getLayoutParams(); params.height = height; tv.setLayoutParams(params); } public int getWidth() { return this.tv.getWidth(); } public void setWidth(int width) { ViewGroup.LayoutParams params = tv.getLayoutParams(); params.width = width; tv.setLayoutParams(params); } public Wrapper(TextView tv) { this.tv = tv; }}
然后就是使用代码:
// tv = findViewById(R.id.xxx);Wrapper wrapper = new Wrapper(tv);// 传入wrapperObjectAnimator objectAnimator = ObjectAnimator.ofInt(wrapper, "height", (int) getPX(0), (int) getPX(50));//dp 2 pxobjectAnimator.setDuration(2000);objectAnimator.start();
这样,通过包装类 ,可以真实地控制tv的宽和高
方法二:使用ValueAnimator
ValueAnimator
的动画监听函数里可以对控件宽高直接操作
代码:
ValueAnimator animator = ValueAnimator.ofFloat(1, 100);animator.setDuration(500);animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { float value = (float) animation.getAnimatedValue(); RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) tv.getLayoutParams(); layoutParams.height = (int) (value * getPX(50)); tv.setLayoutParams(layoutParams); }});animator.start();
8.ValueAnimator和TypeEvaluator结合练习
TypeEvaluator
即估值器,可以根据动画的进展来估算出要改变的数据大小,进而将这些数据设置给控件的属性从而形成动画。如下代码中。
ValueAnimator.ofObject(evaluator, start, end);
.ofObject()
,传入的就是一个继承了TypeEvaluator的估值器。
先实现一个小例子,如下的动画
代码实现:
1.先循环创建出5个TextView
,注意动态设置id的时候不要设置成0,否则,若父布局是RelativeLayout
时,设置添加规则时,因为在如下语句中
params.addRule(RelativeLayout.BELOW, i);
查看源码如图所示:
第二个参数是规则参照的id,但是为0 的时候,规则无效。
代码:
for (int i = 0; i < 5; i++) { TextView tv = new TextView(getApplicationContext()); tv.setId(i + 1); RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT); params.setMargins(getDP(0), getDP(10), getDP(0), getDP(0)); params.addRule(RelativeLayout.ALIGN_PARENT_LEFT); if (i > 0) { params.addRule(RelativeLayout.BELOW, i); } else { params.addRule(RelativeLayout.BELOW, tv_show.getId()); params.topMargin = getDP(100); } tv.setLayoutParams(params); tv.getLayoutParams().height = getDP(30); tv.getLayoutParams().width = getDP(30); tv.setBackgroundResource(R.drawable.circle); tv.setOnClickListener(this); rl.addView(tv);}
2.创建自定义的TypeEvaluator,运动轨迹是二次的贝塞尔曲线,midPoint
为二次贝塞尔曲线的公式中的P1
代码:
public class BallEvaluator implements TypeEvaluator<Point> { private Point midPoint; public BallEvaluator(Point midPoint) { this.midPoint = midPoint; } @Override public Point evaluate(float t, Point startValue, Point endValue) { int x = (int) ((1 - t) * (1 - t) * startValue.x + 2 * t * (1 - t) * midPoint.x + t * t * endValue.x); int y = (int) ((1 - t) * (1 - t) * startValue.y + 2 * t * (1 - t) * midPoint.y + t * t * endValue.y); return new Point(x, y); }}
3.点击响应事件中,获取各个view的位置,并创建ValueAnimator对象,传入TypeEvaluator对象实例
代码:
// 点击事件函数private void start(final View v) { // 创建用以移动的view,位置即是当前view的位置 final TextView tv = new TextView(getApplicationContext()); RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT); tv.setLayoutParams(params); tv.getLayoutParams().height = getDP(30); tv.getLayoutParams().width = getDP(30); tv.setBackgroundResource(R.drawable.circle); tv.setX(v.getX()); tv.setY(v.getY()); rl.addView(tv); // 加入,记得删除 // 开始点P0 int now_x = (int) v.getX(); int now_y = (int) v.getY(); Point startposition = new Point(now_x, now_y); //中间点P1 int mid_pointX = (now_x + width) / 2; int mid_pointY = now_y - getDP(300); // 向上少许的抛物线 Point midPoint = new Point(mid_pointX, mid_pointY); //结束点P2 int tv_x = (int) tv_end.getX(); int tv_y = (int) tv_end.getY(); Point endposition = new Point(tv_x, tv_y); BallEvaluator ballEvaluator = new BallEvaluator(midPoint); ValueAnimator animator = ValueAnimator.ofObject(ballEvaluator, startposition, endposition); animator.setDuration(400); animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { Point point = (Point) animation.getAnimatedValue(); tv.setX(point.x); tv.setY(point.y); } }); animator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { super.onAnimationEnd(animation); rl.removeView(tv); // 移除创建的view tv_end.setText(String.valueOf(++count)); //最后数字+1 } }); animator.start();}
- android属性动画animator
- Android属性动画(Animator)
- Android之属性动画Animator
- Android Animator属性动画总结
- Android之Animator属性动画
- Android 动画之属性动画(Animator)
- Android动画之(Property Animator(属性动画))
- android属性动画Animator(一)
- Android-Animator属性动画( ObjectAnimator , AnimatorSet , ValueAnimator )
- Android——Animator笔记:属性动画
- 4.4.5 Android 属性动画Animator
- Android:属性动画 Animator类的记录
- 【Android - 基础】之Animator属性动画
- Android 属性动画,Animator,ValueAnimator,ObjectAnimator, AnimatorSet
- 属性动画Animator
- 属性动画Animator学习
- Animator属性动画
- animator属性动画
- 中文乱码问题
- javaweb连接mysql的两种方法
- java中的Cipher类
- 使用apt-get和nvm安装node的区别
- Scala的学习
- Android属性动画(Animator)
- 解决当FORM的ENCTYPE="multipart/form-data" 时request.getParameter()获取不到值的问题
- xml介绍与解析
- python中如何避免中文是乱码
- 设计模式——单例模式
- 全局变量、局部变量
- HDU 2034 人见人爱A-B
- Maven动态切换配置文件
- PHP文件上传