Android-自訂View實現ImageView播放gif

來源:互聯網
上載者:User

標籤:

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

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.