Android开发之视图动画

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();
相关推荐
小雨cc5566ru4 小时前
uniapp+Android面向网络学习的时间管理工具软件 微信小程序
android·微信小程序·uni-app
bianshaopeng6 小时前
android 原生加载pdf
android·pdf
hhzz6 小时前
Linux Shell编程快速入门以及案例(Linux一键批量启动、停止、重启Jar包Shell脚本)
android·linux·jar
火红的小辣椒7 小时前
XSS基础
android·web安全
勿问东西9 小时前
【Android】设备操作
android
五味香9 小时前
C++学习,信号处理
android·c语言·开发语言·c++·学习·算法·信号处理
图王大胜11 小时前
Android Framework AMS(01)AMS启动及相关初始化1-4
android·framework·ams·systemserver
工程师老罗13 小时前
Android Button “No speakable text present” 问题解决
android
小雨cc5566ru14 小时前
hbuilderx+uniapp+Android健身房管理系统 微信小程序z488g
android·微信小程序·uni-app
小雨cc5566ru15 小时前
微信小程序hbuilderx+uniapp+Android 新农村综合风貌旅游展示平台
android·微信小程序·uni-app