帧动画
逐帧动画就是将一组图片资源一帧一帧播放,逐帧动画跟补间动画一样都可以通过XML或者Java代码实现
实现步骤:
a. drawable文件夹下创建外层标签为animation-list的标签用来存放帧动画的每一张图片;
b. 设置animation-list中的oneshot属性:代表是否只执行一次;
c. 编写< item >标签用来存放帧动画中的每一张图片;
d. 使用android:drawable属性设置每一帧显示的图片;
e. 使用android:duration属性设置每一帧显示时长;
f.java代码中使用AnimationDrawable获取帧动画对象;
g.使用start()方法播放
h.使用stop()方法停止播放
<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot="false">
<!--oneshot是否执行一次动画-->
<!--item一帧动画-->
<!--drawable一帧显示的图片-->
<!--duration一帧显示的时长-->
<item android:drawable="@drawable/ufo_home_00000"
android:duration="50"/>
<item android:drawable="@drawable/ufo_home_00001"
android:duration="50"/>
<item android:drawable="@drawable/ufo_home_00002"
android:duration="50"/>
<item android:drawable="@drawable/ufo_home_00003"
android:duration="50"/>
<item android:drawable="@drawable/ufo_home_00004"
android:duration="50"/>
<item android:drawable="@drawable/ufo_home_00005"
android:duration="50"/>
<item android:drawable="@drawable/ufo_home_00006"
android:duration="50"/>
<item android:drawable="@drawable/ufo_home_00007"
android:duration="50"/>
<item android:drawable="@drawable/ufo_home_00008"
android:duration="50"/>
<item android:drawable="@drawable/ufo_home_00009"
android:duration="50"/>
<item android:drawable="@drawable/ufo_home_00010"
android:duration="50"/>
<item android:drawable="@drawable/ufo_home_00011"
android:duration="50"/>
<item android:drawable="@drawable/ufo_home_00012"
android:duration="50"/>
<item android:drawable="@drawable/ufo_home_00013"
android:duration="50"/>
<item android:drawable="@drawable/ufo_home_00014"
android:duration="50"/>
<item android:drawable="@drawable/ufo_home_00015"
android:duration="50"/>
<item android:drawable="@drawable/ufo_home_00016"
android:duration="50"/>
<item android:drawable="@drawable/ufo_home_00017"
android:duration="50"/>
<item android:drawable="@drawable/ufo_home_00018"
android:duration="50"/>
<item android:drawable="@drawable/ufo_home_00019"
android:duration="50"/>
<item android:drawable="@drawable/ufo_home_00020"
android:duration="50"/>
</animation-list>
activity
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
AnimationDrawable ad;
ImageView img;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
}
private void init(){
findViewById(R.id.main_btn_start).setOnClickListener(this);
findViewById(R.id.main_btn_stop).setOnClickListener(this);
img = findViewById(R.id.main_img);
ad = (AnimationDrawable) img.getBackground();
}
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.main_btn_start:
ad.start();
break;
case R.id.main_btn_stop:
ad.stop();
break;
}
}
}
补间动画
一. 在android中补间动画可以分为四类:alpha(渐变)、scale(缩放)、translate(位移)、rotate(旋转)。
在这四种动画里每种动画拥有它的独有的属性的同时又拥有相同的属性,其中
alpha:渐变透明度动画效果
scale:渐变缩放动画效果
translate:渐变位置移动动画效果
rotate:渐变旋转动画效果,这四种动画能够分别带来不同的效果体验,又能混合在一起完成酷炫的动画效果。
二. 公共属性:
android:duration:设置动画播放时间属性
android:fillAfter设置动画播放完成是都保持移动后的状态
android:interpolator设置插值器
AccelerateInterpolator:
AccelerateInterpolator是加速插值器,表示动画开始的时候速率变化比较慢,然后开始加速
DecelerateInterpolator:
DecelerateInterpolator是减速插值器,表示动画开始瞬间加速到最大值,然后逐渐变慢
LinearInterpolator:
LinearInterpolator是线性插值器,也称匀速加速器,他的速率是保持恒定的
BounceInterpolator:
BounceInterpolator 是弹性插值器,模拟控件自由落地后回弹的效果
AnticipateInterpolator:
AnticipateInterpolator是初始偏移插值器,是开始动画的时候向前偏移一段距离,然后应用动画
OvershootInterpolator:
OvershootInterpolator是结束偏移插值器,表示动画结束时,沿动画方向继续运动一段距离后再结束动画
三. 位移动画(TranslateAnimation):
位移渐变,需要指定移动点的开始和结束坐标.
fromXDelta:X轴起点
toXDelta:X轴终点
fromYDelta:Y轴起点
toYDelta:Y轴终点
100%代表宽或者高的长度
四. 旋转动画(RotateAnimation):
旋转渐变,可以指定旋转的参考点
android:fromDegrees=“0”:开始角度
android:toDegrees="-180":结束角度
android:pivotX=“50%”:控件x轴中点
android:pivotY=“50%”:控件y轴中点
android:duration=“1000”:时长
android:interpolator="@android:anim/linear_interpolator":线性插值器
五. 缩放动画(ScaleAnimation):
缩放渐变,可以指定缩放的参考点
android:pivotX=“50%”:缩放X轴原点
android:pivotY=“50%”:缩放Y轴原点
android:fromXScale=“1.0”:X轴起始倍数
android:toXScale=“0.1”:X轴缩放倍数
android:fromYScale=“1.0”:y轴起始倍数
android:toYScale=“0.1”:y轴缩放倍数
android:duration=“1000”
android:interpolator="@android:anim/linear_interpolator"
六. 渐变动画(AlphaAnimation):
透明度(alpha)渐变效果
android:fromAlpha=“1.0”:透明度开始
android:toAlpha=“0.1”:透明度结束
七. AnimationSet:组合动画
AnimationSet提供了一个把多个动画组合成一个组合的机制,并可设置组中动画的时序关系,如同时播放,顺序播放等。
android:shareInterpolator=“true”:共享插值器
android:repeatMode=“reverse”:重复模式
res下创建anim
平移
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1000"
android:fromXDelta="0"
android:toXDelta="100%"
android:fromYDelta="0"
android:toYDelta="100%"
android:interpolator="@android:anim/linear_interpolator"
>
</translate>
渐变
<?xml version="1.0" encoding="utf-8"?>
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1000"
android:interpolator="@android:anim/linear_interpolator"
android:fromAlpha="1"
android:toAlpha="0.1"
>
</alpha>
旋转
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1000"
android:interpolator="@android:anim/linear_interpolator"
android:fromDegrees="0"
android:toDegrees="180"
android:fillAfter="true"
android:pivotX="50%"
android:pivotY="50%"
>
</rotate>
缩放
<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1000"
android:interpolator="@android:anim/linear_interpolator"
android:pivotX="50%"
android:pivotY="50%"
android:fromXScale="1"
android:toXScale="2"
android:fromYScale="1"
android:toYScale="1"
>
</scale>
组合动画
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:shareInterpolator="@android:anim/linear_interpolator"
android:duration="3000"
android:repeatMode="restart"
>
<translate
android:fromXDelta="0"
android:toXDelta="300"
android:fromYDelta="0"
android:toYDelta="300" />
<rotate
android:pivotY="50%"
android:pivotX="50%"
android:fromDegrees="0"
android:toDegrees="360"
/>
</set>
activity
public class TweenActivity extends AppCompatActivity implements View.OnClickListener {
private ImageView img;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_tween);
init();
}
private void init(){
img = findViewById(R.id.img);
findViewById(R.id.btn1).setOnClickListener(this);
findViewById(R.id.btn2).setOnClickListener(this);
findViewById(R.id.btn3).setOnClickListener(this);
findViewById(R.id.btn4).setOnClickListener(this);
findViewById(R.id.btn5).setOnClickListener(this);
findViewById(R.id.btn6).setOnClickListener(this);
findViewById(R.id.btn7).setOnClickListener(this);
findViewById(R.id.btn8).setOnClickListener(this);
findViewById(R.id.btn9).setOnClickListener(this);
}
@Override
public void onClick(View v) {
int id = v.getId();
switch (id){
case R.id.btn1:
//分类筛选下拉列表过度使用
TranslateAnimation t1 = (TranslateAnimation) AnimationUtils.loadAnimation(this,R.anim.t_anim);
img.startAnimation(t1);
break;
case R.id.btn2:
//下拉刷新旋转箭头动画
RotateAnimation r1 = (RotateAnimation) AnimationUtils.loadAnimation(this,R.anim.r_anim);
img.startAnimation(r1);
break;
case R.id.btn3:
AlphaAnimation a1 = (AlphaAnimation) AnimationUtils.loadAnimation(this,R.anim.a_anim);
img.startAnimation(a1);
break;
case R.id.btn4:
//滑动隐藏,停止显示过度效果
ScaleAnimation s1 = (ScaleAnimation) AnimationUtils.loadAnimation(this,R.anim.s_anim);
img.startAnimation(s1);
break;
case R.id.btn5:
//java位移动画
TranslateAnimation t2 = new TranslateAnimation(0,img.getWidth(),0,img.getHeight());
t2.setDuration(1000);
t2.setFillAfter(true);
t2.setInterpolator(new LinearInterpolator());
t2.setRepeatCount(1);//设置动画重复次数->执行2次->原有一次重复一次
t2.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
Log.e("ZXY","onAnimationStart");
}
@Override
public void onAnimationEnd(Animation animation) {
Log.e("ZXY","onAnimationEnd");
}
@Override
public void onAnimationRepeat(Animation animation) {
Log.e("ZXY","onAnimationRepeat");
}
});
img.startAnimation(t2);
break;
case R.id.btn6:
RotateAnimation r2 = new RotateAnimation(0,180,0,0);
r2.setDuration(1000);
r2.setInterpolator(new LinearInterpolator());
img.startAnimation(r2);
break;
case R.id.btn7:
AlphaAnimation a2 = new AlphaAnimation(1.0f,0.5f);
a2.setDuration(1000);
a2.setInterpolator(new LinearInterpolator());
img.startAnimation(a2);
break;
case R.id.btn8:
ScaleAnimation s2 = new ScaleAnimation(1,3,1,1);
s2.setDuration(1000);
s2.setInterpolator(new LinearInterpolator());
img.startAnimation(s2);
break;
case R.id.btn9:
AnimationSet set = (AnimationSet) AnimationUtils.loadAnimation(this,R.anim.set_anim);
img.startAnimation(set);
break;
}
}
}
属性动画
- 属性动画:
通过动态改变控件的属性,从而达到动画效果的动画 - 属性动画与补间动画区别:
属性动画改变控件属性,补间动画只是显示上对控件做了改变 - 属性动画使用过程:
- ValueAnimator:
通过不断控制值的变化,再不断 手动 赋给对象的属性,从而实现动画效果
ValueAnimator.ofInt(起始值,结束值)
ValueAnimator.addUpdateListener()添加更新监听
onAnimationUpdate:属性动画值改变回调方法
ValueAnimator.start():启动动画
- ObjectAnimator:
直接对对象的属性值进行改变操作,从而实现动画效果
ObjectAnimator.ofFloat(对象,属性,起始值,结束值)
- 插值器与估值器:
(1). 9大系统提供插值器:
AccelerateDecelerateInterpolator 缓慢启动,中间过程移动非常快,缓慢结束,适用于在屏幕上启动和结束的动画。
AccelerateInterpolator 缓慢启动,在移动过程中慢慢加快,适用于在屏幕上启动,屏幕外结束的动画。
AnticipateInterpolator 类似于AccelerateInterpolator ,但是有一个导致它以负值启动的弹力,一次一个物体向下移动的动画会先向上移动,然后再向下移动,可以理解为把一个物体放在一个弹弓上向后拉然后弹射出去。
AnticipateOvershootInterpolator 前半部分AnticipateInterpolator
相同,到达终点后会继续以这个速度继续向原来的方向运动一段距离之后再回到终点。
BounceInterpolator 类似于一个有弹性的小球掉到地上,然后又弹回来,再落下去,但是每次弹起来的高度会越来越低,直到最终静止在地面上。
CycleInterpolator 运动曲线类似于 sin 函数,起始位置相当于 sin 零点,终点相当于 sin 的顶点。比如有一个处于中心的一个小球,你的目标是把它移到下方的一个位置,这个位置暂称之为终点,那这个小球的运动轨迹会是
: 先向下移动到终点,然后再向上移动到初始位置,然后在向上移动 初始位置到终点 同样的距离,然后再返回到初始位置。这是一个周期,至于动画会执行几个周期,这取决于你在构造函数中传入的浮点参数,这个参数就是周期。
DecelerateInterpolator 以最大速度启动,结束时放慢速度,适用于在屏幕之外启动,在屏幕内结束的动画。
FastOutLinearInInterpolator 在 support 库中,这个插值器使用一个查找表来描述位移。简单的说,它的启动过程像 AccelerateInterpolator ,结束过程像LinearInterpolator 。
FastOutSlowInInterpolator 在 support 库中,这个插值器也是使用一个查找表来描述位移。它的启动过程像 AccelerateInterpolator ,结束过程像DecelerateInterpolator 。
LinearInterpolator 以一个恒定的速度变化的动画。
LinearOutSlowInInterpolator 在 support 库中,这个插值器也是使用一个查找表来描述位移。它的启动过程像 LinearInterpolator ,结束过程像DecelerateInterpolator 。
OvershootInterpolator 类似于AccelerateInterpolator,但是有一个是它不能立即停到终点位置的力,使它超过终点位置,然后在弹回终点,就想撞到了弹弓上。
(2). 估值器:
IntEvaluator:针对整型属性
FloatEvaluator:针对浮点型属性
ArgbEvaluator:针对Color属性
fraction:从起始值到结束值的分数,即为根据时间变化的浮点数,从0到1
startValue:起始值
endValue:结束值
public class ValueActivity extends AppCompatActivity implements View.OnClickListener {
private Button mbtn;
private ImageView img;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_values);
img = findViewById(R.id.vimg);
mbtn = findViewById(R.id.vbtn2);
findViewById(R.id.vbtn1).setOnClickListener(this);
mbtn.setOnClickListener(this);
findViewById(R.id.vbtn3).setOnClickListener(this);
findViewById(R.id.vbtn4).setOnClickListener(this);
findViewById(R.id.vbtn5).setOnClickListener(this);
}
@Override
public void onClick(View v) {
int id = v.getId();
switch (id){
case R.id.vbtn1:
TranslateAnimation t = new TranslateAnimation(0,300,0,0);
t.setDuration(1000);
t.setFillAfter(true);
t.setInterpolator(new LinearInterpolator());
mbtn.startAnimation(t);
break;
case R.id.vbtn2:
Log.e("ZXY","按钮被点击");
break;
case R.id.vbtn3:
valueAnim();
break;
case R.id.vbtn4:
objectAnim();
break;
case R.id.vbtn5:
bounce();
break;
}
}
//自动设置
private void objectAnim(){
ObjectAnimator oa = ObjectAnimator.ofFloat(mbtn,
"alpha",0.1f,1.0f);
oa.setDuration(1000);
oa.setInterpolator(new LinearInterpolator());
oa.start();
}
//手动设置
private void valueAnim(){
ValueAnimator va = ValueAnimator.ofInt(mbtn.getWidth(),mbtn.getWidth()*2);
va.setDuration(1000);
va.setInterpolator(new LinearInterpolator());
va.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
int width = (int) animation.getAnimatedValue();
Log.e("ZXY","onAnimationUpdate->"+width);
//手动改变控件宽度
//getLayoutParams->获取布局参数
//LayoutParams->布局参数;告诉父容器子控件想要的位置
//LayoutParams->与父容器相结合
LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) mbtn.getLayoutParams();
lp.width = width;
mbtn.setLayoutParams(lp);
}
});
va.start();
}
//BounceInterpolator
private void bounce(){
ValueAnimator va = ValueAnimator.ofInt(0,400);
va.setDuration(3000);
va.setInterpolator(new BounceInterpolator());
va.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
int margin = (int) animation.getAnimatedValue();
Log.e("ZXY","onAnimationUpdate:"+margin);
LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) img.getLayoutParams();
lp.topMargin = margin;
img.setLayoutParams(lp);
}
});
va.start();
}
}