Android 显示 Gif动态图片的三种常用方法
2015-02-10 17:43
501 查看
1.首先描述下自定义控件的一般方法:
自定义控件是被创造出来,所以先要复写它三个的构造方法,根据需求决定复写哪个,若没有自定义属性,复写只有一个参数的即可。若有自定义属性,则可以通过obtainStyledAttributes获得TypedArray对象,通过该对象获得属性并进行相应操作。然后下面的过程和画画差不多,我们在画一样东西的时候,首先要知道物品大概的样子,也就是需要复写onMeasure()方法,测量控件以及其子布局的大小。知道物品的大概后,我们需要对其里面的细节精雕细琢,也就是调用onLayout()方法,决定其子View的位置。最后就是将图整体勾勒出来,即是调用onDraw()方法。这样子控件大概的样子就出来了,再根据需求增加相应借口,回调方法。
2.Android显示gif的三种方式:
(1)使用Android自带的Movie对象,将Gif当成视频。随着时间的变化,通过setTime方法设置需要显示的图片,然后onDraw方法不断将新的画画出来。实例代码如下:
MainActivity:
自定义组件GifView:
(2)自定义TextView显示Gif,先使用GifDecoder将Gif文件解析成一张张图片,然后通过ImageSpan将图片显示在TextView中,定义一个线程不断刷新图片。
自定义TextView:
完整项目链接:http://download.csdn.net/detail/aehaojiu/8438351
(3)使用WebView加载Gif:
自定义控件是被创造出来,所以先要复写它三个的构造方法,根据需求决定复写哪个,若没有自定义属性,复写只有一个参数的即可。若有自定义属性,则可以通过obtainStyledAttributes获得TypedArray对象,通过该对象获得属性并进行相应操作。然后下面的过程和画画差不多,我们在画一样东西的时候,首先要知道物品大概的样子,也就是需要复写onMeasure()方法,测量控件以及其子布局的大小。知道物品的大概后,我们需要对其里面的细节精雕细琢,也就是调用onLayout()方法,决定其子View的位置。最后就是将图整体勾勒出来,即是调用onDraw()方法。这样子控件大概的样子就出来了,再根据需求增加相应借口,回调方法。
2.Android显示gif的三种方式:
(1)使用Android自带的Movie对象,将Gif当成视频。随着时间的变化,通过setTime方法设置需要显示的图片,然后onDraw方法不断将新的画画出来。实例代码如下:
MainActivity:
public class MainActivity extends Activity { private GifView gv; private ListView lv_content; private int[] gifResource={R.drawable.car,R.drawable.rick,R.drawable.car,R.drawable.mm,R.drawable.qq}; private MyAdapter adapter=null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); lv_content=(ListView) findViewById(R.id.lv_content); adapter = new MyAdapter(); lv_content.setAdapter(adapter); /* lv_content.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { if(adapter!=null) { adapter.notifyDataSetChanged(); } } });*/ // 去掉listView的item点击的效果 // lv_content.setEnabled(false); lv_content.setSelector(color.transparent); } private class MyAdapter extends BaseAdapter{ @Override public int getCount() { // TODO Auto-generated method stub return gifResource.length; } @Override public Object getItem(int position) { return null; } @Override public long getItemId(int position) { return 0; } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder=null; if(convertView == null) { convertView=View.inflate(getApplicationContext(), R.layout.item_gif, null); holder=new ViewHolder(); holder.tv_username=(TextView) convertView.findViewById(R.id.tv_username); holder.tv_comemnt=(TextView) convertView.findViewById(R.id.tv_comment); holder.gv=(GifView) convertView.findViewById(R.id.gv); convertView.setTag(holder); }else{ holder=(ViewHolder) convertView.getTag(); } holder.tv_username.setText("username"+position); holder.tv_comemnt.setText("comment"+position); holder.gv.setMovieResource(gifResource[position]); holder.gv.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { GifView view=(GifView) v; view.setPaused(!view.isPause()); } }); return convertView; } class ViewHolder{ public TextView tv_username; public TextView tv_comemnt; public GifView gv; } } }
自定义组件GifView:
package com.example.gifdemo.view; import com.example.gifdemo.R; 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.os.SystemClock; import android.util.AttributeSet; import android.view.View; /**使用Android自定义的movie实现**/ public class GifView extends View{ private static final int DEFAULT_GIF_DURATION=1000; // the reference for gif private int mMovieResourceId; private Movie mMovie; private long mStart; private int mCurrentAnimationTime=0; private boolean mPause=true; private boolean mVisible=true; private long mWidth; private long mHeight; private float mScale; private float mLeft; private float mTop; private int mMeasuredWidth; private int mMeasureHeight; public GifView(Context context) { this(context,null); } public GifView(Context context, AttributeSet attrs) { this(context, attrs,R.styleable.CustomTheme_gifMoviewViewStyle); } public GifView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); setViewAttributes(context, attrs, defStyleAttr); } private void setViewAttributes(Context context, AttributeSet attrs, int defStyleAttr) { /** * 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); } //?? TODO get the collection of the attrs final TypedArray array=context.obtainStyledAttributes(attrs, R.styleable.GifView, defStyleAttr, R.style.Widget_GifMoviewView); mPause=array.getBoolean(R.styleable.GifView_paused, true); mMovieResourceId=array.getResourceId(R.styleable.GifView_gif, -1); // recycle TypedArray array.recycle(); if(mMovieResourceId!=-1) { mMovie=Movie.decodeStream(getResources().openRawResource(mMovieResourceId)); } } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { if(mMovie!=null) { int mWidth=mMovie.width(); int mHeight=mMovie.height(); float scaleX=1f; int measureModeWidth=MeasureSpec.getMode(widthMeasureSpec); if(measureModeWidth!=MeasureSpec.UNSPECIFIED) { int maximumWidth=MeasureSpec.getSize(widthMeasureSpec); if(mWidth>maximumWidth) { scaleX=(float)mWidth/(float)maximumWidth; } } float scaleY=1f; int measureModeHeight=MeasureSpec.getMode(heightMeasureSpec); if(measureModeHeight!=MeasureSpec.UNSPECIFIED) { int maximumHeight=MeasureSpec.getSize(heightMeasureSpec); if(mHeight>maximumHeight) { scaleY=(float)mHeight/(float)maximumHeight; } } mScale=1f/Math.max(scaleX, scaleY); mMeasuredWidth=(int) (mWidth*mScale); mMeasureHeight=(int) (mHeight*mScale); setMeasuredDimension(mMeasuredWidth,mMeasureHeight); }else { setMeasuredDimension(getSuggestedMinimumWidth(), getSuggestedMinimumHeight()); } } @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); /** Calculate left / top for drawing in center **/ mLeft=(getWidth()-mMeasuredWidth)/2f; mTop=(getHeight()-mMeasureHeight)/2f; mVisible= getVisibility() == View.VISIBLE; } @Override protected void onDraw(Canvas canvas) { if(mMovie!=null) { if(!mPause) { updateCurrentTime(); drawFrame(canvas); invalidateView(); }else{ drawFrame(canvas); } } } private void updateCurrentTime() { long now=SystemClock.uptimeMillis(); if(mStart==0) { mStart=now; } int dur=mMovie.duration(); if(dur==0) { dur=DEFAULT_GIF_DURATION; } mCurrentAnimationTime=(int)((now-mStart)%dur); } private void drawFrame(Canvas canvas) { mMovie.setTime(mCurrentAnimationTime); canvas.save(Canvas.MATRIX_SAVE_FLAG); canvas.scale(mScale, mScale); // TODO mMovie.draw(canvas, mLeft/mScale, mTop/mScale); mMovie.draw(canvas, 0, 0); canvas.restore(); } /** * Invalidates view only if it is visible. * <br> * {@link #postInvalidateOnAnimation()} is used for Jelly Bean and higher. * */ @Suppres bede sLint("NewApi") private void invalidateView() { if(mVisible) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { postInvalidateOnAnimation(); } else { invalidate(); } } } // the methods of the important attribute public void setPaused(boolean pause) { this.mPause=pause; // retrieve the StartTime if(!mPause) { mStart=SystemClock.uptimeMillis()-mCurrentAnimationTime; } invalidate(); } public boolean isPause() { return mPause; } public void setMovieResource(int movieResourceId) { this.mMovieResourceId=movieResourceId; mMovie=Movie.decodeStream(getResources().openRawResource(movieResourceId)); // important Call this when something has changed which has invalidated the //layout of this view. requestLayout(); } public void setMovie(Movie movie) { this.mMovie=movie; requestLayout(); } public Movie getMovie() { return mMovie; } public void setMovieTime(int time) { this.mCurrentAnimationTime=time; invalidate(); } }
(2)自定义TextView显示Gif,先使用GifDecoder将Gif文件解析成一张张图片,然后通过ImageSpan将图片显示在TextView中,定义一个线程不断刷新图片。
自定义TextView:
package com.yyg.gifdemo3.view; public class MyTextView extends TextView{ private Context mContext; private SpannableStringBuilder mSb=new SpannableStringBuilder(); private String dummyStr="dummy"; private SimpleImageMemCache mCache; private List<AnimatedImageSpan> mGifSpanList=new ArrayList<AnimatedImageSpan>(); public MyTextView(Context context) { super(context); mContext=context; } public MyTextView(Context context, AttributeSet attrs) { super(context, attrs); mContext=context; } public MyTextView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); mContext=context; } public void setImageCache(SimpleImageMemCache pImageCache) { this.mCache=pImageCache; } @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); Log.d(this.getClass().getName(), "onDetachedFromWindow "); for (AnimatedImageSpan ais : mGifSpanList) { Log.d(this.getClass().getName(), "animation playing " + ais.isPlaying()); if (ais.isPlaying()) { ais.stopRendering(); } } mGifSpanList.clear(); mSb.clearSpans(); mSb.clear(); } public void appendText(String text) { mSb.append(text); } public void appendAnimation(GifResource pAssetsSet,AnimationSettings pSettings) { mSb.append(dummyStr); AnimatedImageSpan ais=new AnimatedImageSpan(mContext); ais.setAssetsSet(pAssetsSet); ais.setBitmapCache(mCache); mSb.setSpan(ais, mSb.length()-dummyStr.length(), mSb.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); AnimationClickableSpan clickableSpan=new AnimationClickableSpan(this, ais, pSettings); mSb.setSpan(clickableSpan, mSb.length()-dummyStr.length(), mSb.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); mGifSpanList.add(ais); } public void finishAddContent() { this.setText(mSb); // setMovementMethod,此方法在需要响应用户事件时使用,如点击一个电话号码就跳转到拨号页面。如果不执行这个方法是不会响应事件的,即便文本看着已经是下划线蓝色字了。 this.setMovementMethod(LinkMovementMethod.getInstance()); } private static class AnimationClickableSpan extends ClickableSpan { private AnimatedImageSpan mImageSpan; private AnimationSettings mSettings; private AnimatedImageUpdateHandler updateHandler; public AnimationClickableSpan(MyTextView pTextView ,AnimatedImageSpan pAnimatedImageSpan,AnimationSettings pSettings) { this.mImageSpan=pAnimatedImageSpan; this.mSettings=pSettings; this.updateHandler=new AnimatedImageUpdateHandler(pTextView); } @Override public void onClick(View widget) { if(this.mImageSpan.isPlaying()) { this.mImageSpan.stopRendering(); }else{ this.mImageSpan.playGif(this.mSettings,this.updateHandler); } } } }
完整项目链接:http://download.csdn.net/detail/aehaojiu/8438351
(3)使用WebView加载Gif:
package com.example.gifdemo3; import android.os.Build; import android.os.Bundle; import android.app.Activity; import android.view.Menu; import android.webkit.WebView; public class MainActivity extends Activity { private WebView wv_gif; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); wv_gif=(WebView) findViewById(R.id.wv_gif); if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.KITKAT) { wv_gif.loadUrl("http://www.wyzu.cn/data/uploadfile/200803/2008032812262650.gif"); } } }
相关文章推荐
- Android三步显示gif动态图片
- ios中用三种方式显示gif动态图片
- Android TextView里直接显示图片的三种方法
- Android TextView里直接显示图片的三种方法
- Android显示GIF图片的方法
- Android 显示和控制gif动态图片的播放
- c# winform 显示动态gif图片的方法
- Android播放Gif动态图片的几种方法
- c# winform 显示动态gif图片的方法
- Android TextView里直接显示图片的三种方法
- Android显示动态图片的两种方法
- Android中动态显示gif图片
- Android TextView里直接显示图片的三种方法
- Android TextView里直接显示图片的三种方法
- Android 显示Gif 动态图片
- Android中显示gif动态图片
- c# winform 显示动态gif图片的方法
- Android之ImageView既能普通图片又能显示gif的方法
- android显示gif动态图的方法
- TextView图文混排,显示添加的图片,三种常用方法,亲测