自定义ImageView,展示gif图或者利用帧动画展示动图

1、自定义ImageView,展示帧动画,让图片变换。适用于专家加V标识,并且让这个V标识动

import android.content.Context;
import android.graphics.drawable.Animatable;
import android.util.AttributeSet;
import android.widget.ImageView;

import com.chen.customviewdemo.R;

public class FrameAnimationImageView extends ImageView {

    public FrameAnimationImageView(Context context) {
        this(context, null);
    }

    public FrameAnimationImageView(Context context, AttributeSet attrs) {
        this(context, attrs, -1);
    }

    public FrameAnimationImageView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        init();
    }

    /**
     * 初始化设置
     */
    private void init() {

        //不可以使用这个
        //setBackgroundResource(R.drawable.frame_anim);

        //需要使用这个
        setImageResource(R.drawable.frame_anim);
        ((Animatable) getDrawable()).start();
    }

}

在drawable文件夹下,创建 frame_anim.xml

<?xml version="1.0" encoding="utf-8"?>
<animation-list
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:oneshot="false">
    <!--设置循环播放-->
    <!--android:oneshot="false"-->
    <!--true 表示单次播放-->
    <item
        android:drawable="@mipmap/a"
        android:duration="60"/>
    <item
        android:drawable="@mipmap/arrow"
        android:duration="60"/>

</animation-list>

在activity的布局文件中声明即可

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    android:id="@+id/activity_main"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    >

    <com.chen.customviewdemo.view.FrameAnimationImageView
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_centerInParent="true"
        />

</RelativeLayout>

————————————————————————————————————–

2、自定义展示gif图的ImageView。需要自定义属性和在清单中关闭硬件加速。后面会有说明

注:因为涉及到流的读取和关闭硬件加速,可能会对其他地方有影响。不太建议使用

PowerImageView

/**
 * PowerImageView是一个经过扩展的ImageView,它不仅继承了ImageView原生的所有功能,还加入了播放GIF动画的功能。
 *
 * @author guolin
 */
public class PowerImageView extends ImageView implements OnClickListener {

    /**
     * 播放GIF动画的关键类
     */
    private Movie mMovie;

    /**
     * 开始播放按钮图片
     */
    private Bitmap mStartButton;

    /**
     * 记录动画开始的时间
     */
    private long mMovieStart;

    /**
     * GIF图片的宽度
     */
    private int mImageWidth;

    /**
     * GIF图片的高度
     */
    private int mImageHeight;

    /**
     * 图片是否正在播放
     */
    private boolean isPlaying;

    /**
     * 是否允许自动播放
     */
    private boolean isAutoPlay;

    /**
     * PowerImageView构造函数。
     *
     * @param context
     */
    public PowerImageView(Context context) {
        super(context);
    }

    /**
     * PowerImageView构造函数。
     *
     * @param context
     */
    public PowerImageView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    /**
     * PowerImageView构造函数,在这里完成所有必要的初始化操作。
     *
     * @param context
     */
    public PowerImageView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.PowerImageView);
        /*int resourceId = getResourceId(a, context, attrs);
        if (resourceId != 0) {
            // 当资源id不等于0时,就去获取该资源的流
            InputStream is = getResources().openRawResource(resourceId);*/

        //直接获取图片的流
        InputStream is = getResources().openRawResource(R.drawable.anim);
        // 使用Movie类对流进行解码
        mMovie = Movie.decodeStream(is);
        if (mMovie != null) {
            // 如果返回值不等于null,就说明这是一个GIF图片,下面获取是否自动播放的属性
            isAutoPlay = a.getBoolean(R.styleable.PowerImageView_auto_play, false);
            Bitmap bitmap = BitmapFactory.decodeStream(is);
            mImageWidth = bitmap.getWidth();
            mImageHeight = bitmap.getHeight();

            bitmap.recycle();
            if (!isAutoPlay) {
                // 当不允许自动播放的时候,得到开始播放按钮的图片,并注册点击事件
                mStartButton = BitmapFactory.decodeResource(getResources(),
                        R.drawable.start_play);
                setOnClickListener(this);
            }
        }
    }

    @Override
    public void onClick(View v) {
        if (v.getId() == this.getId()) {
            // 当用户点击图片时,开始播放GIF动画
            isPlaying = true;
            invalidate();//刷新后执行onDraw方法
        }
    }

    @Override
    protected void onDraw(Canvas canvas) {
        if (mMovie == null) {
            // mMovie等于null,说明是张普通的图片,则直接调用父类的onDraw()方法
            super.onDraw(canvas);
        } else {
            // mMovie不等于null,说明是张GIF图片
            if (isAutoPlay) {
                // 如果允许自动播放,就调用playMovie()方法播放GIF动画
                playMovie(canvas);
                invalidate();
            } else {
                // 不允许自动播放时,判断当前图片是否正在播放
                if (isPlaying) {
                    // 正在播放就继续调用playMovie()方法,一直到动画播放结束为止
                    if (playMovie(canvas)) {
                        isPlaying = false;//若为该值,则不再执行
                    }
                    invalidate();
                } else {
                    // 还没开始播放就只绘制GIF图片的第一帧,并绘制一个开始按钮,也可以表示播放完后的情景
                    mMovie.setTime(0);
                    mMovie.draw(canvas, 0, 0);
                    int offsetW = (mImageWidth - mStartButton.getWidth()) / 2;
                    int offsetH = (mImageHeight - mStartButton.getHeight()) / 2;
                    canvas.drawBitmap(mStartButton, offsetW, offsetH, null);
                }
            }
        }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        if (mMovie != null) {
            // 如果是GIF图片则重写设定PowerImageView的大小
            setMeasuredDimension(mImageWidth, mImageHeight);
        }
    }

    /**
     * 开始播放GIF动画,播放完成返回true,未完成返回false。
     *
     * @param canvas
     * @return 播放完成返回true,未完成返回false。
     */
    private boolean playMovie(Canvas canvas) {
        long now = SystemClock.uptimeMillis();//若循环播放,则不断的得到当前时间
        if (mMovieStart == 0) {
            mMovieStart = now;
        }
        //得到gif图片的时间长
        int duration = mMovie.duration();
        if (duration == 0) {
            duration = 1000;
        }
        //计算有多少帧
        int relTime = (int) ((now - mMovieStart) % duration);
        //设置播放第几帧
        mMovie.setTime(relTime);
        mMovie.draw(canvas, 0, 0);
        if ((now - mMovieStart) >= duration) {
            mMovieStart = 0;
            return true;
        }
        return false;
    }


}

自定义属性 attrs.xml中

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <declare-styleable name="PowerImageView">
        <attr name="auto_play" format="boolean"></attr>
    </declare-styleable>

</resources>

清单文件中:

android:hardwareAccelerated="false"

最后使用:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    android:id="@+id/activity_main"
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">


    <com.chen.animdemo.PowerImageView
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_centerInParent="true"
        android:src="@drawable/anim"
        app:auto_play="true"/>

</RelativeLayout>
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值