1. 程式人生 > >Canvas擦出部分割槽域的實現(不擦出背景)

Canvas擦出部分割槽域的實現(不擦出背景)

開發中遇到了如下佈局的實現

這個圓形頭像可以使用

但是圓形頭像底部弓形的view卻不太好實現

最開始想使用Drawable底部設定圓角來實現,可是效果卻不怎麼理想,不能完美的與頭像對齊

後來想到可以使用Canvas,畫出一個圓形,然後剪裁掉上面一塊矩形區域

從網上找到的方法大概都如下程式碼所示

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.*;
import android.os.Build;
import android.util.AttributeSet;
import android.view.View;
import androidx.annotation.Nullable;
import androidx.annotation.Px;
import androidx.annotation.RequiresApi;

public class FractionCircleView extends View {
    public FractionCircleView(Context context) {
        super(context);
    }

    public FractionCircleView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public FractionCircleView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    public FractionCircleView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
    }
   
   @Override
    protected void onDraw(Canvas canvas) {

        //建立畫筆
        Paint paint = new Paint();
        paint.setAntiAlias(true);
        paint.setColor(Color.parseColor("#9e00a0e9"));

        float size = Math.min(getMeasuredWidth(),getMeasuredHeight());

        float radius = size/2;
        //繪製圓形drawCircle(float cx, float cy, float radius, @NonNull Paint paint)
        // 引數含義依次是 cx : 中心點在佈局中的 x 軸位置, cy :中心點在佈局中 y 軸位
        // 置,radius :半徑 , paint :畫筆                                         
        canvas.drawCircle(getMeasuredWidth()/2,getMeasuredHeight()/2,radius,paint);


        canvas.save();
        //設定裁剪區域,設定完成之後Canvas會在裁剪區域繪製
        canvas.clipRect(0,0,getMeasuredWidth(), (int) (getMeasuredHeight()*0.7));
        //Canvas 擦除顏色
        canvas.drawColor(Color.TRANSPARENT,PorterDuff.Mode.CLEAR);
        canvas.restore();

    }
}

這樣做雖然實現了底部弓形的view,但是會導致view的背景整個被擦除,包括view後面的父佈局都會變成黑色

應該改成下面的方式

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.*;
import android.os.Build;
import android.util.AttributeSet;
import android.view.View;
import androidx.annotation.Nullable;
import androidx.annotation.Px;
import androidx.annotation.RequiresApi;

public class FractionCircleView extends View {
    public FractionCircleView(Context context) {
        super(context);
    }

    public FractionCircleView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public FractionCircleView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    public FractionCircleView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
    }

    @Override
    protected void onDraw(Canvas canvas) {

        //建立畫筆
        Paint paint = new Paint();
        paint.setAntiAlias(true);
        paint.setColor(Color.parseColor("#9e00a0e9"));

        int size = Math.min(getMeasuredWidth(),getMeasuredHeight());
        Bitmap bitmap = Bitmap.createBitmap(size,size,Bitmap.Config.ARGB_8888);
        Canvas canvasTemp = new Canvas(bitmap);
        //將原先的Canvas繪製在bitmap上面
        canvas.drawBitmap(bitmap,0,0,null);

        float radius = size/2;
        //繪製圓形drawCircle(float cx, float cy, float radius, @NonNull Paint paint)
        // 引數含義依次是 cx : 中心點在佈局中的 x 軸位置, cy :中心點在佈局中 y 軸位  
        // 置,radius :半徑 , paint :畫筆                                  
        canvasTemp.drawCircle(getMeasuredWidth()/2,getMeasuredHeight()/2,radius,paint);


        canvasTemp.save();
        //設定裁剪區域,設定完成之後Canvas會在裁剪區域繪製
        canvasTemp.clipRect(0,0,getMeasuredWidth(), (int) (getMeasuredHeight()*0.7));
        //Canvas 擦除顏色,由於擦除顏色使用的不是view本身的Canvas,
        //所以不會擦除背景和父佈局的view
        canvasTemp.drawColor(Color.TRANSPARENT,PorterDuff.Mode.CLEAR);
        canvasTemp.restore();

    }
}

上面的程式碼將原先的Canvas繪製在Bitmap上,使用新的Canvas進行剪裁操作就可以解決背景變黑的問題