1. 程式人生 > >Android圓形圖片不求人,自定義View實現(BitmapShader使用)

Android圓形圖片不求人,自定義View實現(BitmapShader使用)

在很多APP當中,圓形的圖片是必不可少的元素,美觀大方。本文將帶領讀者去實現一個圓形圖片自定View,力求只用一個Java類來完成這件事情。

一、先上效果圖


二、實現思路

  • 在定義View 的onMeasure()方法裡設定View的寬高相等,應該取寬高中的最小值。
  • 在自定義View的onDraw()裡面使用畫筆paint結合BitmapShaper畫出一個圓形區域。
  • 上述兩步已經可以實現一個圓形圖片,但是如果圖片大於View的設定的寬高,則只會繪製左上角的局域,內容顯示不完全(如下圖)。因此,還應該做好圖片的縮放。

三、具體實現

1.新建一個java類 CircleImageView繼承 ImageView,這個是完整的程式碼。

public class CircleImageView extends ImageView {

    private Paint mPaint; //畫筆

    private int mRadius; //圓形圖片的半徑

    private float mScale; //圖片的縮放比例

    public CircleImageView(Context context) {
        super(context);
    }

    public CircleImageView(Context context, AttributeSet attrs) {
        super
(context, attrs); } public CircleImageView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); //因為是圓形圖片,所以應該讓寬高保持一致
int size = Math.min(getMeasuredWidth(), getMeasuredHeight()); mRadius = size / 2; setMeasuredDimension(size, size); } @Override protected void onDraw(Canvas canvas) { mPaint = new Paint(); Bitmap bitmap = drawableToBitmap(getDrawable()); //初始化BitmapShader,傳入bitmap物件 BitmapShader bitmapShader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); //計算縮放比例 mScale = (mRadius * 2.0f) / Math.min(bitmap.getHeight(), bitmap.getWidth()); Matrix matrix = new Matrix(); matrix.setScale(mScale, mScale); bitmapShader.setLocalMatrix(matrix); mPaint.setShader(bitmapShader); //畫圓形,指定好中心點座標、半徑、畫筆 canvas.drawCircle(mRadius, mRadius, mRadius, mPaint); } //寫一個drawble轉BitMap的方法 private Bitmap drawableToBitmap(Drawable drawable) { if (drawable instanceof BitmapDrawable) { BitmapDrawable bd = (BitmapDrawable) drawable; return bd.getBitmap(); } int w = drawable.getIntrinsicWidth(); int h = drawable.getIntrinsicHeight(); Bitmap bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(bitmap); drawable.setBounds(0, 0, w, h); drawable.draw(canvas); return bitmap; } }

2. onMeasure()方法裡面,計算好寬高

因為是圓形圖片,所以應該讓寬高保持一致,取測量尺寸寬高中的最小值最為最終結果。

@Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        //因為是圓形圖片,所以應該讓寬高保持一致
        int size = Math.min(getMeasuredWidth(), getMeasuredHeight());
        mRadius = size / 2;

        setMeasuredDimension(size, size);
    }

3. onDraw()方法裡面畫出圓形圖片,注意看註釋,很詳細。

@Override
    protected void onDraw(Canvas canvas) {

        mPaint = new Paint();
        Bitmap bitmap = drawableToBitmap(getDrawable());

        //初始化BitmapShader,傳入bitmap物件
        BitmapShader bitmapShader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);

        //計算縮放比例
        mScale = (mRadius * 2.0f) / Math.min(bitmap.getHeight(), bitmap.getWidth());

        Matrix matrix = new Matrix();
        matrix.setScale(mScale, mScale);
        bitmapShader.setLocalMatrix(matrix);


        mPaint.setShader(bitmapShader);

        //畫圓形,指定好中心點座標、半徑、畫筆
        canvas.drawCircle(mRadius, mRadius, mRadius, mPaint);
    }

4. 上一步中的將drwable轉換為bitmap的方法。

//寫一個drawble轉BitMap的方法
    private Bitmap drawableToBitmap(Drawable drawable) {
        if (drawable instanceof BitmapDrawable) {
            BitmapDrawable bd = (BitmapDrawable) drawable;
            return bd.getBitmap();
        }
        int w = drawable.getIntrinsicWidth();
        int h = drawable.getIntrinsicHeight();
        Bitmap bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        drawable.setBounds(0, 0, w, h);
        drawable.draw(canvas);
        return bitmap;
    }

四、使用該自定義View

1. 佈局檔案裡面使用,此處使用了斯嘉麗的美圖


<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.roundimage.MainActivity"
    >

    <com.roundimage.CircleImageView
        android:id="@+id/image1"
        android:layout_width="200dp"
        android:layout_height="200dp"
        android:layout_centerInParent="true"
        android:scaleType="centerCrop"
        android:src="@drawable/beauty"
        />
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/image1"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="10dp"
        android:text="斯嘉麗·約翰遜"
        android:textColor="#333333"
        android:textSize="17sp"
        />
</RelativeLayout>

2. 各種效果圖,用於驗證適應性

  • 尺寸都指定為200dp
   android:layout_width="200dp"
   android:layout_height="200dp"

  • 尺寸都指定為100dp
   android:layout_width="100dp"
   android:layout_height="100dp"

  • 尺寸都指定不一樣,一個150,一個400
   android:layout_width="100dp"
   android:layout_height="200dp"

  • 尺寸設定為wrap_content
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"


五、總結

實現圓形圖片有很多種方法:

  • 可以使用一些開源框架如Fresco,這個可以參考本人的另一篇部落格 Fresco圖片框架簡介及使用

  • 笨辦法,讓視覺給到一張圓形圖片(如果每張圖都需要處理,可能她會打死你)

  • 笨辦法,用一個view在上面擋住(這個我寫的自己都笑了)

  • 自定義View,就如本文介紹的。

  • 自定義Drawble,這個和自定義view可以相互補充。

總之,如果讀者有需要圓形圖的,可以把這個copy一下自己用,就一個類,簡單精巧。

如果覺得本文對你有幫助,請關注、留言、點讚我,謝謝!