写点什么

Android 动画之帧动画

作者:向阳逐梦
  • 2023-04-20
    四川
  • 本文字数:3299 字

    阅读完需:约 11 分钟

Android动画之帧动画

Android 中的动画,毕竟在 APP 中添加上一些动画,会让我们的应用变得很炫,比如最简单的关开 Activity,当然自定义控件动画肯定必不可少啦。Android 中的动画分为三大类,逐帧动画(Frame)以及补间动画(Tween),还有 Android 3.0 以后引入的属性动画(Property),而本节给大家带来的是第一种动画——逐帧动画的一个基本使用。

1.帧动画概念以及用法

帧动画非常容易理解,其实就是简单的由 N 张静态图片收集起来,然后我们通过控制依次显示这些图片,因为人眼"视觉残留"的原因,会让我们造成动画的"错觉",跟放电影的原理一样!

当然我们也可以在 Java 代码中创建逐帧动画,创建 AnimationDrawable 对象,然后调用 addFrame(Drawable frame,int duration)向动画中添加帧,接着调用 start()和 stop()而已。

下面我们来写两个例子体会下帧动画的效果以及熟悉下用法:

2.使用示例

示例一:最简单的例子:

运行效果图

代码实现

首先编写我们的动画文件,非常简单,先在 res 下创建一个 anim 目录,接着开始撸我们的动画文件:miao_gif.xml:这里的 android:oneshot 是设置动画是否只是播放一次,true 只播放一次,false 循环播放!

<?xml version="1.0" encoding="utf-8"?><animation-list xmlns:android="http://schemas.android.com/apk/res/android"    android:oneshot="false">    <item        android:drawable="@mipmap/img_miao1"        android:duration="80" />    <item        android:drawable="@mipmap/img_miao2"        android:duration="80" />    <item        android:drawable="@mipmap/img_miao3"        android:duration="80" />    <!--限于篇幅,省略其他item,自己补上-->    ...</animation-list>
复制代码

动画文件有了,接着到我们的布局文件:activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical">
<Button android:id="@+id/btn_start" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="开始" />
<Button android:id="@+id/btn_stop" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="停止" />
<ImageView android:id="@+id/img_show" android:layout_width="120dp" android:layout_height="120dp" android:layout_gravity="center" android:background="@anim/miao_gif" /> </LinearLayout>
复制代码

最后是我们的 MainActivity.java,这里在这里控制动画的开始以及暂停

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private Button btn_start; private Button btn_stop; private ImageView img_show; private AnimationDrawable anim;
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); bindViews(); anim = (AnimationDrawable) img_show.getBackground(); }
private void bindViews() { btn_start = (Button) findViewById(R.id.btn_start); btn_stop = (Button) findViewById(R.id.btn_stop); img_show = (ImageView) findViewById(R.id.img_show); btn_start.setOnClickListener(this); btn_stop.setOnClickListener(this); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.btn_start: anim.start(); break; case R.id.btn_stop: anim.stop(); break; } }}
复制代码

示例二:在指定地方播放帧动画

运行效果图


代码实现

依旧是先上我们的动画文件:anim_zhuan.xml

<animation-list xmlns:android="http://schemas.android.com/apk/res/android"    android:oneshot="true">    <item        android:drawable="@mipmap/img_zhuan1"        android:duration="80" />    <item        android:drawable="@mipmap/img_zhuan2"        android:duration="80" />    <item        android:drawable="@mipmap/img_zhuan3"        android:duration="80" />     <!--限于篇幅,省略其他item,自己补上-->    ...</animation-list> 
复制代码

接着我们来写一个自定义的 ImageView:FrameView.java,这里通过反射获得当前播放的帧,然后是否为最后一帧,是的话隐藏控件!

/** * Created by Jay on 2015/11/15 0015. */public class FrameView extends ImageView {
private AnimationDrawable anim;
public FrameView(Context context) { super(context); }
public FrameView(Context context, AttributeSet attrs) { super(context, attrs); }
public FrameView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); }
public void setAnim(AnimationDrawable anim){ this.anim = anim; }
public void setLocation(int top,int left){ this.setFrame(left,top,left + 200,top + 200); }
@Override protected void onDraw(Canvas canvas) { try{ //反射调用AnimationDrawable里的mCurFrame值 Field field = AnimationDrawable.class .getDeclaredField("mCurFrame"); field.setAccessible(true); int curFrame = field.getInt(anim);// 获取anim动画的当前帧 if (curFrame == anim.getNumberOfFrames() - 1)// 如果已经到了最后一帧 { //让该View隐藏 setVisibility(View.INVISIBLE); } }catch (Exception e){e.printStackTrace();} super.onDraw(canvas); }}
复制代码

最后是我们的 MainActivity.java,创建一个 FrameLayout,添加 View,对触摸事件中按下的事件做处理,显示控件以及开启动画。

public class MainActivity extends AppCompatActivity {
private FrameView fView; private AnimationDrawable anim = null;
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); FrameLayout fly = new FrameLayout(this); setContentView(fly); fView = new FrameView(this); fView.setBackgroundResource(R.anim.anim_zhuan); fView.setVisibility(View.INVISIBLE); anim = (AnimationDrawable) fView.getBackground(); fView.setAnim(anim); fly.addView(fView); fly.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { //设置按下时才产生动画效果 if(event.getAction() == MotionEvent.ACTION_DOWN){ anim.stop(); float x = event.getX(); float y = event.getY(); fView.setLocation((int) y - 40,(int)x-20); //View显示的位置 fView.setVisibility(View.VISIBLE); anim.start(); //开启动画 } return false; } }); }}
复制代码

3.本节示例代码和 Gif 帧提取工具下载

AnimationDemo1.zip

AnimationDemo2.zip

Gif帧提取工具

发布于: 刚刚阅读数: 3
用户头像

向阳逐梦

关注

人生享受编程,编程造就人生! 2022-06-01 加入

某公司芯片测试工程师,嵌入式开发工程师,InfoQ签约作者,阿里云星级博主,华为云·云享专家。座右铭:向着太阳,追逐梦想!

评论

发布
暂无评论
Android动画之帧动画_android_向阳逐梦_InfoQ写作社区