天天看點

Android自定View:可以設定寬高比例和圓角圖檔的ImageView

昨天有個朋友讓我折騰一個這樣的ImageView,

他說“我想要一個既可以圓角又可以設定寬高比的imageview”

是以我就折騰了下。

大概是這樣的

Android自定View:可以設定寬高比例和圓角圖檔的ImageView

1.attributes

這裡說一下:如果參考邊是:寬,那麼你高度的設定其實是沒有效果的

因為,代碼裡面 我直接把高度重新計算了

<declare-styleable name="SakuraImage">
   <!--參考邊-->
   <attr name="refer" format="enum">
        <enum name="寬" value="1"/>
        <enum name="高" value="2"/>
    </attr>
    <!--長寬比例-->
    <attr name="ratio" format="float"/>
    <!--圓弧度-->
    <attr name="radius" format="float"/>
</declare-styleable>
           

2.xml

<mos.kos.cache.widget.SakuraImage
    android:layout_width="200dp"
    android:layout_height="200dp"
    android:scaleType="centerCrop"
    android:src="@drawable/image"
    sakura:radius="20"
    sakura:ratio="1"
    sakura:refer="高"/>
           

3.Code

3.1.長寬按比例設定

這一步主要是在

onMeasure

裡面完成的

具體的看下面的代碼和代碼裡的注釋

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    if (ratio > 0) {
        //參考邊為:寬
        if (referEdge == 1) {
            ratioW = MeasureSpec.getSize(widthMeasureSpec);
            ratioH = (int) (ratioW * ratio);//根據寬來計算高
		//參考邊為:高
        } else {
            ratioH = MeasureSpec.getSize(heightMeasureSpec);
            ratioW = (int) (ratioH * ratio);//根據高來計算寬
        }
        //丢給父類處理
        super.onMeasure(MeasureSpec.makeMeasureSpec(ratioW, MeasureSpec.EXACTLY),
            MeasureSpec.makeMeasureSpec(ratioH, MeasureSpec.EXACTLY));
    } else {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }
    Logger.v("寬高1:ratioW=" + ratioW + ",ratioH=" + ratioH);
}
           

3.2.設定帶圓弧的圖檔

這裡稍微麻煩一點,不過主要還是在

onDraw

裡面處理的
  • 1.先找到圖檔的錨點
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    super.onSizeChanged(w, h, oldw, oldh);
    rectF.top = 0;
    rectF.left = 0;
    rectF.right = getWidth(); // 寬度
    rectF.bottom = getHeight(); // 高度
    setBitmapShader();
}
           
  • 2.關鍵的一步:設定圖檔的透明區域Shader
下面是一段僞代碼,把這一塊的關鍵點都整到一起的
//先整一個畫筆
Paint bmpPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG);
bmpPaint.setStyle(Paint.Style.FILL);
bmpPaint.setAntiAlias(true);
        
//這裡的bmp是搞到的Bitmap圖檔
BitmapShader bmpShader = new BitmapShader(bmp, 
Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
//bmpShader 就是圓弧所裁剪調的透明區域
bmpPaint.setShader(bmpShader);

//這個矩陣主要是對裁剪後的圖檔做縮放、還有位置的處理
matrix.set(null);//設為預設值,固定為CENTER_CROP
// 縮放
float scale = Math.max(getWidth() * 1f / bmp.getWidth(), getHeight() * 1f / bmp.getHeight());
// 居中
float dx = (getWidth() - bmp.getWidth() * scale) / 2;
float dy = (getHeight() - bmp.getHeight() * scale) / 2;
matrix.setScale(scale, scale);
matrix.postTranslate(dx, dy);
bmpShader.setLocalMatrix(matrix);
invalidate();//重新整理
           
  • 3.最後繪制

這裡我踩了個坑,記錄一下:

繪制的時候

最好

用Canvas 的路徑繪制

canvas.drawPath()

,就是第1步打的那4個錨點,這樣也是最簡單的

我之前嘗試過直接用畫布來繪制矩形

canvas.drawRoundRect(

或者繪制圖形

canvas.drawBitmap(

雖然也成功了,但是效果不怎麼理想。

@Override
protected void onDraw(Canvas canvas) {
    if (bmp != null) {
        path.reset();
        path.addRoundRect(rectF, radius, radius, Path.Direction.CW);
        canvas.drawPath(path, bmpPaint);
    }
}
           

最後丢再幾張效果圖

  • 1.寬高比為1的時候
    Android自定View:可以設定寬高比例和圓角圖檔的ImageView
  • 2.這裡是以寬為參考邊
    Android自定View:可以設定寬高比例和圓角圖檔的ImageView
  • 3.這裡是以高為參考邊
    Android自定View:可以設定寬高比例和圓角圖檔的ImageView

源碼下載下傳