這裏主要了解下離屏緩衝和圖像混合模式,可能在自定義view的時候會用到,繪製的內容也非常簡單,一個簡單的圓形頭像
繪製大概分爲5步:
1,開啓離屏緩衝
2,繪製一個圓
3,設置圖像混合模式 https://www.cnblogs.com/libertycode/p/6290497.html
4,繪製bitmap
5,繪製完成後使用 restoreToCount 將離屏緩衝的繪製內容拿回來
/**
* 離屏緩衝和圖像混合模式(圓形頭像)
*/
public class HeadPhotoView extends View {
private float imgWidth = UnitUtil.dp2px(260);
private float mPadding = UnitUtil.dp2px(50);
private Paint mPaint;
private Bitmap mBitmap;
// 圖像混合模式
Xfermode xfermode = new PorterDuffXfermode(PorterDuff.Mode.SRC_IN);
RectF savedArea = new RectF();
public HeadPhotoView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
{
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setColor(Color.RED);
mBitmap = getAvatar((int) imgWidth);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
savedArea.set(
mPadding, mPadding,
mPadding + imgWidth, mPadding + imgWidth
);
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
/*
和save幾乎一樣,唯一區別相比save會把繪製內容挪到離屏緩衝去
必須設置,否則PorterDuffXfermode無效
離屏緩衝還可通過setLayerType(LAYER_TYPE_HARDWARE,null)設置:
三個參數
setLayerType(LAYER_TYPE_HARDWARE,null); 開啓硬件加速外會額外有一個離屏緩衝,耗性能
setLayerType(LAYER_TYPE_SOFTWARE,null); 關閉硬件加速
setLayerType(LAYER_TYPE_NONE,null); 開啓硬件加速
官方詳解用途:在開啓動畫之前通過setLayerType()開啓離屏緩衝,動畫結束時再關閉;
對自定義屬性動畫無用,只是自帶的屬性動畫有用
例: view.setLayerType(View.LAYER_TYPE_HARDWARE,null);
ObjectAnimator animator = ObjectAnimator.ofFloat(view,"rotationY",180);
animator.addListener(new AnimatorListenerAdapter(){
@Override
public void onAnimationEnd(Animator animation){
view.setLayerType(LAYER_TYPE_NONE,null)
}
});
animator.start();
對比saveLayer():
saveLayer比較靈活,在繪製的過程中就可以加,官方建議少用,方法很重
setLayerType()相比saveLayer不靈活,而且是全局的,比如在此類中可在{}中添加setLayerType(LAYER_TYPE_HARDWARE,null)開啓離屏緩衝,
這樣就是全局開啓離屏緩衝,也就意味着侷限性,假設你在此類中做疊加繪製之前有其他繪製內容,就不能使用
*/
int saved = canvas.saveLayer(savedArea, mPaint);
// 繪製一個圓(繪製橢圓是因爲座標點好計算,寬高一樣就是圓)
canvas.drawOval(
mPadding, mPadding,
mPadding + imgWidth, mPadding + imgWidth,
mPaint
);
// 設置圖像混合模式,進行疊加繪製
mPaint.setXfermode(xfermode);
// 繪製bitmap
canvas.drawBitmap(
mBitmap,
mPadding, mPadding, // 左上padding
mPaint
);
mPaint.setXfermode(null);
// 繪製完成後使用 restoreToCount 將離屏緩衝的繪製內容拿回來
canvas.restoreToCount(saved);
}
Bitmap getAvatar(int width) {
BitmapFactory.Options options = new BitmapFactory.Options();
// inJustDecodeBounds爲true,不返回bitmap,只返回這個bitmap的尺寸
options.inJustDecodeBounds = true;
// 從資源中讀取(比較浪費資源,所以上面設置爲true,只獲取圖片寬高)
BitmapFactory.decodeResource(getResources(), R.drawable.qyn, options);
// 再設置爲false,最後要返回bitmap
options.inJustDecodeBounds = false;
// 根據縮放比例重新計算寬高
options.inDensity = options.outWidth;
options.inTargetDensity = width;
return BitmapFactory.decodeResource(getResources(), R.drawable.qyn, options);
}
}
硬件加速:CPU把繪製內容轉換爲GPU操作,然後交給GPU進行,由GPU負責真正的繪製,這就叫硬件繪製,使用GPU繪製就叫做硬件加速;
離屏緩衝:單獨的一個繪製View的區域