ImageView的高級使用技巧

http://mp.weixin.qq.com/s/Rg213sQQ2ge4ARRzzxH4pw

看到一篇很使用的文章,想記錄下來,已標註轉載,莫怪!

mageView是大家用的非常多的控件之一,其相比於其他控件多了一個src屬性。我們平時在其中顯示的圖片往 往需要跟隨外部的變化切換圖片,這個時候我們一般會選擇用多張圖片來實現,如果變化後的圖片和原圖很類似,只是更改了顏色我們完全沒有必要去弄張新圖片 來,今天就來教大家如何實現這種情況的需求。


如何使用Imageview的問題我就不再多說了,現在我們要實現下面這樣一個Imageview:



一個圓形的Imageview,但是圓形的圖片顏色和中間的那個src圖片和其顏色都是可以變化的,比如這個是一個安全類的app,在掃描到有病毒的時候會 根據病毒的類型變化成不同的樣式。現在我們假定有3中狀態:無病毒、低風險病毒、高風險病毒,分別對於上面的三個狀態。對於這樣一個情況,你可能會使用多 張圖片來實現,這樣帶來的後果就是增加項目的工作量和app的大小。我們如何使用最少的圖片來實現呢?



使用background加src來實現

你可能最先想到的是分兩個部分,第一個是圓形的純色部分使用背景來實現,中間使用圖片來實現。我們照着這個思路來實現第一種效果,打開手機開發者選項裏面的過度繪製,來看看層級:


過度繪製的顏色從低到高分別是:藍色-綠色-淡紅-紅色,分別對應x1-x2-x3-x4的繪製次數。很明顯我們這裏存在兩層的繪製問題。這麼我們的佈局文件是這樣的:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <ImageView
        android:id="@+id/imgv_toHint"
        android:layout_width="200dp"
        android:layout_height="200dp"
        android:layout_centerInParent="true"
        android:background="@drawable/imgv_bg"
        android:padding="30dp"
        android:scaleType="centerInside"
        android:src="@drawable/center_icon" />
</RelativeLayout>


這裏的Imageview分別設置了一個背景和一個圖片,那麼我們如何根據狀態來設置對應的狀態呢?來看java代碼部分:

  imgv_toHint = (ImageView) findViewById(R.id.imgv_toHint);
        LightingColorFilter bFilter = new LightingColorFilter(Color.TRANSPARENT, getResources().getColor(R.color.imgv_bg_yellow));
        imgv_toHint.getBackground().setColorFilter(bFilter);
        LightingColorFilter iFilter = new LightingColorFilter(Color.TRANSPARENT, getResources().getColor(R.color.src_bg_second));
        imgv_toHint.getDrawable().setColorFilter(iFilter);


運行效果:



運行之後就可以看到和第二種效果是一樣的,這種方式有點略屌。使用了一個ColorFilter來對圖像進行處理,其中ColorFilter是一個抽象的類,不能直接來使用,需要使用其子類,他的子類有3個:  LightingColorFilter、 ColorMatrixColorFilter、PorterDuffColorFilter;具體的使用我這裏就不過多的展開了,有興趣的同學可以深入的學習下,對處理圖片是非常有用的。當然還可以使用圖片中的各種tint屬性來實現,這裏就不再具體的演示如何實現了。




使用layer-list加level-list來實現

layer-list:其實質是給其中定義的item中的圖片按照順序一張張的繪製上去,默認是繪製一樣的大小,但是我們可以指定偏移量來達到不一樣的大小。

level-list:其實質是定義多張圖片對應多個狀態(使用int值來表示),在代碼中我們設置不同的狀態來控制顯示不同的圖片。


我們來看xml中的代碼:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <ImageView
        android:id="@+id/imgv_toHint"
        android:layout_width="200dp"
        android:layout_height="200dp"
        android:layout_centerInParent="true"
        android:src="@drawable/level_icon" />
</RelativeLayout>


來看看level_icon文件:

<?xmlversion="1.0" encoding="utf-8"?>
<level-list
xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:drawable="@drawable/layer_bg_first"
        android:maxLevel="1"/>
    <item
        android:drawable="@drawable/layer_bg_secend"
        android:maxLevel="2"/>
    <item
        android:drawable="@drawable/layer_bg_third"
        android:maxLevel="3"/>
</level-list>


來看看其中一個layer-list:

<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:width="160dp"
        android:height="160dp"
        android:drawable="@drawable/imgv_bg_first" />
    <item
        android:width="100dp"
        android:height="100dp"
        android:drawable="@drawable/center_icon_first"
        android:left="30dp"
        android:top="30dp" />
</layer-list>


在代碼中我們可以這樣使用:

  imgv_toHint = (ImageView) findViewById(R.id.imgv_toHint);
        imgv_toHint.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                imgv_toHint.getDrawable().setLevel(level = level >= 3 ? 1 : ++level);
            }
        });


獲取到drawable對象,然後設置其level系統就自動更換圖片了


這 種方式可以做到最少的代碼來控制圖片的更換,用一個變量來控制圖片自動顯示,使代碼非常的整潔,但是其也有一個不好的地方就是可能會增加圖片的數量。具體 的取捨需要根據具體的項目來考慮。當然我們也可以結合tint屬性和colorfilter來減少圖片的數量,但是又增加了代碼的數量。這種方式也存在過 度繪製的問題。

說了這麼多,過度繪製的問題還是沒能解決,其根本原因是我們還沒有給他們做到一張圖片來顯示。如果要做到一張圖片顯示又不 過多的引入圖片的數量,我們可以使用一個bitmap對象來繪製一張圖片然後設置到imageview上面去。因爲bitmap在繪製的時候不管是多麼復 雜,其也算是一層view。利用這個思路,我們來減少過度繪製的問題。




去掉過度繪製的問題

這種方式就不能夠在xml文件中直接設置src圖片了,因爲前面我們知道這種方式設置的話是行不通的。那麼我們只能在代碼中來設置,我們可以給資源文件中的layer-list轉化爲一張圖片,然後設置到imageview上面,這樣的話多了一層轉化少了一層繪製。

來看java中的代碼:

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        imgv_toHint = (ImageView) findViewById(R.id.imgv_toHint);
        Drawable src = getDrawable(R.drawable.layer_bg_secend);
        imgv_toHint.setImageBitmap(drawable2Bmp(src));
    }
    private Bitmap drawable2Bmp(Drawable drawable) {
        Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(),
                drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565);
        Canvas canvas = new Canvas(bitmap);
        drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
        drawable.draw(canvas);
        return bitmap;
    }


這裏我們定義了一個drawable轉爲Bitmap的方法,給資源中的drawable對象轉化爲一張bitmap圖片,然後設置到imageview上面。


發佈了6 篇原創文章 · 獲贊 2 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章