Canvas擦出部分割槽域的實現(不擦出背景)
阿新 • • 發佈:2018-12-22
開發中遇到了如下佈局的實現
這個圓形頭像可以使用
但是圓形頭像底部弓形的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進行剪裁操作就可以解決背景變黑的問題