1. 程式人生 > >android開發萬能圓角ImageView

android開發萬能圓角ImageView

轉載請註明出處:http://blog.csdn.net/sw950729/article/details/52037798
本文出自:馬雲飛的部落格
本篇文章已授權微信公眾號 guolin_blog (郭霖)獨家釋出
最近一兩個月沒事做,然後就開始封裝一些東西,昨天上司讓我幫他做的圓角圖片。思路自然是和網上的demo不一樣的。
網上demo的效果:
這裡寫圖片描述
差不多應該是這樣的,但是容易出一些問題,比如你的圖片本身就是個圓角?又或者圖片太大,你想縮小顯示,但出現顯示內容不全?
我想實現的效果是這樣的:
這裡寫圖片描述
圖畫的較醜,見諒。
意思就是以他的寬高的最小值,為正方形的寬給他做圓角,當然長方形也可以的,因為我試了效果,沒有問題,你們到時候可以自己嘗試。
參考文章:

http://blog.csdn.net/lmj623565791/article/details/41967509
這是翔神的文章,不過他的效果,並不是我想要的,因為,他的繪圖是從(0,0)點然後擷取寬高繪圖,並不是我想要的重中間擷取,然後繪圖。
大體程式碼和他的差不多。不過依舊刪除了一些無用的程式碼(哈哈,這個我抄程式碼的特性,沒用放著幹嘛,礙眼。)
好了下面上程式碼:
初始化:

  private void inital(Context context, AttributeSet attrs) {
        matrix = new Matrix();
        paint = new
Paint(); //無鋸齒 paint.setAntiAlias(true); TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.RoundAngelImageView); //如果沒設定圓角的預設值,在這設定預設值為10dp BorderRadius=dp2px(BODER_RADIUS_DEFAULT); // 預設為Circle type = array.getInt(R.
styleable.RoundAngelImageView_type, TYPE_CIRCLE); array.recycle(); }

這邊我用到了dp2px。這個就是將dp轉換成px。網上程式碼一堆~~~~:

 public int dp2px(int dp) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
                dp, getResources().getDisplayMetrics());
    }

既然繼承了ImageView,少不了的自然是onmeusre方法:

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        //如果型別是圓形,則強制改變view的寬高一致,以小值為準
        if (type == TYPE_CIRCLE) {
            width = Math.min(getMeasuredWidth(), getMeasuredHeight());
            radius = width / 2;
            setMeasuredDimension(width, width);
        }
    }

設定bitmapshader的程式碼如下:

  Drawable drawable = getDrawable();
        if (drawable == null) {
            return;
        }
        //將drawable轉化成bitmap物件
          Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap();
        if (bitmap == null) {
            return;
        }
        // 將bmp作為著色器,就是在指定區域內繪製bmp
        BitmapShader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
        float scale = 1.0f;
        int viewwidth = getWidth();
        int viewheight = getHeight();
        int drawablewidth = bitmap.getWidth();
        int drawableheight = bitmap.getHeight();
        float dx = 0, dy = 0;
        if (type == TYPE_CIRCLE) {
            // 拿到bitmap寬或高的小值
            int size = Math.min(bitmap.getWidth(), bitmap.getHeight());
            scale = width * 1.0f / size;

        } else if (type == TYPE_ROUND) {
            // 如果圖片的寬或者高與view的寬高不匹配,計算出需要縮放的比例
            // 縮放後的圖片的寬高,一定要大於我們view的寬高;所以我們這裡取大值
            scale = Math.max(getWidth() * 1.0f / bitmap.getWidth(), getHeight()
                    * 1.0f / bitmap.getHeight());
        }

        if (drawablewidth * viewheight > viewwidth * drawableheight) {
            dx = (viewwidth - drawablewidth * scale) * 0.5f;
        } else {
            dy = (viewheight - drawableheight * scale) * 0.5f;
        }

        // shader的變換矩陣,我們這裡主要用於放大或者縮小
        matrix.setScale(scale, scale);
        matrix.postTranslate((int) (dx + 0.5f), (int) (dy + 0.5f));
        // 設定變換矩陣
        BitmapShader.setLocalMatrix(matrix);
        // 設定shader
        paint.setShader(BitmapShader);

如果有人看了前面我給的參考文章,那麼,你可以發現,我把這個類的程式碼進行了改動,差不多就是把圖片的起點座標從(0,0)移動到了我想要的起點。
至於為什麼,我們開啟ImageView的原始碼,找到Center_Crop。這快程式碼的意思差不多是將圖片居中把。
來,我們上原始碼:

if (ScaleType.CENTER_CROP == mScaleType) {
                mDrawMatrix = mMatrix;

                float scale;
                float dx = 0, dy = 0;

                if (dwidth * vheight > vwidth * dheight) {
                    scale = (float) vheight / (float) dheight; 
                    dx = (vwidth - dwidth * scale) * 0.5f;
                } else {
                    scale = (float) vwidth / (float) dwidth;
                    dy = (vheight - dheight * scale) * 0.5f;
                }

                mDrawMatrix.setScale(scale, scale);
                mDrawMatrix.postTranslate((int) (dx + 0.5f), (int) (dy + 0.5f));

他怎麼計算的scale我們別管它,重點是如何計算他的dx和dy。
這裡我就舉個例子來計算。drawable的寬和高是(300,200)。我要繪製的view的寬高是(200,200)。按照 我的思路繪圖是從(50,0)到(250,250),而不是(0,0)到(200,200)。
話不多說。我們看原始碼的計算:

dw*vh=300*200;
dh*vw=200*200;
/*
此時我們需要得到dx的值,dy預設為0,我的起點是(50,0),似乎是對的?我們接著計算
*/
  scale = Math.max(getWidth() * 1.0f / bitmap.getWidth(), getHeight()* 1.0f / bitmap.getHeight());
/**
那麼我們的scale=math.max(200/300,200/200)=1
*/

  dx = (vwidth - dwidth * scale) * 0.5f;
  /**
  那麼dx=(200-300*1)*05=-50,和我想要的50越來越近的,那麼為什麼他postTranslate的時候是(-50,0)而不是(50,0)?
  */

我們畫圖,來說明這一切,看完圖,你或許就懂了。
這裡寫圖片描述
紅色框是我們之後的,那這樣,1這塊區域可以理解成沒了。銷燬了。但是實際的效果是這樣:
這裡寫圖片描述
圓形好像看似沒什麼問題,那你們自己看圓角圖片左邊是不是被拉伸,這個拉伸距離應該剛好是我們之前計算得到的50dp。因為上圖的1那塊已經不存在了,所以你畫圖的時候那快距離就是拉伸的距離。現在我們看看-50dp的圖。
這裡寫圖片描述
1的部分被移出去了。但他依然是存在的,所以繪製的圖是不會出現任何拉伸的。perfect~~~。
屬性配置完了,剩下的就是ondraw方法咯。很簡單,程式碼如下:

protected void onDraw(Canvas canvas) {
        if (getDrawable() == null) {
            return;
        }
        setBitmapShader();
        if (type == TYPE_ROUND) {
            canvas.drawRoundRect(rectF, BorderRadius, BorderRadius,
                    paint);
        } else {
            canvas.drawCircle(radius, radius, radius, paint);
        }
    }

當然你也得考慮到onsizechanged的時候,程式碼也不多:

 protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        // 圓角圖片的範圍
        if (type == TYPE_ROUND)
            rectF = new RectF(0, 0, getWidth(), getHeight());
    }

好了。在這邊我補上attrs屬性:

 <attr name="borderRadius" format="dimension" />
    <attr name="type">
        <enum name="circle" value="0" />
        <enum name="round" value="1" />
    </attr>


    <declare-styleable name="RoundAngelImageView">
        <attr name="borderRadius" />
        <attr name="type" />
    </declare-styleable>

現在。一個完美的,萬能的圓角ImageVIew就解決了。不過好像還缺點什麼,對了。自行修改圓角,自行修改型別,加上這個才算完美。
附上程式碼:

  //修改圓角大小
    public void setBorderRadius(int borderRadius) {
        int px = dp2px(borderRadius);
        if (this.BorderRadius != px) {
            this.BorderRadius = px;
            invalidate();
        }
    }

    //修改type
    public void setType(int type) {
        if (this.type != type) {
            this.type = type;
            if (this.type != TYPE_ROUND && this.type != TYPE_CIRCLE) {
                this.type = TYPE_CIRCLE;
            }
            requestLayout();
        }

    }

現在我們新建個xml。放2張圖片。一個圓角,一個圓形,先看看效果如何:

  <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <sw.angel.roundangelimageview.RoundAngelImageView
            android:layout_width="200dp"
            android:layout_height="200dp"
            android:layout_marginTop="30dp"
            android:layout_gravity="center"
            android:src="@drawable/myimage" />

        <sw.angel.roundangelimageview.RoundAngelImageView
            android:layout_width="200dp"
            android:layout_height="200dp"
            android:layout_marginTop="30dp"
            android:layout_gravity="center"
            android:src="@drawable/mine"
            sw:type="round" />
    </LinearLayout>

多張圖片在外層加一個scrollview。好了。我們來看一下效果:
這裡寫圖片描述
完美~~
圓角大小自行修改。型別自行修改。好了。今天主要內容就這麼多把。
整理了2個多小時~也是夠夠的。
感覺還有一些常用的控制元件,帶刪除鍵的edittext。以及可見不可見的edittext。似乎不難。(有空在研究)。
最後,問你們個問題,忙活了一天沒解決。你們用android.suport.design包是怎麼用的。為什麼我rebuild之後是這樣。
這裡寫圖片描述
這是什麼鬼。不懂。
好了,今天就說到這邊把,能解決我問題的請留言,謝謝。我的android交流群:232748032。歡迎加入。

相關推薦

android開發萬能圓角ImageView

轉載請註明出處:http://blog.csdn.net/sw950729/article/details/52037798 本文出自:馬雲飛的部落格 本篇文章已授權微信公眾號 guolin_blog (郭霖)獨家釋出 最近一兩個月沒事做,然後就開始封裝一

Android自己定義圓角ImageView

play setfill recycle fig wid art app util clear 我們常常看到一些app中能夠顯示圓角圖片。比方qq的聯系人圖標等等,實現圓角圖片一種辦法是直接使用圓角圖片資源,當然假設沒有圓角圖片資源。我們也能夠自己通過程序實現的,以下介

Android開發萬能Utils(工具大全)

AndroidUtils Android開發不得不收藏的Utils 之前寫這篇文章主要是專案應用到的Utils,發現已經有一個更全面的開源庫總結,所以還是非常震驚可以總結的這麼全面,在此我準備重新梳理一遍~(一共兩個庫) 第一個庫: Gradle: impleme

Android開發——Java更改ImageView控制元件src屬性

Android開發——Java更改ImageView控制元件src屬性 一、ImageView控制元件 1、先在drawable資料夾中放置一個名叫icon的圖片,再在xml檔案中建立一個ImageView <ImageView android:id="@+

這才是真正的萬能圓角ImageView

本文已授權我的公眾號:我就是馬雲飛 獨家釋出 不知道有沒有人記得我去年寫過一個圓角的imageview。不知道的可以先去看看:萬能圓角imagview,本文是基於上一篇的內容進行新增以及修改的。不然直接看這篇可能會有點懵。 前言 我為什麼要二次封裝?最

Android開發學習之ImageView手勢拖拽、縮放、旋轉

           在Android應用中,圖片隨手勢的拖拽、縮放、旋轉在很多場景中都會用到,今天我們要做的就是在ImageView的基礎上實現一個可以拖拽、縮放、轉轉的TouchView。              一、實現原理              OnTouc

