android image 位移动画-凯发k8官方网
android 里动画从用途上讲,可以分为三类view animation(view动画)又称 tween animation(补间动画)、drawable animation(帧动画) 和 property animation(属性动画)。 这篇文章,我就介绍一下这三种类型的动画。
目录:
(一)view动画
view动画是基于view的渐变动画,只改变了view的绘制效果,view的实际属性值并未改变。
view动画的对象是view,它支持4种动画效果:
translateanimation(平移动画)
scaleanimation(缩放动画)
rotateanimation(旋转动画)
alphaanimation(透明度动画)
并提供了animationset动画集合。实现原理是每次绘图时view所在的viewgroup中的dispathdraw,流程如下图:
除了这四种典型的动画效果外,帧动画本质上也属于view动画。但是帧动画的表现形式和这4种动画不太一样,因此通常单拎出来归为一类。
这四种动画既可以通过xml来定义,也可以通过代码来动态创建。
使用xml之前我们首先需要创建xml文件,路径为:res/anim/filename.xml。
1. 透明度动画
代码实现:alphaanimation animation = new alphaanimation(0, 1);// 透明度0变化到透明度为1
animation.setduration(1000);// 动画执行时间1s
textview.startanimation(animation);
xml实现:
android:duration="1000"
android:fromalpha="0"
android:interpolator="@android:anim/accelerate_interpolator"
android:repeatcount="3"
android:fillafter="true"
android:repeatmode="restart"
android:toalpha="1" />
2. 旋转动画
代码实现:rotateanimation animation = new rotateanimation(0, 360, 100, 100);
animation.setduration(1000);
animation.setfillafter(true); // 设置保持动画最后的状态
animation.setinterpolator(new accelerateinterpolator()); // 设置插入器
textview.startanimation(animation);
还可以通过系统提供参数来控制动画
new rotateanimation(0f, 360f, animation.relative_to_self, 0.5f, animation.relative_to_self, 0.5f);
xml实现:
android:duration="1000"
android:fromdegrees="0.0"
android:interpolator="@android:anim/linear_interpolator"
android:pivotx="50.0%"
android:pivoty="50.0%"
android:repeatcount="infinite"
android:todegrees="360.0">
参数
说明fromdegrees
为动画起始时的旋转角度,此角度是当前为0及360,设置其他值则先跳至该角度的位置再由from - to的值: 负则正向转,正则反向转
todegrees
为动画旋转到的角度
pivotxtype
为动画在x轴相对于物件位置类型
pivotxvalue
为动画相对于物件的x坐标的开始位置,此值是以本身原始位置为原点,即如设为20%p,则向右移动父控件的20%位移,为负数则向左移
pivotytype
为动画在y轴相对于物件位置类型
pivotyvalue
为动画相对于物件的y坐标的开始位置,此值是以本身原始位置为原点,即如设为20%p,则向下移动父控件的20%位移,为负数则向上移
3. 位移动画
代码实现:translateanimation translateanimation = new translateanimation(0, 200, 0, 200);
translateanimation.setduration(1000);
textview.startanimation(translateanimation);
xml实现:
android:duration="1000"
android:fillafter="true"
android:fromxdelta="0"
android:fromydelta="0"
android:repeatcount="3"
android:toxdelta="200"
android:toydelta="000">
参数
说明fromxdelta
为动画起始时 x坐标上的移动位置
toxdelta
为动画结束时 x坐标上的移动位置
fromydelta
为动画起始时y坐标上的移动位置
toydelta
为动画结束时y坐标上的移动位置
4. 缩放动画
代码实现:scaleanimation animation = new scaleanimation(0,1,0,1);
animation.setduration(1000);
textview.startanimation(animation);
缩放动画也可以设置缩放的中心点
scaleanimation animation = new scaleanimation(0, 1, 0, 1, animation.relative_to_self, 0.5f, animation.relative_to_self, 0.5f);
xml实现:
android:duration="1000"
android:fillafter="true"
android:fillbefore="true"
android:fromxscale="0.0"
android:fromyscale="0.0"
android:interpolator="@android:anim/linear_interpolator"
android:pivotx="50%"
android:pivoty="50%"
android:repeatcount="-1"
android:repeatmode="reverse"
android:startoffset="2000"
android:toxscale="1.0"
android:toyscale="1.0">
参数
说明fromx
为动画起始时 x坐标上的伸缩尺寸 0.0表示收缩到没有
tox
为动画结束时 x坐标上的伸缩尺寸 1.0表示正常无伸缩
fromy
为动画起始时y坐标上的伸缩尺寸 值小于1.0表示收缩
toy
为动画结束时y坐标上的伸缩尺寸 值大于1.0表示放大
pivotxtype
为动画在x轴相对于物件位置类型
pivotxvalue
为动画相对于物件的x坐标的开始位置
pivotxtype
为动画在y轴相对于物件位置类型
pivotyvalue
为动画相对于物件的y坐标的开始位置
5. anim文件使用
animation animation = animationutils.loadanimation(this, r.anim.alpha_anim);
textview.startanimation(animation);
6. 动画集合
animationset提供了一个把多个动画组合成一个组合的机制,并可设置组中动画的时序关系,如同时播放,顺序播放等。
animationset animationset = new animationset(true);
animationset.setduration(1000);
alphaanimation alpha=new alphaanimation(0,1);
alpha.setduration(1000);
animationset.addanimation(alpha);
translateanimation translate = new translateanimation(100, 200, 0, 200);
translate.setduration(1000);
animationset.addanimation(translate);
textview.startanimation(animationset);
7. 动画监听
对于动画事件,android也提供了开始、结束和重复事件的监听方法。
animation.setanimationlistener(new animation.animationlistener() {
@override
public void onanimationstart(animation animation) {
}
@override
public void onanimationend(animation animation) {
}
@override
public void onanimationrepeat(animation animation) {
}
});
8. view动画的特殊使用
(1)layoutanimation
layoutanimation作用于viewgroup,为viewgroup制定一个动画,他的每个子元素都会按照这种动画出场。这种效果常被用在listview上。使用步骤如下:
1)定义layoutanimation
android:delay="0.5"
android:animationorder="reverse"
android:animation="@anim/animation_scale">
android:delay 表示子元素开始动画的时间延迟
android:animationorder 表示子元素动画的顺序,有三个选项:
normal:顺序显示
reverse:表示逆向显示
random:随机播放
android:animation 为子元素指定具体的入场动画
2)为子元素制定具体的入场动画
android:fromxscale="0.1"
android:toxscale="1.5"
android:fromyscale="0.1"
android:toyscale="1.5"
android:duration="2000">
3)为groupview指定layoutanimation属性
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@ id/xlv"
android:layoutanimation="@anim/animation_layout"
android:background="#fff4f7f9"
android:divider="#ddd"
android:dividerheight="1.0px"
android:listselector="#999">
除了在xml文件中进行设置,我们还可以使用代码来完成:
animation animation = animationutils.loadanimation(this, r.anim.anim_item);
layoutanimationcontroller controller = new layoutanimationcontroller(animation);
controller.setdelay(0.5f);
controller.setorder(layoutanimationcontroller.order_normal);
listview.setlayoutanimation(controller);
(2)transition animation(过渡动画)
transition也是基于属性动画的,与属性动画不同的是,它是可以实现布局改变的过渡动画。由于transition的内容较多,具体请参照
(二)帧动画
帧动画就是加载一系列drawable资源来创建动画,这种传统动画某种程度上就是创建不同图片序列,顺序播放,就像电影胶片。在代码中定义动画帧,使用animationdrawable类;xml文件能更简单的组成动画帧,在res/drawable文件夹,使用采用来定义不同的帧。只能设置的属性是动画间隔时间。
android:oneshot="false">
...
然后对组件的属性(如imageview的android:src/android:background)直接设置即可。
imageview iv = findviewbyid(r.id.image_view);
//iv.setbackgroundresource(r.drawable.drawable_animation);
//获取背景,并将其强转成animationdrawable
animationdrawable animationdrawable = (animationdrawable) iv.getbackground();
//判断是否在运行
if(!animationdrawable.isrunning()){
//开启帧动画
animationdrawable.start();
}
注意:帧动画的使用非常简单,但是比较容易引起oom,所以在使用帧动画时应尽量避免使用过多尺寸较大的图片。
(三)属性动画
属性动画的对象除了传统的view对象,还可以是object对象,动画之后,属性值被实实在在的改变了。因此,属性动画能够通过改变view对象的实际属性来实现view动画。任何时候view属性的改变,view能自动调用invalidate()来刷新。
属性动画是在 android 3.0 开始引入的新的动画形式,不过说它新只是相对的,它已经有好几年的历史了,而且现在的项目中的动画 99% 都是用的它,极少再用到 view animation 了。属性动画不仅可以使用自带的 api 来实现最常用的动画,而且通过自定义 view 的方式来做出定制化的动画。
1. viewpropertyanimator
使用方式:
view.animate() 后跟 translationx() 等方法,动画会自动执行。
view.animate().translationx(500);
2. objectanimator
使用方式:
如果是自定义控件,需要添加 setter / getter 方法;
用 objectanimator.ofxxx() 创建 objectanimator 对象;
用 start() 方法执行动画。public class sportsview extends view {
float progress = 0;
......
// 创建 getter 方法
public float getprogress() {
return progress;
}
// 创建 setter 方法
public void setprogress(float progress) {
this.progress = progress;
invalidate();
}
@override
public void ondraw(canvas canvas) {
super.ondraw(canvas);
......
canvas.drawarc(arcrectf, 135, progress * 2.7f, false, paint);
......
}
}
......
// 创建 objectanimator 对象
objectanimator animator = objectanimator.offloat(view, "progress", 0, 65);
// 执行动画
animator.start();
3. 通用功能
(1)setduration(int duration) 设置动画时长
(2)setinterpolator(interpolator interpolator) 设置 interpolator(插值器)
acceleratedecelerateinterpolator 先加速再减速 (默认的 interpolator)
linearinterpolator 匀速
accelerateinterpolator 持续加速
decelerateinterpolator 持续减速直到 0
anticipateinterpolator 先回拉一下再进行正常动画轨迹
overshootinterpolator 动画会超过目标值一些,然后再弹回来
anticipateovershootinterpolator 上面这两个的结合版:开始前回拉,最后超过一些然后回弹
bounceinterpolator 在目标值处弹跳
cycleinterpolator 这个也是一个正弦 / 余弦曲线
fastoutlinearininterpolator 用贝塞尔曲线持续加速
linearoutslowininterpolator 持续减速,初始速度更高
pathinterpolator 自定义动画完成度 / 时间完成度曲线path interpolatorpath = new path();
...
// 匀速
interpolatorpath.lineto(1, 1);
(3)setlistener() / objectanimator.addlistener() 设置监听器
参数类型是 animatorlistener,所以本质上其实都是一样的。 animatorlistener共有 4 个回调方法:
onanimationstart(animator animation)
onanimationend(animator animation)
onanimationcancel(animator animation)
onanimationrepeat(animator animation)
补充:setupdatelistener() /addupdatelistener()
和上面两个方法类似,但是这两个方法虽然名称和可设置的监听器数量不一样,但本质其实都一样的。它们的参数都是 animatorupdatelistener。它只有一个回调方法:
onanimationupdate(valueanimator animation)
4. typeevaluator
关于 objectanimator,可以用 ofint() 来做整数的属性动画和用 offloat() 来做小数的属性动画。这两种属性类型是属性动画最常用的两种,不过在实际的开发中,可以做属性动画的类型还是有其他的一些类型。当需要对其他类型来做属性动画的时候,就需要用到 typeevaluator 了。
(1)argbevaluator
typeevaluator 最经典的用法是使用 argbevaluator 来做颜色渐变的动画。
objectanimator animator = objectanimator.ofint(view, "color", 0xffff0000, 0xff00ff00);
animator.setevaluator(new argbevaluator());
animator.start();
在 android 5.0 (api 21) 加入了新的方法 ofargb()。
objectanimator animator = objectanimator.ofargb(view, "color", 0xffff0000, 0xff00ff00);
animator.start();
(2)自定义 evaluator
// 自定义 hslevaluator
private class hsvevaluator implements typeevaluator {
float[] starthsv = new float[3];
float[] endhsv = new float[3];
float[] outhsv = new float[3];
@override
public integer evaluate(float fraction, integer startvalue, integer endvalue) {
// 把 argb 转换成 hsv
color.colortohsv(startvalue, starthsv);
color.colortohsv(endvalue, endhsv);
// 计算当前动画完成度(fraction)所对应的颜色值
if (endhsv[0] - starthsv[0] > 180) {
endhsv[0] -= 360;
} else if (endhsv[0] - starthsv[0] < -180) {
endhsv[0] = 360;
}
outhsv[0] = starthsv[0] (endhsv[0] - starthsv[0]) * fraction;
if (outhsv[0] > 360) {
outhsv[0] -= 360;
} else if (outhsv[0] < 0) {
outhsv[0] = 360;
}
outhsv[1] = starthsv[1] (endhsv[1] - starthsv[1]) * fraction;
outhsv[2] = starthsv[2] (endhsv[2] - starthsv[2]) * fraction;
// 计算当前动画完成度(fraction)所对应的透明度
int alpha = startvalue >> 24 (int) ((endvalue >> 24 - startvalue >> 24) * fraction);
// 把 hsv 转换回 argb 返回
return color.hsvtocolor(alpha, outhsv);
}
}
objectanimator animator = objectanimator.ofint(view, "color", 0xff00ff00);
// 使用自定义的 hslevaluator
animator.setevaluator(new hsvevaluator());
animator.start();
(3)使用不限定类型的属性做动画
借助于 typeevaluator,属性动画就可以通过 ofobject() 来对不限定类型的属性做动画了。
1)为目标属性写一个自定义的 typeevaluator
2)使用 ofobject() 来创建 animator,并把自定义的 typeevaluator 作为参数填入
private class pointfevaluator implements typeevaluator {
pointf newpoint = new pointf();
@override
public pointf evaluate(float fraction, pointf startvalue, pointf endvalue) {
float x = startvalue.x (fraction * (endvalue.x - startvalue.x));
float y = startvalue.y (fraction * (endvalue.y - startvalue.y));
newpoint.set(x, y);
return newpoint;
}
}
objectanimator animator = objectanimator.ofobject(view, "position",
new pointfevaluator(), new pointf(0, 0), new pointf(1, 1));
animator.start();
5. propertyvaluesholder
很多时候,我们需要在同一个动画中改变多个属性,例如在改变透明度的同时改变尺寸。如果使用 viewpropertyanimator,你可以直接用连写的方式来在一个动画中同时改变多个属性。
view.animate()
.scalex(1)
.scaley(1)
.alpha(1);
而对于 objectanimator,是不能这么用的。不过你可以使用 propertyvaluesholder 来同时在一个动画中改变多个属性。
propertyvaluesholder holder1 = propertyvaluesholder.offloat("scalex", 1);
propertyvaluesholder holder2 = propertyvaluesholder.offloat("scaley", 1);
propertyvaluesholder holder3 = propertyvaluesholder.offloat("alpha", 1);
objectanimator animator = objectanimator.ofpropertyvaluesholder(view, holder1, holder2, holder3)
animator.start();
6. animatorset
有的时候,我们不止需要在一个动画中改变多个属性,还会需要多个动画配合工作,比如,在内容的大小从 0 放大到 100% 大小后开始移动。这种情况使用 propertyvaluesholder 是不行的,因为这些属性如果放在同一个动画中,需要共享动画的开始时间、结束时间、interpolator 等一系列的设定,这样就不能有先后次序地执行动画了。这就需要用到 animatorset 了。
objectanimator animator1 = objectanimator.offloat(...);
animator1.setinterpolator(new linearinterpolator());
objectanimator animator2 = objectanimator.ofint(...);
animator2.setinterpolator(new decelerateinterpolator());
animatorset animatorset = new animatorset();
// 两个动画依次执行
animatorset.playsequentially(animator1, animator2);
animatorset.start();
animatorset 还可以这么用:
// 两个动画同时执行
animatorset.playtogether(animator1, animator2);
animatorset.start();
以及这么用:
// 使用 animatorset.play(animatora).with/before/after(animatorb)
// 的方式来精确配置各个 animator 之间的关系
animatorset.play(animator1).with(animator2);
animatorset.play(animator1).before(animator2);
animatorset.play(animator1).after(animator2);
animatorset.start();
7. propertyvaluesholders.ofkeyframe()
除了合并多个属性和调配多个动画,你还可以在 propertyvaluesholder 的基础上更进一步,通过设置 keyframe (关键帧),把同一个动画属性拆分成多个阶段。例如,你可以让一个进度增加到 100% 后再「反弹」回来。
// 在 0% 处开始
keyframe keyframe1 = keyframe.offloat(0, 0);
// 时间经过 50% 的时候,动画完成度 100%
keyframe keyframe2 = keyframe.offloat(0.5f, 100);
// 时间见过 100% 的时候,动画完成度倒退到 80%,即反弹 20%
keyframe keyframe3 = keyframe.offloat(1, 80);
propertyvaluesholder holder = propertyvaluesholder.ofkeyframe("progress", keyframe1, keyframe2, keyframe3);
objectanimator animator = objectanimator.ofpropertyvaluesholder(view, holder);
animator.start();
总结:「关于复杂的属性关系来做动画」,就这么三种:
使用 propertyvaluesholder 来对多个属性同时做动画;
使用 animatorset 来同时管理调配多个动画;
propertyvaluesholder 的进阶使用:使用 propertyvaluesholder.ofkeyframe() 来把一个属性拆分成多段,执行更加精细的属性动画。
fighting_初心
发布了37 篇原创文章 · 获赞 38 · 访问量 1万
私信
关注
来源:https://www.icode9.com/content-4-622551.html
总结
以上是凯发k8官方网为你收集整理的android image 位移动画_深入理解android之动画的全部内容,希望文章能够帮你解决所遇到的问题。
- 上一篇:
- 下一篇: