【从 0 开始开发一款直播 APP】14 animation-list 逐帧动画自定义 Switch 控件

本文为菜鸟窝作者蒋志碧的连载。“从 0 开始开发一款直播 APP ”系列来聊聊时下最火的直播 APP,如何完整的实现一个类"腾讯直播"的商业化项目


一、Android 中的逐帧动画

先来说说什么是逐帧动画,逐帧动画是一种常见的动画形式(Frame By Frame),其原理是在「连续的关键帧」中分解动画动作,也就是在时间轴的每帧上逐帧绘制不同的内容,使其连续播放而成动画。 因为逐帧动画的帧序列内容不一样,不但给制作增加了负担而且最终输出的文件量也很大,但它的优势也很明显:逐帧动画具有非常大的灵活性,几乎可以表现任何想表现的内容,而它类似与电影的播放模式,很适合于表演细腻的动画。

在 Android 中逐帧动画需要得到 AnimationDrawable 类的支持,是 Drawable 的间接子类。它主要用来创建一个逐帧动画,并且可以对帧进行拉伸,把它设置为 View 的背景即可使用 AnimationDrawable.start() 方法播放。既然逐帧动画是需要播放一帧一帧的图像,所以需要为其添加帧。

AnimationDrawable 结构图

【从 0 开始开发一款直播 APP】14 animation-list 逐帧动画自定义 Switch 控件_第1张图片

官方示例

用于创建逐帧动画的对象,由一系列 Drawable 对象定义,可用作 View 对象的背景。 创建逐帧动画的最简单的方法是将 XML 文件中的动画定义在 res/drawablefolder 中,并将其设置为 View 对象的背景。 然后,调用start() 来运行动画。 在 XML 中定义的 AnimationDrawable 由单个 元素和一系列嵌套的 标签组成。 每个项目定义一个动画框架。 参见下面的例子。


【从 0 开始开发一款直播 APP】14 animation-list 逐帧动画自定义 Switch 控件_第2张图片

二、利用逐帧动画实现自定义 Switch 控件

在谷歌的 Material Design 官方专题中,花了整整一页来介绍 Delightful Details,其中有帧动画的绝佳例子。

【从 0 开始开发一款直播 APP】14 animation-list 逐帧动画自定义 Switch 控件_第3张图片

接下来讲解直播中用到的控件,效果如下
【从 0 开始开发一款直播 APP】14 animation-list 逐帧动画自定义 Switch 控件_第4张图片

定义了两个 Animation-list,文件存放在 res/drawable 目录下

switch_open.xml




    
    
    

switch_close.xml



    
    
    

CustomSwitch.java

CustomSwitch 继承自 AppCompatImageView,AppCompatImageView 继承自 ImageView,实现其构造函数和方法

public class CustomSwitch extends android.support.v7.widget.AppCompatImageView {
    private boolean mChecked = false;
    private AnimationDrawable mAnimationDrawable;
    private Handler mHandler;
    private Runnable mRunnable;
    
    //这里三个构造函数参数类似,相互调用,在第三个构造函数中初始化动画
    public CustomSwitch(Context context) {
        this(context, null);
    }
    public CustomSwitch(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }
    public CustomSwitch(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    //初始化动画
    private void init() {
        mHandler = new Handler();
        mRunnable = new Runnable() {
            @Override
            public void run() {
                onAnimation();
            }
        };
    }

    /**
     * 动画播放
     */
    private void onAnimation() {
        //判断是否选中
        if (mChecked) {
            setImageResource(R.drawable.btn_switch_on);
        } else {
            setImageResource(R.drawable.btn_switch_off);
        }
    }
    //设置选中
    public void setChecked(boolean checked, boolean playAnim) {
        if (checked == mChecked) {
            return;
        }
        mChecked = checked;
        //判断是否正在播放
        if (playAnim) {
            setImageResource(mChecked ? R.drawable.switch_open : R.drawable.switch_close);
            mAnimationDrawable = (AnimationDrawable) getDrawable();
            mAnimationDrawable.start();
            mHandler.postDelayed(mRunnable, getTotalDuration(mAnimationDrawable));
        }
    }

    /**
     * 返回总时长
     * @param animationDrawable
     * @return
     */
    private long getTotalDuration(AnimationDrawable animationDrawable) {
        int duration = 0;
        for (int i = 0; i < animationDrawable.getNumberOfFrames(); i++) {
            duration += animationDrawable.getDuration(i);
        }
        return duration;
    }

    public boolean isChecked() {
        return mChecked;
    }
}

三、CustomSwitch 的使用

activity_publish.xml


 
    

PublishActivity.java

public class PublishActivity extends BaseActivity implements View.OnClickListener{

    private CustomSwitch mBtnSwitch;

    @Override
    protected void setActionBar() {

    }

    @Override
    protected void setListener() {
        mBtnSwitch.setOnClickListener(this);
    }

    @Override
    protected void initData() {
      
    }

    @Override
    protected void initView() {
        mBtnSwitch = obtainView(R.id.btn_record);
    }

    @Override
    protected int getLayoutId() {
        return R.layout.activity_publish;
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.btn_record:
                if (mBtnSwitch.isChecked()) {
                    mBtnSwitch.setChecked(false, true);
                    mTvRecord.setText("不进行录制");
                } else {
                    mBtnSwitch.setChecked(true, true);
                    mTvRecord.setText("进行录制");
                }
                break;
        }
}

详情请转至 GitHub
参考:

https://developer.android.com/reference/android/graphics/drawable/AnimationDrawable.html

http://www.cnblogs.com/plokmju/p/android_AnimationDrawable.html

撸这个项目的一半,你就是大神 , 戳http://mp.weixin.qq.com/s/ZagocTlDfxZpC2IjUSFhHg

你可能感兴趣的:(【从 0 开始开发一款直播 APP】14 animation-list 逐帧动画自定义 Switch 控件)