scale标签实现(缩放)
res下新建anim文件夹,anim文件下新建scaleanim.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 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>
使用:
binding.btn.setOnClickListener(v -> {
//所有的动画都继承自Animation类,也就是说,Animation类是所有动画(scale、alpha、translate、rotate)的基类。
Animation animation = AnimationUtils.loadAnimation(MainActivity.this, R.anim.scaleanim);
binding.rl.startAnimation(animation);
});
效果图:
scale代码实现(缩放)
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标签实现(透明度)
Animation animation = AnimationUtils.loadAnimation(MainActivity.this, R.anim.alphaanim);
binding.rl.startAnimation(animation);
anim下的alphaanim.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:动画开始时的透明度,取值范围为0到1.0,0表示全透明,1.0表示完全不透明。toAlpha:动画结束时的透明度,取值范围为0到1.0,0表示全透明,1.0表示完全不透明。
效果图:
alpha代码实现(透明度)
AlphaAnimation alphaAnimation = new AlphaAnimation(0.0f, 1.0f);
alphaAnimation.setDuration(3000);
alphaAnimation.setFillBefore(true);
binding.rl.startAnimation(alphaAnimation);
效果同标签效果相同。
rotate标签实现(旋转)
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 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 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代码实现(旋转)
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标签实现(平移)
Animation animation = AnimationUtils.loadAnimation(MainActivity.this, R.anim.translateanim);
binding.rl.startAnimation(animation);
translateanim.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代码实现(平移)
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组合标签实现组合动画
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 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代码实现组合动画
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()函数使用
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 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图片:
代码实现:
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 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 version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="#ff6c2f" />
</shape>
代码实现:
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 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 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 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
代码实现:
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();
}
});
实现效果:
代码实现
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();