您当前的位置: 首页 > 学无止境 > 心得笔记 网站首页心得笔记
87_android下的动画处理
发布时间:2021-03-27 17:59:00编辑:雪饮阅读()
补间动画
在安卓中有补间动画和逐帧动画,那么这里就先来介绍下补间动画
这里主要以对于一个图片的操作形成动画,所以事先准备好一个图片

接下来我们要实现主布局,这里主要实现11种补间动画,所以至少需要11个按钮,然后当然还有就是上面的这个图片了,所以activity_main.xml如:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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"
tools:context=".MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="300dip"
android:orientation="vertical">
<LinearLayout
android:orientation="horizontal"
style="@style/LinearLayout_row"
>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="alpha"
android:text="播放透明度变化的动画" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="rotate"
android:text="播放旋转变化的动画" />
</LinearLayout>
<LinearLayout
android:orientation="horizontal"
style="@style/LinearLayout_row"
>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="scale"
android:text="缩放(原倍)" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="scale2"
android:text="缩放(2倍)" />
</LinearLayout>
<LinearLayout
android:orientation="horizontal"
style="@style/LinearLayout_row"
>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="translate"
android:text="平移" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="alpha2"
android:text="播放透明度变化的动画(依赖xml)" />
</LinearLayout>
<LinearLayout
android:orientation="horizontal"
style="@style/LinearLayout_row"
>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="rotate2"
android:text="播放旋转变化的动画(依赖xml)" />
</LinearLayout>
<LinearLayout
android:orientation="horizontal"
style="@style/LinearLayout_row"
>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="translate2"
android:text="平移(依赖xml)" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="set"
android:text="动画集合" />
</LinearLayout>
<LinearLayout
android:orientation="horizontal"
style="@style/LinearLayout_row"
>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="set"
android:text="动画集合(依赖xml)" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="scale3"
android:text="缩放(依赖xml)" />
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<!--
android:scaleType="fitXY"
把原图按照指定的大小在View中显示,拉伸显示图片,不保持原比例,填满ImageView.
-->
<ImageView
android:scaleType="fitXY"
android:id="@+id/iv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_launcher" />
</LinearLayout>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout 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"
tools:context=".MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="300dip"
android:orientation="vertical">
<LinearLayout
android:orientation="horizontal"
style="@style/LinearLayout_row"
>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="alpha"
android:text="播放透明度变化的动画" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="rotate"
android:text="播放旋转变化的动画" />
</LinearLayout>
<LinearLayout
android:orientation="horizontal"
style="@style/LinearLayout_row"
>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="scale"
android:text="缩放(原倍)" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="scale2"
android:text="缩放(2倍)" />
</LinearLayout>
<LinearLayout
android:orientation="horizontal"
style="@style/LinearLayout_row"
>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="translate"
android:text="平移" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="alpha2"
android:text="播放透明度变化的动画(依赖xml)" />
</LinearLayout>
<LinearLayout
android:orientation="horizontal"
style="@style/LinearLayout_row"
>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="rotate2"
android:text="播放旋转变化的动画(依赖xml)" />
</LinearLayout>
<LinearLayout
android:orientation="horizontal"
style="@style/LinearLayout_row"
>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="translate2"
android:text="平移(依赖xml)" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="set"
android:text="动画集合" />
</LinearLayout>
<LinearLayout
android:orientation="horizontal"
style="@style/LinearLayout_row"
>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="set"
android:text="动画集合(依赖xml)" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="scale3"
android:text="缩放(依赖xml)" />
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<!--
android:scaleType="fitXY"
把原图按照指定的大小在View中显示,拉伸显示图片,不保持原比例,填满ImageView.
-->
<ImageView
android:scaleType="fitXY"
android:id="@+id/iv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_launcher" />
</LinearLayout>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
那么为了节省布局代码中过多的行(线性布局)所使用相同的样式,所以上面布局中行的样式都是引入自定义的外部样式,那么这个自定义的外部样式如values/strings.xml:
<resources>
<string name="app_name">anim</string>
<style name="LinearLayout_row">
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">50dip</item>
</style>
</resources>
然后呢,因为虽然说是补间动画,但是其实现也分两种,一种是纯代码实现,一种是依赖单独的xml实现。但是逻辑层整体这里我都是用同一个.java(从布局中的这些按钮也能看得出来)则MainActivity.java如:
package com.example.anim;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.view.animation.AnimationSet;
import android.view.animation.AnimationUtils;
import android.view.animation.RotateAnimation;
import android.view.animation.ScaleAnimation;
import android.view.animation.TranslateAnimation;
import android.widget.ImageView;
public class MainActivity extends AppCompatActivity {
private ImageView iv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
iv = (ImageView) this.findViewById(R.id.iv);
}
//透明度变化范围0-1,动画持续时间2秒
public void alpha(View view){
AlphaAnimation aa = new AlphaAnimation(0.0f, 1.0f);
aa.setDuration(2000);
iv.startAnimation(aa);
}
//旋转范围从0度-90度
public void rotate(View view){
RotateAnimation ra = new RotateAnimation(0, 90);
ra.setDuration(2000);
iv.startAnimation(ra);
}
//缩放的实现是以指定动画开始时候的x坐标与结束时候的x坐标,以及动画开始时候的y坐标与动画结束时的y坐标来实现
public void scale(View view){
//这里xy开始都是0,结束都是1,则相当于原倍缩放
ScaleAnimation sa = new ScaleAnimation(0.0f, 1.0f, 0.0f, 1.0f);
sa.setDuration(2000);
iv.startAnimation(sa);
}
public void scale2(View view){
ScaleAnimation sa = new ScaleAnimation(0.0f, 2.0f, 0.0f, 2.0f);
sa.setDuration(2000);
iv.startAnimation(sa);
}
//平移动画的实现是以动画开始是xy坐标到动画结束时候的xy坐标进行平移操作的
public void translate(View view){
TranslateAnimation ta = new TranslateAnimation(0, 200, 0, 200);
ta.setDuration(2000);
iv.startAnimation(ta);
}
public void alpha2(View view){
Animation aa = AnimationUtils.loadAnimation(this, R.anim.alpha);
iv.startAnimation(aa);
}
public void rotate2(View view){
Animation ra = AnimationUtils.loadAnimation(this, R.anim.rotate);
iv.startAnimation(ra);
}
public void scale3(View view){
Animation sa = AnimationUtils.loadAnimation(this, R.anim.scale);
iv.startAnimation(sa);
}
public void translate2(View view){
Animation ta = AnimationUtils.loadAnimation(this, R.anim.translate);
iv.startAnimation(ta);
}
/**
* 动画的组合 可理解为动画合集
* 各种特效大杂烩,当然有些特效是要注意逻辑上下文的
* 其实这里都是一些伪代码,组合一起的效果,所以动画的执行结果也就没有什么分析意义了
*/
public void set(View view){
//透明 0-1
AlphaAnimation aa = new AlphaAnimation(0.0f, 1.0f);
aa.setDuration(2000);
//旋转 0-90
RotateAnimation ra = new RotateAnimation(0, 90);
ra.setDuration(2000);
//平移 0,0-200,200
TranslateAnimation ta = new TranslateAnimation(0, 200, 0, 200);
ta.setDuration(2000);
//动画集合
AnimationSet set = new AnimationSet(false);
set.addAnimation(ta);
set.addAnimation(ra);
set.addAnimation(aa);
iv.startAnimation(set);
}
/**
* 动画的组合
*/
public void set2(View view){
Animation aa = AnimationUtils.loadAnimation(this, R.anim.set);
iv.startAnimation(aa);
}
}
那么对于逻辑层所依赖的这些独立的xml方式的动画生成方案时候,这些独立的xml我建立在res/anim中的。
则它们各自如:
res/anim/alpha.xml:
<?xml version="1.0" encoding="utf-8"?>
<!--透明度变化的动画依赖xml的一个版本所用的xml-->
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
android:fromAlpha="0.0"
android:toAlpha="1.0"
android:duration="2000"
android:repeatCount="0"
android:repeatMode="restart"
>
</alpha>
<!--
android:repeatMode="restart" 代表动画执行一次结束之后从头开始,如果是reverse那就是反向执行;
android:repeatCount指定动画重复次数
-->
res/anim/rotate.xml:
<?xml version="1.0" encoding="utf-8"?>
<!--
播放旋转变化的动画的对xml依赖的版本的xml
-->
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:fromDegrees="0"
android:toDegrees="90"
android:pivotX="20%"
android:pivotY="20%"
android:duration="2000"
>
</rotate>
<!--
fromDegrees是开始的角度,toDegrees是结束的角度
android:pivotX 表示缩放/旋转起点 X 轴坐标,可以是整数值、百分数(或者小数)、百分数p 三种样式,比如 50、50% / 0.5、50%p。
需要明确的是,这里以进行动画控件的左上角为原点坐标,当属性值为数值,如 50 时,表示原点坐标加上 50px,作为起始点;
如果是百分数,比如 50%,表示原点坐标加上自己宽度的 50%(即控件水平中心)作为起始点 ;
如果是 50%p(字母 p 是 parent 的意思),取值的基数是父控件,因此 50%p 就是表示在原点坐标加上父控件宽度的 50% 作为起始点 x 轴坐标。
android:pivotY 为缩放/旋转起点 Y 轴坐标,其意义与android:pivotX类似。
android:pivotX 与android:pivotY 表示起点,那么图形原本没有任何动画效果的坐标就是终点咯
-->
res/anim/scale.xml:
<?xml version="1.0" encoding="utf-8"?>
<!--缩放的动画依赖xml的一个版本所用的xml-->
<scale xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="2000"
android:fromXScale="0.0"
android:toXScale="2.0"
android:fromYScale="0.0"
android:toYScale="2.0"
android:repeatMode="reverse"
android:repeatCount="1"
>
</scale>
<!--
android:fromXScale初始X轴缩放比例,1.0表示无变化。那么toXScale、fromYScale、toYScale的意思就不言而喻了
android:repeatMode="restart" 代表动画执行一次结束之后从头开始,如果是reverse那就是反向执行;
android:repeatCount指定动画重复次数
-->
res/anim/translate.xml:
<?xml version="1.0" encoding="utf-8"?>
<!--平移的动画依赖xml的一个版本所用的xml-->
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="2000"
android:fromXDelta="0"
android:toXDelta="100"
android:fromYDelta="0"
android:toYDelta="100"
android:startOffset="1000"
>
</translate>
<!--
fromXDelta 起始点X轴坐标,经过我的测试,这里表示的是你要滑出来的界面View的右上角的位置,可以是数值、百分数、百分数p。
如果是数值,比如100,表示在View右上角向右边加上100px,如果是-100,表示在View的右上角加上-100px,也就是向左移。如果是百分数,就是按View自身的比例来进行平移的。
如果是百分数p,是按照主界面的比例来进行平移的,这里的主界面指的是被View压住的界面。
其实这个属性,根据当前动画的目的效果,并结合属性列表中toXDelta、fromYDelta、toYDelta也能猜出来是什么意思了。
android:startOffset="1000" 这个根据字面意思结合部分网上文档,个人理解为等待开始动画运行的时间,单位为毫秒,那么这里1000毫秒,即为1秒后运行动画
-->
res/anim/set.xml:
<?xml version="1.0" encoding="utf-8"?>
<!--动画合集依赖xml的一个版本所用的xml-->
<set xmlns:android="http://schemas.android.com/apk/res/android" >
<alpha
android:duration="2000"
android:fromAlpha="0.0"
android:repeatCount="0"
android:repeatMode="restart"
android:toAlpha="1.0" />
<!--
透明度从0-1
重复0次
持续时间2秒
android:repeatMode="restart" 代表动画执行一次结束之后从头开始,如果是reverse那就是反向执行;
-->
<rotate
android:duration="2000"
android:fromDegrees="0"
android:pivotX="50%p"
android:pivotY="50%p"
android:toDegrees="90" />
<!--
android:fromDegrees 旋转开始角度
android:toDegrees 旋转结束角度
android:pivotX 表示缩放/旋转起点 X 轴坐标,可以是整数值、百分数(或者小数)、百分数p 三种样式,比如 50、50% / 0.5、50%p。
需要明确的是,这里以进行动画控件的左上角为原点坐标,当属性值为数值,如 50 时,表示原点坐标加上 50px,作为起始点;
如果是百分数,比如 50%,表示原点坐标加上自己宽度的 50%(即控件水平中心)作为起始点 ;
如果是 50%p(字母 p 是 parent 的意思),取值的基数是父控件,因此 50%p 就是表示在原点坐标加上父控件宽度的 50% 作为起始点 x 轴坐标。
android:pivotY 为缩放/旋转起点 Y 轴坐标,其意义与android:pivotX类似。
-->
<scale
android:duration="2000"
android:fromXScale="0.0"
android:fromYScale="0.0"
android:repeatCount="1"
android:repeatMode="reverse"
android:toXScale="2.0"
android:toYScale="2.0" />
<!--
android:fromXScale 初始X轴缩放比例,1.0表示无变化
android:fromYScale 初始Y轴缩放比例
android:toXScale 结束X轴缩放比例
android:toYScale 结束Y轴缩放比例
-->
</set>
最后部署到设备中就可以各种补间动画操作了,由于是动画这里也懒得贴图gif了,太麻烦,反正自己这里测试是ok的。
逐帧动画
对于逐帧动画的实现这里准备单独再开一个项目。
首先呢逐帧顾名思义,一帧帧的读取,那么我们这里准备好一些图片,就假定一帧对应一个图片吧。
然后将这些图片都复制到项目中,然后呢在安卓中要想将这些图片组装成逐帧动画可用的资源,则需要一个xml来定义,则定义及图片复制到项目中之后如
这里的list.xml就是提供给逐帧动画进行解析的资源。
那么接下来逐帧动画的播放需要一个容器来承载,就好比之前介绍过的视频的播放一样,而逐帧动画播放的承载容器也和上面的补间动画一样可以直接一个ImageView,只是呢这个ImageView我不给它默认写上图片路径而已,那么讲到这里了,大家应该明白了逐帧动画是怎么作用于imagview了,我个人理解应该就是高速的在ImageView中不断的渲染每个图片,即高速的替换渲染ImageView以各种不同的图片资源。那么废话不多说这里主布局如activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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"
tools:context=".MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/iv" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
那么接下来的实现逻辑就是为这个imageview设置一个背景资源为一个图片列表资源,即上面的list.xml,然后帧动画得到这个绘制背景后就可以开始绘制帧动画了。但是现在需要一个触发事件,这里就不打算用按钮了,这里我打算用触摸屏幕的方式实现。那么具体逻辑如MainActivity.java:
package com.example.frame;
import androidx.appcompat.app.AppCompatActivity;
import android.graphics.drawable.AnimationDrawable;
import android.os.Bundle;
import android.view.MotionEvent;
import android.widget.ImageView;
public class MainActivity extends AppCompatActivity {
private ImageView iv ;
private AnimationDrawable drawable;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
iv = (ImageView) this.findViewById(R.id.iv);
iv.setBackgroundResource(R.drawable.list);
drawable = (AnimationDrawable) iv.getBackground();
}
//触发触摸事件
@Override
public boolean onTouchEvent(MotionEvent event) {
//MotionEvent.ACTION_DOWN 手指 初次接触到屏幕 时触发。
if(event.getAction()==MotionEvent.ACTION_DOWN){
//开始播放帧动画
drawable.start();
}
return super.onTouchEvent(event);
}
}
那么由于是动画,这里不贴动图了,就一个静图(太懒了),以呈现部署到设备后操作触摸屏幕后的效果如:
关键字词:android,动画,补间,逐帧
上一篇:86_9patch图片的使用
下一篇:88_采用传感器获取手机的方向