[置顶] Android中使用Movie显示gif动态图

转载请注明: 

http://blog.csdn.net/u012975705/article/details/48717391 
在看这篇博文之前对attr自定义属性还是不是很熟的童鞋可以先看看:Android中attr详解(http://blog.csdn.net/u012975705/article/details/48716797) 
源码下载:https://github.com/noyo/GifTest

效果图

这里写图片描述 
显示的事两张动态gif图

实现代码

1、布局activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" xmlns:gif="http://schemas.android.com/apk/res-auto" android:gravity="center" android:orientation="vertical" > <com.practice.noyet.giftest.MyGiftView android:id="@+id/gif1" gif:gif="@raw/gift1" android:layout_width="150dp" android:layout_height="150dp" android:layout_gravity="center_horizontal" android:enabled="false" /> <com.practice.noyet.giftest.MyGiftView android:layout_marginTop="10dp" gif:gif="@raw/gift2" android:id="@+id/gif2" android:layout_width="150dp" android:layout_height="150dp" android:layout_gravity="center_horizontal" android:enabled="false" /> </LinearLayout>

 

2、自定义的com.practice.noyet.giftest.MyGiftView.Java代码(代码中都有注释,我就不废话了):

package com.practice.noyet.giftest;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas; import android.graphics.Movie; import android.os.Build; import android.util.AttributeSet; import android.view.View; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; /** * Created by noyet on 2015/9/24. */ public class MyGiftView extends View { /** gift动态效果总时长,在未设置时长时默认为1秒 */ private static final int DEFAULT_MOVIE_DURATION = 1000; /** gift图片资源ID */ private int mGiftId; /** Movie实例,用来显示gift图片 */ private Movie mMovie; /** 显示gift图片的动态效果的开始时间 */ private long mMovieStart; /** 动态图当前显示第几帧 */ private int mCurrentAnimationTime = 0; /** 图片离屏幕左边的距离 */ private float mLeft; /** 图片离屏幕上边的距离 */ private float mTop; /** 图片的缩放比例 */ private float mScale; /** 图片在屏幕上显示的宽度 */ private int mMeasuredMovieWidth; /** 图片在屏幕上显示的高度 */ private int mMeasuredMovieHeight; /** 是否显示动画,为true表示显示,false表示不显示 */ private boolean mVisible = true; /** 动画效果是否被暂停 */ private volatile boolean mPaused = false; public MyGiftView(Context context) { this(context, null); } public MyGiftView(Context context, AttributeSet attrs) { this(context, attrs, R.styleable.CustomTheme_gifViewStyle); } public MyGiftView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); setViewAttributes(context, attrs, defStyleAttr); } /** * * @param context 上下文 * @param attrs 自定义属性 * @param defStyle 默认风格 */ @SuppressLint("NewApi") private void setViewAttributes(Context context, AttributeSet attrs, int defStyle) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { setLayerType(View.LAYER_TYPE_SOFTWARE, null); } final TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.MyGiftView, defStyle, R.style.Widget_MyGiftView); mGiftId = array.getResourceId(R.styleable.MyGiftView_gif, -1); mPaused = array.getBoolean(R.styleable.MyGiftView_paused, false); array.recycle(); if (mGiftId != -1) { byte[] bytes = getGiftBytes(); mMovie = Movie.decodeByteArray(bytes, 0, bytes.length); } } /** * 设置gif图资源 * @param giftResId */ public void setMovieResource(int giftResId) { this.mGiftId = giftResId; byte[] bytes = getGiftBytes(); mMovie = Movie.decodeByteArray(bytes, 0, bytes.length); requestLayout(); } /** * 手动设置 Movie对象 * @param movie Movie */ public void setMovie(Movie movie) { this.mMovie = movie; requestLayout(); } /** * 得到Movie对象 * @return Movie */ public Movie getMovie() { return mMovie; } /** * 设置要显示第几帧动画 * @param time */ public void setMovieTime(int time) { mCurrentAnimationTime = time; invalidate(); } /** * 设置暂停 * * @param paused */ public void setPaused(boolean paused) { this.mPaused = paused; if (!paused) { mMovieStart = android.os.SystemClock.uptimeMillis() - mCurrentAnimationTime; } invalidate(); } /** * 判断gif图是否停止了 * * @return */ public boolean isPaused() { return this.mPaused; } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { if (mMovie != null) { int movieWidth = mMovie.width(); int movieHeight = mMovie.height(); int maximumWidth = MeasureSpec.getSize(widthMeasureSpec); float scaleW = (float) movieWidth / (float) maximumWidth; mScale = 1f / scaleW; mMeasuredMovieWidth = maximumWidth; mMeasuredMovieHeight = (int) (movieHeight * mScale); setMeasuredDimension(mMeasuredMovieWidth, mMeasuredMovieHeight); } else { setMeasuredDimension(getSuggestedMinimumWidth(), getSuggestedMinimumHeight()); } } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { super.onLayout(changed, l, t, r, b); mLeft = (getWidth() - mMeasuredMovieWidth) / 2f; mTop = (getHeight() - mMeasuredMovieHeight) / 2f; mVisible = getVisibility() == View.VISIBLE; } @Override protected void onDraw(Canvas canvas) { if (mMovie != null) { if (!mPaused) { updateAnimationTime(); drawMovieFrame(canvas); invalidateView(); } else { drawMovieFrame(canvas); } } } /** * 重绘 */ @SuppressLint("NewApi") private void invalidateView() { if (mVisible) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { postInvalidateOnAnimation(); } else { invalidate(); } } } /** * 更新当前显示进度 */ private void updateAnimationTime() { long now = android.os.SystemClock.uptimeMillis(); // 如果第一帧,记录起始时间 if (mMovieStart == 0) { mMovieStart = now; } // 取出动画的时长 int dur = mMovie.duration(); if (dur == 0) { dur = DEFAULT_MOVIE_DURATION; } // 算出需要显示第几帧 mCurrentAnimationTime = (int) ((now - mMovieStart) % dur); } /** * 绘制图片 * @param canvas 画布 */ private void drawMovieFrame(Canvas canvas) { // 设置要显示的帧,绘制即可 mMovie.setTime(mCurrentAnimationTime); canvas.save(Canvas.MATRIX_SAVE_FLAG); canvas.scale(mScale, mScale); mMovie.draw(canvas, mLeft / mScale, mTop / mScale); canvas.restore(); } @SuppressLint("NewApi") @Override public void onScreenStateChanged(int screenState) { super.onScreenStateChanged(screenState); mVisible = screenState == SCREEN_STATE_ON; invalidateView(); } @SuppressLint("NewApi") @Override protected void onVisibilityChanged(View changedView, int visibility) { super.onVisibilityChanged(changedView, visibility); mVisible = visibility == View.VISIBLE; invalidateView(); } @Override protected void onWindowVisibilityChanged(int visibility) { super.onWindowVisibilityChanged(visibility); mVisible = visibility == View.VISIBLE; invalidateView(); } /** * 将gif图片转换成byte[] * @return byte[] */ private byte[] getGiftBytes() { ByteArrayOutputStream baos = new ByteArrayOutputStream(); InputStream is = getResources().openRawResource(mGiftId); byte[] b = new byte[1024]; int len; try { while ((len = is.read(b, 0, 1024)) != -1) { baos.write(b, 0, len); } baos.flush(); } catch (IOException e) { e.printStackTrace(); } finally { if (is != null) { try { is.close(); } 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值