Tôi có chế độ xem thực hiện một số bản vẽ cơ bản. Sau đó tôi muốn vẽ một hình chữ nhật với một lỗ được đục lỗ để chỉ có thể nhìn thấy một vùng của bản vẽ trước đó. Và tôi muốn làm điều này với khả năng tăng tốc phần cứng được bật cho chế độ xem của tôi để có hiệu suất tốt nhất.Đấm một lỗ trong lớp phủ hình chữ nhật với tăng tốc HW được bật trên Chế độ xem
Hiện tại tôi có hai phương pháp hoạt động, nhưng chỉ hoạt động khi tăng tốc phần cứng bị vô hiệu hóa và phương thức kia quá chậm.
Phương pháp 1: SW Acceleration (Chậm)
final int saveCount = canvas.save();
// Clip out a circle.
circle.reset();
circle.addCircle(cx, cy, radius, Path.Direction.CW);
circle.close();
canvas.clipPath(circle, Region.Op.DIFFERENCE);
// Draw the rectangle color.
canvas.drawColor(backColor);
canvas.restoreToCount(saveCount);
này không hoạt động với khả năng tăng tốc phần cứng cho chế độ xem vì 'canvas.clipPath' không được hỗ trợ trong chế độ này (Tôi biết tôi có thể buộc SW rendering, nhưng tôi muốn tránh điều đó).
Cách 2: HW Acceleration (V. chậm)
// Create a new canvas.
final Bitmap b = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
final Canvas c = new Canvas(b);
// Draw the rectangle colour.
c.drawColor(backColor);
// Erase a circle.
c.drawCircle(cx, cy, radius, eraser);
// Draw the bitmap on our views canvas.
canvas.drawBitmap(b, 0, 0, null);
đâu tẩy được tạo ra như
eraser = new Paint()
eraser.setColor(0xFFFFFFFF);
eraser.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
này rõ ràng là chậm - một mới Bitmap
kích thước của quan điểm là tạo ra mọi cuộc gọi vẽ.
Phương pháp 3: HW Acceleration (Fast, không hoạt động trên một số thiết bị)
canvas.drawColor(backColor);
canvas.drawCircle(cx, cy, radius, eraser);
Tương tự như các HW tăng tốc phương pháp tương thích, nhưng không cần vải thêm. Có một vấn đề lớn với điều này mặc dù - nó hoạt động với SW rendering buộc, nhưng trên HTC One X (Android 4.0.4 - và có lẽ một số thiết bị khác) ít nhất với HW rendering cho phép nó rời khỏi vòng tròn hoàn toàn màu đen. Điều này có thể liên quan đến 22361.
Phương pháp 4: HW Acceleration (chấp nhận, hoạt động trên tất cả các thiết bị)
Theo đề nghị của Jan để cải thiện phương pháp 2, tôi tránh tạo bitmap trong mỗi cuộc gọi đến onDraw
, thay vì làm như vậy trong onSizeChanged
:
if (w != oldw || h != oldh) {
b = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
c = new Canvas(b);
}
Và sau đó chỉ cần sử dụng những trong onDraw
:
if (overlayBitmap == null) {
b = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
c = new Canvas(b);
}
b.eraseColor(Color.TRANSPARENT);
c.drawColor(backColor);
c.drawCircle(cx, cy, radius, eraser);
canvas.drawBitmap(b, 0, 0, null);
.210
Việc thực hiện là không tốt như phương pháp 3, nhưng tốt hơn nhiều so với 2 và tốt hơn một chút so với 1.
Câu hỏi đặt ra
Làm thế nào tôi có thể đạt được hiệu quả tương tự, nhưng làm như vậy một cách tương thích với HW tăng tốc (VÀ hoạt động liên tục trên các thiết bị)? Một phương pháp làm tăng hiệu suất kết xuất SW cũng sẽ được chấp nhận.
NB: Khi di chuyển vòng tròn xung quanh tôi chỉ làm mất hiệu lực một vùng - không phải toàn bộ canvas - vì vậy không có chỗ cho cải thiện hiệu suất ở đó.
Chỉ đơn giản là bộ nhớ đệm 'Bitmap b' và' Canvas c' có thể? Nó có giúp được không? –
Tôi không nghĩ vậy - nếu bạn chỉ làm 'b' và' c' nói trong 'onSizeChanged' và không phải trong' onDraw' thì bạn sẽ vẽ nhiều lần trên cùng một khung hình mà không xóa (vì vậy bạn muốn kết thúc với nhiều lớp). Trên thực tế nó sẽ làm việc nếu tôi có thể xóa 'b' trong' onDraw' mà cũng có thể có được - Tôi sẽ thử nó, cảm ơn! –
@Jan: Cảm ơn điều này đã làm việc - tôi đã tạo Bitmap 'b' và Canvas' c' trong 'onSizeChanged', sau đó tôi chỉ cần gọi' b.eraseColor (Color.Transparent) 'trước khi thực hiện bất kỳ bản vẽ nào để xóa bất kỳ bản vẽ trước đó trên 'c'. Đăng bình luận của bạn như là một câu trả lời và tôi sẽ đánh dấu nó là chính xác nếu tôi không nhận được bất kỳ câu trả lời hữu ích hơn trong ngày hôm sau hay như vậy. Nó vẫn không trơn tru như phương pháp 3, nhưng tốt hơn nhiều so với 2. –