【Android實戰】記錄自學自訂GifView過程,能同時支援gif和其他圖片!【實用篇】

來源:互聯網
上載者:User

標籤:android   自訂gifview   反射   

之前寫了一篇部落格,《【Android實戰】記錄自學自訂GifView過程,詳解屬性那些事!【學習篇】》
關於自訂GifView的,詳細講解了學習過程及遇到的一些類的解釋,然後完成了一個項目,能通過在xml加入自訂 view (MyGifView)中加入自訂屬性(my:gif_src = “@drawable/coffee”),達到播放gif圖片的效果。

但是,有幾個問題

1.gif_src 屬性只支援 gif 圖,並不支援其他類型的圖片

2.只支援預設的引用圖片,不能另外設定

問題一

gif_src 屬性只支援 gif 圖,並不支援其他類型的圖片。

解決思路:
ImageView本身有個屬性 src 是定義好的,已經可以用它播放靜態圖片,如果再能通過它播放動態圖片,不就解決問題啦?!

於是查看 ImageView 類的源碼,看到建構函式

public ImageView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {    //...    final TypedArray a = context.obtainStyledAttributes(                    attrs, com.android.internal.R.styleable.ImageView, defStyleAttr, defStyleRes);    Drawable d = a.getDrawable(com.android.internal.R.styleable.ImageView_src);    if (d != null) {         setImageDrawable(d);    }    //...}

有沒有很眼熟?!對,之前自訂屬性的時候用過!這裡不過把屬性路徑改了!之前我們用的是自訂的路徑 R.styleable.GifView 。

於是乎,我也想著,要是能在繼承類(MyGifView)裡面複製上段代碼,然後再用movie轉化,轉換成功說明是 gif,就用之前的方法播放,轉換失敗說明是其他格式的圖片,就交給 ImageView 自己處理!

真是好辦法!

然而,根本不能這麼用:

但是思路是對的!

通過參考《 Android PowerImageView實現,可以播放動畫的強大ImageView》

得知了可以用反射!
中心代碼:

  /**      * 通過Java反射,擷取到src指定圖片資源所對應的id。      *       * @param a 屬性群組     * @param context      * @return 返回布局檔案中指定圖片資源所對應的id,沒有指定任何圖片資源就返回0。      */      private int getResourceId(TypedArray a, Context context) {          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;      }  

之前在自訂view初始化中的代碼,我是用得到自訂屬性值的方法擷取gif的資料

int resId = typedArray.getResourceId(R.styleable.GifView_gif_src, 0); //gif_src屬性對應值

現在只需要改這一句就好啦!

//int resId = typedArray.getResourceId(R.styleable.GifView_gif_src, 0); //gif_src屬性對應值int resId = getResourceId(typedArray, context); //src屬性對應值

然後後面都不用改啦!

(但是轉換成 InputStream 的時候,還是要加一句判斷 if (resId != 0)再進行轉換)

if (resId != 0) {    InputStream iStream = getResources().openRawResource(resId); //此方法能通過資源檔id尋找到資源檔並轉化為輸入資料流    mMovie = Movie.decodeStream(iStream); //輸入資料流轉化為Movie (mMovie 為全域變數,類型 Movie)}
問題二

只支援預設的引用圖片,不能另外設定

解決思路:
從外面設定無非就是外面調用setImageResource(int resId)setImageDrawable(Drawable drawable)setImageBitmap(Bitmap bm)等這些方法去改變 ImageView 屬性 src 所對應的值!

那麼,重寫這些方法,把資源改成我們的 movie 就好啦!so easy!

首先重寫setImageResource(int resId)

@Override public void setImageResource(int resId) {    if (resId != 0) {        InputStream iStream = getResources().openRawResource(resId);        Movie movie = Movie.decodeStream(iStream);        setMovie(movie, iStream);        if (mMovie == null) {            super.setImageResource(resId);        }    } else {        super.setImageResource(resId);    }    invalidate();}

然後在外面(比如MainActivity),調用gifView.setImageResource(R.drawable.coffee)是可以顯示gif的,其他格式的圖片也可以正常顯示。

but…

出現了一個bug…

就是現在必須在xml裡面的自訂MyGifView添加預設的 src 引用 或者 backgroud 附初始值,不然會報錯崩潰,如果不想添加預設圖片,可以把background設定為透明 #00000000

報錯的原因,大概是沒設定src屬性時,調用反射int resId = getResourceId(typedArray, context);得到的 resId 也並不為0 (具體得到的是什麼我也還不知),然後進入 if 語句執行InputStream iStream = getResources().openRawResource(resId);轉換流的時候報了null 指標,導致程式崩潰。

暫時按照設定預設src或者backgroud的方法可以解決,如果廣大網友知道是什麼原因,有什麼更好的辦法解決它,懇求告知一下!

代耕……

著作權聲明:本文為博主原創文章,未經博主允許不得轉載。

【Android實戰】記錄自學自訂GifView過程,能同時支援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.