ImageView之ScaleType詳解及拓展

ImageView中有個很重要也很經常使用的屬性android:scaleType,相信你們都應該不陌生,主要用於控制圖片在ImageView中顯示的樣式,好比顯示大小、顯示位置、顯示內容區域。固然也能夠在代碼中設置: setScaleType(ImageView.ScaleType.xxx); ScaleType的取值一共有8種:fitCenterfitEndcentercenterCropcenterInsidematrixfitXYfitStart。其中默認值是fitCenter。 咱們先來看比較簡單的center吧,一個60dp*40dp的ImageView(爲了顯示效果,背景設成藍色)裏面放了張20dp*20dp的圖片。上圖看看效果:java

center的含義是:保持原圖的大小,顯示在ImageView的中心。當原圖的size大於ImageView的size,超過部分裁剪處理。 再來看比較「暴力」的fitXYandroid

fitXY的含義:拉伸顯示圖片,不保持原比例,填滿ImageView.嗯,果真很暴力。canvas

嗯,接下來咱們...什麼?難道你覺得我要把剩下的6種樣式都貼張圖出來,而後愉快地水一篇博客嗎? ide

因此接下來我放大招了,開始分析源碼!工具

詳解

上面設置了這麼多種ScaleType,那麼最終生效的位置在哪呢?答案就在 configureBounds()方法裏,限於篇幅我貼了上面兩種樣式的法,其餘的樣式實現也都相似。post

private void configureBounds() {
        //圖片寬高
        final int dwidth = mDrawableWidth;
        final int dheight = mDrawableHeight;
         //Imageview寬高
        final int vwidth = getWidth() - mPaddingLeft - mPaddingRight;//
        final int vheight = getHeight() - mPaddingTop - mPaddingBottom;

        final boolean fits = (dwidth < 0 || vwidth == dwidth)
                && (dheight < 0 || vheight == dheight);

        if (dwidth <= 0 || dheight <= 0 || ScaleType.FIT_XY == mScaleType) {
         
            mDrawable.setBounds(0, 0, vwidth, vheight);
            mDrawMatrix = null;
        } else {
            mDrawable.setBounds(0, 0, dwidth, dheight);
             if (ScaleType.MATRIX == mScaleType) {//樣式應用自定義MATRIX
                if (mMatrix.isIdentity()) {
                    mDrawMatrix = null;
                } else {
                    mDrawMatrix = mMatrix;
                }
            } 
         if (ScaleType.CENTER == mScaleType) {
                // Center bitmap in view, no scaling.
                mDrawMatrix = mMatrix;
                mDrawMatrix.setTranslate(Math.round((vwidth - dwidth) * 0.5f),
                                         Math.round((vheight - dheight) * 0.5f));
            } 

複製代碼

能夠看到最終的實現用到了Drawable類和Matrix類的方法。前者你們都很熟悉,就是咱們設置的要顯示的圖片,而Matrix叫作矩陣,是一個專門用來處理圖形變換中的重要工具類,熟悉自定義View的同窗應該對它不陌生,canvas.setMatrix(matrix)能夠作出不少獨特效果來。而咱們今天的主角是ImageView,因此沒錯imageView也有這個方法:spa

imageView.setImageMatrix(matrix)

經過上述方法咱們就能將本身定義的Matrix應用到ImageView中。能夠看到源碼,要使這個方法生效,ScaleType必定要設爲MATRIX,否則執行完本身的變換後仍是會執行樣式本身的變換,至關於沒執行。code

FIT_XY的實現很簡單,就用到了setBounds(int left, int top, int right, int bottom),這個四參數指的是drawable的繪製區域。 center用到了postTranslate(float dx, float dy),將Drawable移到ImageView中間,由於沒有其餘處理,圖片若是比ImageView大,那麼多餘的區域就會被裁剪掉,不顯示了。cdn

拓展

說了這麼多來個小栗子來加深理解吧: 仍是上面那張圖片,scaleType設爲matrix,咱們再加一個按鈕,點擊事件以下:blog

int m = 20;
    //平移
    private void onClick(View v) {
        Matrix matrix = new Matrix();
        matrix.postTranslate(m, m);
        imageView.setImageMatrix(matrix);
        m = m + 3;
    }
複製代碼

來看看效果:

經過改變postTranslate參數的值咱們就能改變圖片在View中繪製的起始位置。 固然不會這麼簡單。Matrix還有其餘方法: postRotate(float degrees, float px, float py)//旋轉: 咱們仿照center的處理將圖片移到ImageView中心,而後進行旋轉:

int m = 20;
    //旋轉
    private void onClick(View v) {
       Matrix matrix = new Matrix();
        int width = imageView.getDrawable().getIntrinsicWidth();
        int height = imageView.getDrawable().getIntrinsicHeight();
        final int vwidth = imageView.getWidth();
        final int vheight = imageView.getHeight();
        matrix.setTranslate(Math.round((vwidth - width) * 0.5f),
                Math.round((vheight - height) * 0.5f));
        matrix.postRotate(m, vwidth * 0.5f, vheight * 0.5f);
        imageView.setImageMatrix(matrix);
        m = m + 3;
    }
複製代碼

看看效果:

還有一種是錯切,將圖片的形狀改變: void setSkew(float kx, float ky) 實際用到的比較少,就不貼代碼了,直接看效果吧:

總結

說了這麼多,這篇文章就是給你們介紹了android:scaleType的自定義用法,當遇到Imageview預設的顯示模式不能知足咱們現有需求的時候(好比我就遇到原圖按照原來的大小居底部顯示,若是原圖的大小超過了ImageView的大小,那麼就剪裁掉多餘部分,保留底部,和centerCrop裁剪四周有所不一樣),咱們就能夠動態設置本身的matrix來自定義顯示效果。固然若是你常常要用到這種方式的時候,能夠繼承Imageview,封裝這些自定義樣式。

相關文章
相關標籤/搜索