zoukankan      html  css  js  c++  java
  • [置顶] 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();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
            return baos.toByteArray();
        }
    }
    

    3、MainActivity.java:

    package com.practice.noyet.giftest;
    
    import android.app.Activity;
    import android.os.Bundle;
    
    public class MainActivity extends Activity {
    
        private MyGiftView gif1;
        private MyGiftView gif2;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            gif1 = (MyGiftView) findViewById(R.id.gif1);
            gif2 = (MyGiftView) findViewById(R.id.gif2);
    
            /** ........ */
        }
    
    }
    
     
    博乐点评
    一共有2位博乐进行推荐
    • yayun0516  2015-10-08 20:36:45 
    • 这篇文章很实用啊,正在学习自定义控件的童鞋可以学习学习。会有收获。
    • gao_chun  2015-09-29 15:26:20 
    • 多谢博主的总结。Android中也有好多显示Gif的开源库和ImageView,比如GitHub上的这个:https://github.com/felipecsl/GifImageView
  • 相关阅读:
    XML
    基于SQL的全文检索引擎Sphinx
    php中的Session与Cookie
    公共网关接口CGI(Common GatewayInterface)
    Memcached、memcached、memcache
    MemCache
    在windows上使用symfony创建简易的CMS系统(三)
    在windows上使用symfony创建简易的CMS系统(二)
    在windows上使用symfony创建简易的CMS系统(一)
    Window7上搭建symfony开发环境(PEAR)
  • 原文地址:https://www.cnblogs.com/xgjblog/p/6474813.html
Copyright © 2011-2022 走看看