scale标签实现(缩放)
res下新建anim文件夹,anim文件下新建scaleanim.xml文件:
xml
<?xml version="1.0" encoding="utf-8"?><scale xmlns:android="http://schemas.android.com/apk/res/android" android:duration="2000" android:fillAfter="true" android:fromXScale="1.0" android:fromYScale="1.0" android:pivotX="50%" android:pivotY="50%" android:repeatCount="infinite" android:repeatMode="reverse" android:toXScale="1.8" android:toYScale="1.8" />
duration:用于设置完成一次动画的持续时间,以毫秒为单位。
fillAfter:如果设置为true,控件动画结束时,将保持动画结束时的状态。不设置默认为false。
fillBefore:如果设置为true,则控件动画结束时,将还原到初始化状态。
fillEnabled:与android:fillBefore效果相同,都是在控件动画结束时,将还原到初始化状态。
fromXScale:动画起始时,控件在X轴方向上相对自身的缩放比例,浮点值。比如 1.0 代表自身无变化,0.5代表缩小1倍,2.0代表放大1倍。
fromYScale:动画起始时,控件在Y轴方向上相对自身的缩放比例,浮点值。
interpolator:用于设定插值器,其实就是指定的动画效果,如弹跳效果等。
pivotX:缩放起始点X轴坐标,可以是数值、百分数、百分数三种样式,如50、50%、50%p。如果是数值,表示在当前视图的左上角, 即原点处加上50px,作为缩放起始点X轴坐标;如果是50%则表示在当前控件的左上角加上自己宽度的50%作为缩放起始点X轴坐标; 如果是50%p,则表示在当前控件的左上角加上父控件宽度的50%作为缩放起始点X轴坐标。
pivotY:缩放起始点Y轴坐标,取值及含义与android:pivotX相同。
repeatCount:用于指定动画的重复次数,当取值 infinite时,表示无限循环。
repeatMode:用于设定重复的类型,有reverse、restart,其中reverse表示倒序回放;restart表示重放, 并且必须与repeatCount一起使用才能看到效果。
toXScale:动画结束时,控件在X轴方向上相对自身的缩放比例,浮点值。
toYScale:动画结束时,控件在Y轴方向上相对自身的缩放比例,浮点值。
activity_main.xml布局代码:
xml
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <Button android:id="@+id/btn" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginStart="10dp" android:layout_marginEnd="10dp" android:text="开始动画" /> <RelativeLayout android:id="@+id/rl" android:layout_width="100dp" android:layout_height="100dp" android:layout_gravity="center_horizontal" android:layout_marginTop="50dp" android:background="@color/red"> <TextView android:id="@+id/tv" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:text="福" android:textColor="@color/black" android:textSize="50sp" android:textStyle="bold" /> </RelativeLayout></LinearLayout>
使用:
css
binding.btn.setOnClickListener(v -> { //所有的动画都继承自Animation类,也就是说,Animation类是所有动画(scale、alpha、translate、rotate)的基类。 Animation animation = AnimationUtils.loadAnimation(MainActivity.this, R.anim.scaleanim); binding.rl.startAnimation(animation);});
效果图:

scale代码实现(缩放)
ini
ScaleAnimation scaleAnimation = new ScaleAnimation(1.0f, 1.8f, 1.0f, 1.8f,
Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
scaleAnimation.setDuration(2000);
scaleAnimation.setRepeatCount(Animation.INFINITE);
scaleAnimation.setRepeatMode(Animation.REVERSE);
binding.rl.startAnimation(scaleAnimation);
属性参数和标签属性相对应,效果和标签实现效果相同。
alpha标签实现(透明度)
ini
Animation animation = AnimationUtils.loadAnimation(MainActivity.this, R.anim.alphaanim);
binding.rl.startAnimation(animation);
anim下的alphaanim.xml文件
xml
<?xml version="1.0" encoding="utf-8"?><alpha xmlns:android="http://schemas.android.com/apk/res/android" android:duration="3000" android:fillBefore="true" android:fromAlpha="0" android:toAlpha="1.0" />
fromAlpha:动画开始时的透明度,取值范围为01.0,0表示全透明,1.0表示完全不透明。toAlpha:动画结束时的透明度,取值范围为01.0,0表示全透明,1.0表示完全不透明。
效果图:

alpha代码实现(透明度)
ini
AlphaAnimation alphaAnimation = new AlphaAnimation(0.0f, 1.0f);
alphaAnimation.setDuration(3000);
alphaAnimation.setFillBefore(true);
binding.rl.startAnimation(alphaAnimation);
效果同标签效果相同。
rotate标签实现(旋转)
ini
Animation animation = AnimationUtils.loadAnimation(MainActivity.this, R.anim.rotateanim);
binding.rl.startAnimation(animation);
Animation animation2 = AnimationUtils.loadAnimation(MainActivity.this, R.anim.rotateanim2);
binding.tv.startAnimation(animation2);
rotateanim.xml文件代码:
xml
<?xml version="1.0" encoding="utf-8"?><rotate xmlns:android="http://schemas.android.com/apk/res/android" android:duration="2000" android:fillAfter="true" android:fromDegrees="0" android:pivotX="50%" android:pivotY="50%" android:toDegrees="45" />
fromDegrees:动画开始旋转时的角度位置,正值代表顺时针方向的度数, 负值代表逆时针方向的度数。
toDegrees:动画结束时旋转到的角度位,正值代表顺时针方向的度数,负值代表逆时针方向的度数。
rotateanim2.xml代码:
xml
<?xml version="1.0" encoding="utf-8"?><rotate xmlns:android="http://schemas.android.com/apk/res/android" android:duration="2000" android:fillAfter="true" android:fromDegrees="0" android:pivotX="50%" android:pivotY="50%" android:toDegrees="-405" />

rotate代码实现(旋转)
ini
RotateAnimation rotateAnimation = new RotateAnimation(0.0f, 45.0f,
Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
rotateAnimation.setDuration(2000);
rotateAnimation.setFillAfter(true);
binding.rl.startAnimation(rotateAnimation);
RotateAnimation rotateAnimation2 = new RotateAnimation(0.0f, -405.0f,
Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
rotateAnimation2.setDuration(2000);
rotateAnimation2.setFillAfter(true);
binding.tv.startAnimation(rotateAnimation2);
效果同上。
translate标签实现(平移)
ini
Animation animation = AnimationUtils.loadAnimation(MainActivity.this, R.anim.translateanim);
binding.rl.startAnimation(animation);
translateanim.xml
xml
<?xml version="1.0" encoding="utf-8"?><translate xmlns:android="http://schemas.android.com/apk/res/android" android:duration="2000" android:fillAfter="true" android:fromXDelta="0" android:fromYDelta="0" android:interpolator="@android:anim/cycle_interpolator" android:toXDelta="90%" android:toYDelta="90%" />
fromXDelta:起始点X轴坐标,可以是数值、百分数、百分数p,三种种样式。
fromYDelta:起始点Y轴坐标,可以是数值、百分数、百分数p,三种种样式。
android:interpolator="@android:anim/accelerate_interpolator" 加速插值器。
android:interpolator="@android:anim/decelerate_interpolator" 减速插值器。
android:interpolator="@android:anim/linear_interpolator" 匀速插值器。
android:interpolator="@android:anim/bounce_interpolator" 弹跳插值器。
android:interpolator="@android:anim/anticipate_interpolator" 初始偏离插值器。
android:interpolator="@android:anim/overshoot_interpolator" 结束偏移插值器,表示在动画结束时, 沿动画方向继续运动一段距离后再结束动画。
android:interpolator="@android:anim/anticipate_overshoot_interpolator" 是AnticipateInterpolator 与OvershootInterpolator的合体,即在动画开始时向前偏离,在动画结束时向后偏移一段距离。
android:interpolator="@android:anim/cycle_interpolator" 循环插值器,表示动画循环播放特定的次数,速率沿正弦曲线改变。
tension:初始偏离插值器偏移量、结束偏移插值器偏移量,默认值为2。
toXDelta:终点X轴坐标。
toYDelta:终点Y轴坐标。

translate代码实现(平移)
scss
TranslateAnimation translateAnimation = new TranslateAnimation(Animation.ABSOLUTE, 0,
Animation.ABSOLUTE, 90, Animation.ABSOLUTE, 0,
Animation.ABSOLUTE, 90);
translateAnimation.setDuration(2000);
translateAnimation.setFillAfter(true);
//加速插值器
//translateAnimation.setInterpolator(new AccelerateInterpolator());
//减速插值器
//translateAnimation.setInterpolator(new DecelerateInterpolator());
//线性(匀速)插值器
//translateAnimation.setInterpolator(new LinearInterpolator());
//弹跳插值器
//translateAnimation.setInterpolator(new BounceInterpolator());
//初始偏离插值器,参数float tension对应的XML属性为android:tension,表示张力值,默认值为2,值越大,
//初始的偏移量越大,而且速度越快;当直接使用 new AnticipateInterpolator()构造时,使用的是tension的默认值
//translateAnimation.setInterpolator(new AnticipateInterpolator(4));
//结束偏移插值器,表示在动画结束时,沿动画方向继续运动一段距离后再结束动画。
//translateAnimation.setInterpolator(new OvershootInterpolator(4));
//AnticipateOvershootInterpolator是AnticipateInterpolator与OvershootInterpolator的合体,
//即在动画开始时向前偏离,在动画结束时向后偏移一段距离。
//translateAnimation.setInterpolator(new AnticipateOvershootInterpolator(3,4));
//循环插值器,表示动画循环播放特定的次数,速率沿正弦曲线改变。
translateAnimation.setInterpolator(new CycleInterpolator(1));
binding.rl.startAnimation(translateAnimation);
set组合标签实现组合动画
ini
Animation animation = AnimationUtils.loadAnimation(MainActivity.this, R.anim.setanim);
binding.rl.startAnimation(animation);
Animation animation2 = AnimationUtils.loadAnimation(MainActivity.this, R.anim.rotateanim2);
binding.tv.startAnimation(animation2);
setanim.xml
xml
<?xml version="1.0" encoding="utf-8"?><!--注意:在set标签中设置repeateCount属性是无效的,必须对每个动画单独设置才有作用--><set xmlns:android="http://schemas.android.com/apk/res/android" android:duration="2000" android:fillAfter="true"> <!--scale标签(缩放)--> <scale android:fromXScale="1.0" android:fromYScale="1.0" android:pivotX="50%" android:pivotY="50%" android:repeatCount="infinite" android:repeatMode="reverse" android:toXScale="1.5" android:toYScale="1.5" /> <!--alpha标签(透明度)--> <alpha android:fillBefore="true" android:fromAlpha="0" android:toAlpha="1.0" /> <!--rotate标签(旋转)--> <rotate android:fillAfter="true" android:fromDegrees="0" android:pivotX="50%" android:pivotY="50%" android:toDegrees="45" /> <!--translate标签(平移)--> <translate android:fillAfter="true" android:fromXDelta="-400" android:toXDelta="0" /></set>

set代码实现组合动画
ini
ScaleAnimation scaleAnimation = new ScaleAnimation(1.0f, 1.5f, 1.0f, 1.5f,
Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
scaleAnimation.setRepeatCount(Animation.INFINITE);
scaleAnimation.setRepeatMode(Animation.REVERSE);
AlphaAnimation alphaAnimation = new AlphaAnimation(0.0f, 1.0f);
RotateAnimation rotateAnimation = new RotateAnimation(0.0f, 45.0f,
Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
TranslateAnimation translateAnimation = new TranslateAnimation(Animation.ABSOLUTE, -400,
Animation.ABSOLUTE, 0, Animation.ABSOLUTE, 0,
Animation.ABSOLUTE, 0);
AnimationSet animationSet = new AnimationSet(true);
animationSet.addAnimation(scaleAnimation);
animationSet.addAnimation(alphaAnimation);
animationSet.addAnimation(rotateAnimation);
animationSet.addAnimation(translateAnimation);
animationSet.setDuration(2000);
animationSet.setFillAfter(true);
binding.rl.startAnimation(animationSet);
Animation animation2 = AnimationUtils.loadAnimation(MainActivity.this, R.anim.rotateanim2);
binding.tv.startAnimation(animation2);
setAnimationlistener()函数使用
typescript
RotateAnimation rotateAnimation3 = new RotateAnimation(0.0f, 0.0f,
Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
binding.tv.startAnimation(rotateAnimation3);
TranslateAnimation translateAnimation = new TranslateAnimation(Animation.ABSOLUTE, -400,
Animation.ABSOLUTE, 0, Animation.ABSOLUTE, 0,
Animation.ABSOLUTE, 0);
translateAnimation.setDuration(2000);
translateAnimation.setFillAfter(true);
RotateAnimation rotateAnimation = new RotateAnimation(0.0f, 45.0f,
Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
rotateAnimation.setDuration(2000);
rotateAnimation.setFillAfter(true);
RotateAnimation rotateAnimation2 = new RotateAnimation(0.0f, -405.0f,
Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
rotateAnimation2.setDuration(2000);
rotateAnimation2.setFillAfter(true);
translateAnimation.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
//当动画开始时,会调用此函数
}
@Override
public void onAnimationEnd(Animation animation) {
//当动画结束时,会调用此函数通
binding.rl.startAnimation(rotateAnimation);
}
@Override
public void onAnimationRepeat(Animation animation) {
//当动画重复时,会调用此函数
}
});
rotateAnimation.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
binding.tv.startAnimation(rotateAnimation2);
}
@Override
public void onAnimationRepeat(Animation animation) {
}
});
binding.rl.startAnimation(translateAnimation);

实现加载框动画
实现方案:使用旋转效果加上匀速插值器或加减速插值器实现。
布局:
xml
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <Button android:id="@+id/btn" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginStart="10dp" android:layout_marginEnd="10dp" android:text="开始动画" /> <ImageView android:id="@+id/loading" android:layout_width="60dp" android:layout_height="60dp" android:layout_gravity="center_horizontal" android:layout_marginTop="40dp" android:src="@drawable/loading" /></LinearLayout>
drawable-xxhdpi的loading.png图片:

代码实现:
ini
RotateAnimation rotateAnim = new RotateAnimation(0, 360,
Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
rotateAnim.setRepeatCount(Animation.INFINITE);
rotateAnim.setDuration(2000);
rotateAnim.setInterpolator(new LinearInterpolator());
binding.loading.startAnimation(rotateAnim);
实现效果:

实现扫描动画
实现方案:叠加错时放大加透明度实现。
布局
xml
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <Button android:id="@+id/btn" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginStart="10dp" android:layout_marginEnd="10dp" android:text="开始动画" /> <FrameLayout android:layout_width="match_parent" android:layout_height="match_parent"> <ImageView android:id="@+id/circle1" android:layout_width="140dp" android:layout_height="140dp" android:layout_gravity="center" android:src="@drawable/scan_crile" /> <ImageView android:id="@+id/circle2" android:layout_width="140dp" android:layout_height="140dp" android:layout_gravity="center" android:src="@drawable/scan_crile" /> <ImageView android:id="@+id/circle3" android:layout_width="140dp" android:layout_height="140dp" android:layout_gravity="center" android:src="@drawable/scan_crile" /> <ImageView android:id="@+id/circle4" android:layout_width="140dp" android:layout_height="140dp" android:layout_gravity="center" android:src="@drawable/scan_crile" /> </FrameLayout></LinearLayout>
drawable下引用的scan_crile.xml资源文件:
xml
<?xml version="1.0" encoding="utf-8"?><shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval"> <solid android:color="#ff6c2f" /></shape>
代码实现:
ini
Animation animation1 = AnimationUtils.loadAnimation(this, R.anim.scale_alpha_anim);
Animation animation2 = AnimationUtils.loadAnimation(this, R.anim.scale_alpha_anim);
Animation animation3 = AnimationUtils.loadAnimation(this, R.anim.scale_alpha_anim);
Animation animation4 = AnimationUtils.loadAnimation(this, R.anim.scale_alpha_anim);
binding.circle1.startAnimation(animation1);
animation2.setStartOffset(600);
binding.circle2.startAnimation(animation2);
animation3.setStartOffset(1200);
binding.circle3.startAnimation(animation3);
animation1.setStartOffset(1800);
binding.circle4.startAnimation(animation4);
anim下的组合动画scale_alpha_anim.xml引用文件:
xml
<?xml version="1.0" encoding="utf-8"?><set xmlns:android="http://schemas.android.com/apk/res/android" android:duration="3000"> <scale android:fromXScale="1.0" android:fromYScale="1.0" android:pivotX="50%" android:pivotY="50%" android:repeatCount="infinite" android:toXScale="3" android:toYScale="3" /> <alpha android:fromAlpha="0.4" android:repeatCount="infinite" android:toAlpha="0" /></set>
实现效果:

实现逐帧动画
xml实现
布局:
xml
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <Button android:id="@+id/btn" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginStart="10dp" android:layout_marginEnd="10dp" android:text="开始动画" /> <Button android:id="@+id/btnStop" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginStart="10dp" android:layout_marginEnd="10dp" android:text="停止动画" /> <ImageView android:id="@+id/frame_image" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:layout_marginTop="20dp" android:background="@drawable/playing_ani" /></LinearLayout>
drawable文件下playing_ani.xml
xml
<?xml version="1.0" encoding="utf-8"?><!--oneshot:设置是否只播放一次--><animation-list xmlns:android="http://schemas.android.com/apk/res/android" android:oneshot="false"> <!--drawable:设置图片--> <!--duration:播放时间设置--> <item android:drawable="@drawable/icon_gif_playing1" android:duration="250" /> <item android:drawable="@drawable/icon_gif_playing2" android:duration="250" /> <item android:drawable="@drawable/icon_gif_playing3" android:duration="250" /> <item android:drawable="@drawable/icon_gif_playing4" android:duration="250" /></animation-list>
drawable-xxhdpi文件夹下的图片资源:
icon_gif_playing1.png

icon_gif_playing2.png

icon_gif_playing3.png

icon_gif_playing4.png

代码实现:
ini
private AnimationDrawable animationDrawable;
...
binding.btn.setOnClickListener(v -> {
animationDrawable = (AnimationDrawable) binding.frameImage.getBackground();
//开始播放逐帧动画
animationDrawable.start();
});
binding.btnStop.setOnClickListener(v -> {
if (animationDrawable != null && animationDrawable.isRunning()) {
//停止播放逐帧动画
animationDrawable.stop();
}
});
实现效果:

代码实现
scss
animationDrawable = new AnimationDrawable();
//按顺序遍历图片名称
for (int i = 1; i <= 4; i++) {
//通过文件名获取资源id
//第一个参数name:资源名称
//第二个参数defType:资源类型
//第三个参数defPackage:应用包名
int id = getResources().getIdentifier("icon_gif_playing" + i, "drawable", getPackageName());
Drawable drawable = getResources().getDrawable(id);
animationDrawable.addFrame(drawable, 250);
}
//设置非播放一次
animationDrawable.setOneShot(false);
binding.frameImage.setBackground(animationDrawable);
animationDrawable.start();