標籤:
http://blog.csdn.net/guolin_blog/article/details/11100315
總體思路是這樣的
PowerImageView類繼承ImageView類
給PowerImageView類添加自訂屬性auto_play
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" > <com.example.customview.CounterView android:layout_width="100dp" android:layout_height="100dp" android:layout_centerInParent="true" /> </RelativeLayout>
建構函式中,初始化:
得到資源id,通過id擷取流,判斷是不是gif圖片
如果是gif圖片,需要得到:auto_play,圖片長度,圖片寬度這三個屬性
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); // 使用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); } } } }
得到資源id的方法有兩個:
1.反射
/** * 通過Java反射,擷取到src指定圖片資源所對應的id。 * * @param a * @param context * @param attrs * @return 返回布局檔案中指定圖片資源所對應的id,沒有指定任何圖片資源就返回0。 */ private int getResourceId(TypedArray a, Context context, AttributeSet attrs) { try { Field field = TypedArray.class.getDeclaredField("mValue"); field.setAccessible(true); TypedValue typedValueObject = (TypedValue) field.get(a); return typedValueObject.resourceId; } catch (Exception e) { e.printStackTrace(); } finally { if (a != null) { a.recycle(); } } return 0; }
這個方法可以得到的不僅僅是自訂的屬性,給ImageView設定的所有屬性都可以一起得到。
2.通過attr的方法
for (int i = 0; i < attrs.getAttributeCount(); i++)
{
if(attrs.getAttributeName(i).equals("src"))
{
System.out.println(attrs.getAttributeResourceValue(i, 0)+"=========");
return attrs.getAttributeResourceValue(i, 0);
}
}
播放gif的方法:
儲存起始時間,判斷現在時間-起始時間是否大於動畫長度,大於則停
下面我們來看看playMovie()方法中是怎樣播放GIF圖片的吧。可以看到,首先會對動畫開始的時間做下記錄,然後對動畫持續的時間做下記錄,接著使用當前的時間減去動畫開始的時間,得到的時間就是此時PowerImageView應該顯示的那一幀,然後藉助Movie對象將這一幀繪製到螢幕上即可。之後每次調用playMovie()方法都會繪製一幀圖片,連貫起來也就形成了GIF動畫。注意,這個方法是有傳回值的,如果目前時間減去動畫開始時間大於了動畫期間,那就說明動畫播放完成了,返回true,否則返回false。
/** * 開始播放GIF動畫,播放完成返回true,未完成返回false。 * * @param canvas * @return 播放完成返回true,未完成返回false。 */ private boolean playMovie(Canvas canvas) { long now = SystemClock.uptimeMillis(); if (mMovieStart == 0) { mMovieStart = now; } 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; }
繪製gif:
onMeasure規定圖片大小,gif則用setMeasuredDimension給定大小
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); if (mMovie != null) { // 如果是GIF圖片則重寫設定PowerImageView的大小 setMeasuredDimension(mImageWidth, mImageHeight); } }
onDraw繪製圖片,非gir則用預設
起始時繪製開始按鈕
isplaying時繼續調用play_movie,再invalidate()
@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); } } } }
然後我們還可以通過修改activity_main.xml中的代碼,給它加上允許自動播放的屬性,代碼如下所示:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:attr="http://schemas.android.com/apk/res/com.example.powerimageviewtest" android:layout_width="match_parent" android:layout_height="match_parent" > <com.example.powerimageviewtest.PowerImageView android:id="@+id/image_view" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:src="@drawable/anim" attr:auto_play="true" /> </RelativeLayout>
注意:
這裡不能對gif的大小進行設定,gif多大,顯示出來就是多大。這裡主要是示範自訂view,並不是專門實現gif功能
源碼下載,請點擊這裡
Android-自訂View實現ImageView播放gif