Android自定義圓角ImageView 支援網路圖片

         先看下效果圖                        我們再來看一張CSDN的圓角圖片                           從佈局可以看出csdn app 的頭像也是圓角的Image,但可以看到,有明顯的毛刺感,不知道是csdn

Android開發教程--設定ImageView圖片的顯示比例

為適應不同螢幕的手機,ImageView圖片的顯示比例,可以使用android:scaleType屬性來處理,處理方式的有以下幾種: 1、在xml配置中使用:android:scaleType="centerCrop" 2、在程式碼中使用:   imageView.setS

android 自定義圓角ImageView以及鋸齒的處理

看到很多人開發過程中要使用圓角圖片時,解決方法有: 1.重新繪製一張圖片 2.通過佈局來配置 3.通過重寫View來實現 其中1,2在這裡就不講了,重點講講方法三的實現。實現一:通過擷取畫布一個圓形區域與圖片的相交部分進行繪製,缺點:鋸齒明顯,設定Paint,Canvas抗

Android自定義圓角ImageView

我們經常看到一些app中可以顯示圓角圖片,比如qq的聯絡人圖示等等,實現圓角圖片一種辦法是直接使用圓角圖片資源,當然如果沒有圓角圖片資源,我們也可以自己通過程式實現的,下面介紹一個自定義圓角ImageView的方法: package com.yulongfei.imagev

Android開發之自定義圓角矩形圖片ImageView

android中的ImageView只能顯示矩形的圖片,這樣一來不能滿足我們其他的需求,比如要顯示圓角矩形的圖片,這個時候,我們就需要自定義ImageView了,其原理就是首先獲取到圖片的Bitmap,然後進行裁剪對應的圓角矩形的bitmap,然後在onDraw()進行繪製

Android開發控制元件-VarietyImageView(百變ImageView,可以根據要求指定哪個角是圓角,哪個角是直角)

ImageView相信是Android開發人員再熟悉不過的一個控制元件了,在一般情況下基本的ImageView也都能滿足我們的開發需求,但相信大家也都遇到過ImageView無法滿足實際需求的情況,這次我就遇到了,先來看下需求: 1)可以設定成圓形ImageView

Android開發圓形ImageView實現

radi appcompat con code roi contex draw ttr extends 1、自定義屬性,在value文件夾下新建attrs文件,聲明如下屬性 <declare-styleable name="CircleImageView">

Android開發 - ImageView加載Base64編碼的圖片

base64編碼 [] 地址 加載本地 .cn ... ear 情況 ring 在我們開發應用的過程中,並不是所有情況下都請求圖片的URL或者加載本地圖片,有時我們需要加載Base64編碼的圖片。這種情況出現在服務端需要動態生成的圖片,比如: 二維碼 圖形驗證碼 ...

Android 開發:(四)Button圓角實現

本節學習button的圓角實現: 利用上節登入button示例: 1.效果對比: <Button android:layout_width="match_parent" android:layout_height="45dp

android開發:如何動態設定ImageView和button的背景

改變ImageView的背景 Drawable drawable = ResourcesCompat.getDrawable(getResources(), R.drawable.has_authorization, null); imv_authorization.setBac

Android開發 ImageView上繪製旋轉圓環(透明度不同的旋轉圓環,利用canvas drawArc實現)

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

Android開發 - ImageView載入Base64編碼的圖片

在我們開發應用的過程中,並不是所有情況下都請求圖片的URL或者載入本地圖片,有時我們需要載入Base64編碼的圖片。這種情況出現在服務端需要動態生成的圖片,比如: 二維碼 圖形驗證碼 ... 這些應用場景有個共同點就是,這些圖片都是由伺服器動態生成,並不需要生成後儲存成檔案再返回給客戶端

Android開發--圓角按鈕和繪製直線的實現

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

Android開發學習筆記(十二)基礎UI控制元件之ImageView、CheckBox、RadioButton

一、ImageView:直接繼承自View,它的作用是在介面上顯示Drawable物件。 ImageView在佈局檔案(如main_activity.xml)中常用的屬性 有 scaleType ,s