[Android开发]Gif图片下载和显示

来源:互联网 发布:nginx阿里云绑定域名 编辑:程序博客网 时间:2024/06/05 10:43

浏览了很多网上很多关于Gif图片显示的资料,总结起来一共为四种方案:

1.使用GitHub:android-gif-drawable ,具体方法网上很多参考。

缺点:目前GitHub上的源码是使用AndroidStudio写的,使用Eclipse编译起来比较麻烦,而且,使用jni,对于一般跟我一样水平的一时还搞不明白,且使用下载的最近的jar包某些机型会报jni的错,比如HTC M8 和三星S4.

2.使用GifView,该种方案在网上使用较多,参考资料也较多,说一说我使用该jar包遇到的问题,在加载大量图片的时候,我加载了一共9张图,显示第3张的时候出现OOM。

3.使用Movie,这是我在使用以上两种方案不成功之后,采用的方案,一会具体说说实现过程。

4.使用webview,该种方法没有写demo测试,具体可行性为止,看到有人问,如何释放webview加载的资源,应该是存在这样的问题的,但是,如果可以解决,也不失为一种好的方案。

具体说一说,第三种方案,使用Movie现实现实Gif图片。


/** * This is a View class that wraps Android {@link Movie} object and displays it. * You can set GIF as a Movie object or as a resource id from XML or by calling * {@link #setMovie(Movie)} or {@link #setMovieResource(int)}. * <p> * You can pause and resume GIF animation by calling {@link #setPaused(boolean)}. * <p> * The animation is drawn in the center inside of the measured view bounds. *  * @author Sergey Bakhtiarov */public class GifMovieView extends View {private static final int DEFAULT_MOVIEW_DURATION = 1000;private int mMovieResourceId;private Movie mMovie;private long mMovieStart;private int mCurrentAnimationTime = 0;/** * Position for drawing animation frames in the center of the view. */private float mLeft;private float mTop;/** * Scaling factor to fit the animation within view bounds. */private float mScale;//控制图片显示大小/** * Scaled movie frames width and height. */private int mMeasuredMovieWidth;private int mMeasuredMovieHeight;private volatile boolean mPaused = false;private boolean mVisible = true;public GifMovieView(Context context) {this(context, null);}public GifMovieView(Context context, AttributeSet attrs) {this(context, attrs, R.styleable.CustomTheme_gifMoviewViewStyle);}public GifMovieView(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);setViewAttributes(context, attrs, defStyle);}@SuppressLint("NewApi")private void setViewAttributes(Context context, AttributeSet attrs,int defStyle) {/** * Starting from HONEYCOMB have to turn off HW acceleration to draw * Movie on Canvas. */if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {setLayerType(View.LAYER_TYPE_SOFTWARE, null);}final TypedArray array = context.obtainStyledAttributes(attrs,R.styleable.GifMoviewView, defStyle,R.style.Widget_GifMoviewView);mMovieResourceId = array.getResourceId(R.styleable.GifMoviewView_gif,-1);mPaused = array.getBoolean(R.styleable.GifMoviewView_paused, false);array.recycle();if (mMovieResourceId != -1) {mMovie = Movie.decodeStream(getResources().openRawResource(mMovieResourceId));}}public void setMovieInputStream(InputStream is) {if (is.markSupported()) {try {int readlimit = is.available();is.mark(readlimit);} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}mMovie = Movie.decodeStream(is);requestLayout();}public void setMovieResource(int movieResId) {this.mMovieResourceId = movieResId;mMovie = Movie.decodeStream(getResources().openRawResource(mMovieResourceId));requestLayout();}public void setMovie(Movie movie) {this.mMovie = movie;requestLayout();}public Movie getMovie() {return mMovie;}public void setMovieTime(int time) {mCurrentAnimationTime = time;invalidate();}public void setPaused(boolean paused) {this.mPaused = paused;/** * Calculate new movie start time, so that it resumes from the same * frame. */if (!paused) {mMovieStart = android.os.SystemClock.uptimeMillis()- mCurrentAnimationTime;}invalidate();}public boolean isPaused() {return this.mPaused;}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {if (mMovie != null) {int movieWidth = mMovie.width();int movieHeight = mMovie.height();/* * Calculate horizontal scaling */float scaleH = 1f;int measureModeWidth = MeasureSpec.getMode(widthMeasureSpec);if (measureModeWidth != MeasureSpec.UNSPECIFIED) {int maximumWidth = MeasureSpec.getSize(widthMeasureSpec);if (maximumWidth > movieWidth) {scaleH = (float) maximumWidth / (float) movieWidth;}}/* * calculate vertical scaling */float scaleW = 1f;int measureModeHeight = MeasureSpec.getMode(heightMeasureSpec);if (measureModeHeight != MeasureSpec.UNSPECIFIED) {int maximumHeight = MeasureSpec.getSize(heightMeasureSpec);if (maximumHeight > movieHeight) {scaleW = (float) maximumHeight / (float) movieHeight;}}/* * calculate overall scale */mScale = Math.min(scaleH, scaleW);mMeasuredMovieWidth = (int) (movieWidth * mScale);mMeasuredMovieHeight = (int) (movieHeight * mScale);setMeasuredDimension(mMeasuredMovieWidth, mMeasuredMovieHeight);} else {/* * No movie set, just set minimum available size. */setMeasuredDimension(getSuggestedMinimumWidth(),getSuggestedMinimumHeight());}}@Overrideprotected void onLayout(boolean changed, int l, int t, int r, int b) {super.onLayout(changed, l, t, r, b);/* * Calculate left / top for drawing in center */mLeft = (getWidth() - mMeasuredMovieWidth) / 2f;mTop = (getHeight() - mMeasuredMovieHeight) / 2f;mVisible = getVisibility() == View.VISIBLE;}@Overrideprotected void onDraw(Canvas canvas) {if (mMovie != null) {if (!mPaused) {updateAnimationTime();drawMovieFrame(canvas);invalidateView();} else {drawMovieFrame(canvas);}}}/** * Invalidates view only if it is visible. <br> * {@link #postInvalidateOnAnimation()} is used for Jelly Bean and higher. *  */@SuppressLint("NewApi")private void invalidateView() {if (mVisible) {if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {postInvalidateOnAnimation();} else {invalidate();}}}/** * Calculate current animation time */private void updateAnimationTime() {long now = android.os.SystemClock.uptimeMillis();if (mMovieStart == 0) {mMovieStart = now;}int dur = mMovie.duration();if (dur == 0) {dur = DEFAULT_MOVIEW_DURATION;}mCurrentAnimationTime = (int) ((now - mMovieStart) % dur);}/** * Draw current GIF frame */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")@Overridepublic void onScreenStateChanged(int screenState) {super.onScreenStateChanged(screenState);mVisible = screenState == SCREEN_STATE_ON;invalidateView();}@SuppressLint("NewApi")@Overrideprotected void onVisibilityChanged(View changedView, int visibility) {super.onVisibilityChanged(changedView, visibility);mVisible = visibility == View.VISIBLE;invalidateView();}@Overrideprotected void onWindowVisibilityChanged(int visibility) {super.onWindowVisibilityChanged(visibility);mVisible = visibility == View.VISIBLE;invalidateView();}}


在attrs.xml添加

 <resources>   <declare-styleable name="GifMoviewView">        <attr name="gif" format="reference" />        <attr name="paused" format="boolean" />    </declare-styleable>    <declare-styleable name="CustomTheme">        <attr name="gifMoviewViewStyle" format="reference" />    </declare-styleable></resources>


使用

    <com.example.ui.view.GifMovieView        android:id="@+id/gif_image"        android:layout_width="fill_parent"        android:layout_height="wrap_content"        android:layout_gravity="center" />

File gifFile = new File(result);BufferedInputStream bis = new BufferedInputStream(new FileInputStream(gifFile));<pre name="code" class="html"><span style="white-space: pre;"></span>iv_header.setMovieInputStream(bis);


Finish。


0 0
原创粉丝点击