Vẽ trên các đối tượng canvas

Lớp học lập trình này nằm trong khóa học Nâng cao về Android trong Kotlin. Bạn sẽ nhận được nhiều giá trị nhất từ khóa học này nếu bạn làm việc qua các lớp học lập trình theo trình tự, nhưng bạn không bắt buộc phải làm vậy. Tất cả các lớp học lập trình đều có trên trang đích của các lớp học lập trình Android nâng cao trong Kotlin.

Giới thiệu

Trong Android, bạn có một số kỹ thuật có sẵn để triển khai đồ họa 2D tùy chỉnh và ảnh động trong chế độ xem.

Ngoài việc sử dụng hình vẽ, bạn có thể tạo bản vẽ 2D bằng các phương thức vẽ của lớp Canvas. Canvas là giao diện vẽ 2D cung cấp các phương thức vẽ. Điều này rất hữu ích khi ứng dụng của bạn cần thường xuyên vẽ lại vì bản thân người dùng sẽ thấy nội dung thay đổi theo thời gian. Trong lớp học lập trình này, bạn tìm hiểu cách tạo và vẽ trên canvas hiển thị trong View.

Các loại thao tác mà bạn có thể thực hiện trên canvas bao gồm:

  • Tô màu toàn bộ cho canvas.
  • Vẽ các hình dạng, chẳng hạn như hình chữ nhật, hình cung và đường dẫn theo kiểu xác định trong đối tượng Paint. Đối tượng Paint lưu giữ thông tin về kiểu và màu về cách vẽ hình học (chẳng hạn như đường kẻ, hình chữ nhật, hình bầu dục và đường dẫn), hoặc ví dụ: kiểu chữ của văn bản.
  • Áp dụng các phép biến đổi, chẳng hạn như bản dịch, tỷ lệ hoặc các phép biến đổi tùy chỉnh.
  • Ghim, tức là áp dụng hình dạng hoặc đường dẫn vào canvas để xác định các phần hiển thị.

Bạn có thể hình dung bản vẽ Android như thế nào (siêu đơn giản!)

Vẽ trong Android hay trên bất kỳ hệ thống hiện đại nào khác là một quy trình phức tạp bao gồm các lớp trừu tượng và tối ưu hóa cho phần cứng. Cách Android vẽ là một chủ đề hấp dẫn được viết ra và nhiều chi tiết của ứng dụng này nằm ngoài phạm vi của lớp học lập trình này.

Trong bối cảnh của lớp học lập trình này và ứng dụng vẽ trên canvas để hiển thị ở chế độ xem toàn màn hình, bạn có thể hình dung như sau.

  1. Bạn cần một chế độ xem để hiển thị những gì bạn đang vẽ. Đây có thể là một trong các chế độ xem do hệ thống Android cung cấp. Hoặc, trong lớp học lập trình này, bạn tạo một chế độ xem tùy chỉnh đóng vai trò là chế độ xem nội dung cho ứng dụng (MyCanvasView).
  2. Chế độ xem này, như tất cả chế độ xem, đều có canvas riêng (canvas).
  3. Để có cách vẽ cơ bản nhất trên canvas của chế độ xem, bạn có thể ghi đè phương thức onDraw() của chế độ xem đó và vẽ trên canvas.
  4. Khi xây dựng bản vẽ, bạn cần lưu bộ nhớ đệm những gì bạn đã vẽ trước đây. Có một số cách để lưu dữ liệu của bạn vào bộ nhớ đệm, một cách là trong bitmap (extraBitmap). Một cách khác là lưu lịch sử nội dung bạn đã vẽ dưới dạng tọa độ và hướng dẫn.
  5. Để vẽ vào webhook lưu trong bộ nhớ đệm (extraBitmap) bằng API vẽ trên vải canvas, bạn cần tạo một canvas lưu bộ nhớ đệm (extraCanvas) cho bitmap lưu vào bộ nhớ đệm.
  6. Sau đó, bạn vẽ trên canvas bộ nhớ đệm (extraCanvas) và vẽ vào bộ nhớ đệm (extraBitmap).
  7. Để hiển thị mọi nội dung được vẽ trên màn hình, bạn cần yêu cầu canvas sẽ xem (canvas) để vẽ bitmap vào bộ nhớ đệm (extraBitmap).

Kiến thức bạn cần có

  • Cách tạo một ứng dụng có Hoạt động, bố cục cơ bản và chạy ứng dụng đó bằng Android Studio.
  • Cách liên kết trình xử lý sự kiện với chế độ xem.
  • Cách tạo chế độ xem tùy chỉnh.

Kiến thức bạn sẽ học được

  • Cách tạo Canvas và vẽ trên đó để phản hồi thao tác chạm của người dùng.

Bạn sẽ thực hiện

  • Tạo một ứng dụng vẽ các đường trên màn hình để phản hồi người dùng đang chạm vào màn hình.
  • Ghi lại các sự kiện chuyển động và vẽ lại các đường kẻ trên canvas được hiển thị ở chế độ xem tùy chỉnh toàn màn hình trên màn hình.

Ứng dụng MiniPaint sử dụng chế độ xem tùy chỉnh để hiển thị một dòng phản hồi thao tác chạm của người dùng, như minh họa trong ảnh chụp màn hình dưới đây.

Bước 1. Tạo dự án MiniPaint

  1. Tạo một dự án mới trong Kotlin có tên là MiniPaint bằng mẫu Empty Hoạt động.
  2. Mở tệp app/res/values/colors.xml và thêm hai màu sau.
<color name="colorBackground">#FFFF5500</color>
<color name="colorPaint">#FFFFEB3B</color>
  1. Mở styles.xml
  2. Trong phần mẹ của kiểu AppTheme đã cho, hãy thay DarkActionBar bằng NoActionBar. Thao tác này sẽ xóa thanh thao tác để bạn có thể vẽ toàn màn hình.
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">

Bước 2. Tạo lớp MyCanvasView

Trong bước này, bạn tạo một chế độ xem tùy chỉnh MyCanvasView để vẽ.

  1. Trong gói app/java/com.example.android.minipaint, hãy tạo một Mới > Tệp/Lớp Kotlin có tên là MyCanvasView.
  2. Đặt lớp MyCanvasView mở rộng lớp View và chuyển vào context: Context. Chấp nhận dữ liệu nhập được đề xuất.
import android.content.Context
import android.view.View

class MyCanvasView(context: Context) : View(context) {
}

Bước 3. Đặt MyCanvasView làm chế độ xem nội dung

Để hiển thị nội dung bạn sẽ vẽ trong MyCanvasView, bạn phải đặt nội dung đó làm chế độ xem nội dung của MainActivity.

  1. Mở strings.xml và xác định một chuỗi để sử dụng cho nội dung mô tả nội dung của chế độ xem.
<string name="canvasContentDescription">Mini Paint is a simple line drawing app.
   Drag your fingers to draw. Rotate the phone to clear.</string>
  1. Mở MainActivity.kt
  2. Trong onCreate(), hãy xóa setContentView(R.layout.activity_main).
  3. Tạo một thực thể của MyCanvasView.
val myCanvasView = MyCanvasView(this)
  1. Dưới đây là yêu cầu toàn màn hình cho bố cục của myCanvasView. Thực hiện việc này bằng cách đặt cờ SYSTEM_UI_FLAG_FULLSCREEN trên myCanvasView. Bằng cách này, chế độ xem sẽ lấp đầy hoàn toàn màn hình.
myCanvasView.systemUiVisibility = SYSTEM_UI_FLAG_FULLSCREEN
  1. Thêm nội dung mô tả nội dung.
myCanvasView.contentDescription = getString(R.string.canvasContentDescription)
  1. Dưới đây, hãy đặt chế độ xem nội dung thành myCanvasView.
setContentView(myCanvasView)
  1. Chạy ứng dụng của bạn. Bạn sẽ thấy một màn hình hoàn toàn màu trắng, vì canvas không có kích thước và bạn chưa vẽ gì.

Bước 1. Ghi đè onSizeChanged()

Hệ thống Android gọi phương thức onSizeChanged() mỗi khi một chế độ xem thay đổi kích thước. Vì chế độ xem bắt đầu mà không có kích thước, nên phương thức onSizeChanged() của chế độ xem cũng được gọi sau khi Hoạt động được tạo và tăng cường lần đầu. Do đó, phương thức onSizeChanged() này là vị trí lý tưởng để tạo và thiết lập canvas của chế độ xem.

  1. Trong MyCanvasView, ở cấp lớp, hãy xác định các biến cho một canvas và một bitmap. Hãy gọi cho họ extraCanvasextraBitmap. Đây là những canvas và canvas để lưu vào bộ nhớ đệm đã được vẽ trước đó.
private lateinit var extraCanvas: Canvas
private lateinit var extraBitmap: Bitmap
  1. Xác định một biến cấp lớp backgroundColor cho màu nền của canvas và khởi tạo biến đó thành colorBackground mà bạn đã xác định trước đó.
private val backgroundColor = ResourcesCompat.getColor(resources, R.color.colorBackground, null)
  1. Trong MyCanvasView, hãy ghi đè phương thức onSizeChanged(). Phương thức gọi lại này được hệ thống Android gọi với kích thước màn hình đã thay đổi, tức là có chiều rộng và chiều cao mới (để thay đổi thành) cũng như chiều rộng và chiều cao cũ (để thay đổi từ).
override fun onSizeChanged(width: Int, height: Int, oldWidth: Int, oldHeight: Int) {
   super.onSizeChanged(width, height, oldWidth, oldHeight)
}
  1. Bên trong onSizeChanged(), hãy tạo một bản sao của Bitmap có chiều rộng và chiều cao mới, tức là kích thước màn hình, và chỉ định cho extraBitmap. Đối số thứ ba là cấu hình màu của bản đồ bit. ARGB_8888 lưu trữ mỗi màu bằng 4 byte và được đề xuất.
extraBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
  1. Tạo một phiên bản Canvas từ extraBitmap và chỉ định phiên bản đó cho extraCanvas.
 extraCanvas = Canvas(extraBitmap)
  1. Chỉ định màu nền để tô màu extraCanvas.
extraCanvas.drawColor(backgroundColor)
  1. Nhìn vào onSizeChanged(), một bitmap và canvas mới được tạo mỗi khi hàm thực thi. Bạn cần một bitmap mới vì kích thước đã thay đổi. Tuy nhiên, đây là rò rỉ bộ nhớ, để lại các bitmap cũ. Để khắc phục sự cố này, hãy tái chế extraBitmap trước khi tạo mã tiếp theo bằng cách thêm mã này ngay sau lệnh gọi vào super.
if (::extraBitmap.isInitialized) extraBitmap.recycle()

Bước 2. Ghi đè onDraw()

Toàn bộ công việc vẽ cho MyCanvasView diễn ra sau onDraw().

Để bắt đầu, hãy hiển thị canvas, lấp đầy màn hình bằng màu nền mà bạn đã đặt trong onSizeChanged().

  1. Ghi đè onDraw() và vẽ nội dung của extraBitmap đã lưu vào bộ nhớ đệm trên canvas được liên kết với chế độ xem. Phương thức drawBitmap() Canvas có nhiều phiên bản. Trong mã này, bạn cung cấp bitmap, tọa độ x và y (tính bằng pixel) của góc trên cùng bên trái và null cho Paint, như bạn sẽ đặt sau.
override fun onDraw(canvas: Canvas) {
   super.onDraw(canvas)
canvas.drawBitmap(extraBitmap, 0f, 0f, null)
}


Xin lưu ý rằng canvas được chuyển đến onDraw() và được hệ thống sử dụng để hiển thị bitmap là khác với canvas bạn đã tạo trong phương thức onSizeChanged() và được bạn dùng để vẽ trên bitmap.

  1. Chạy ứng dụng của bạn. Bạn sẽ thấy toàn bộ màn hình được tô màu nền đã chỉ định.

Để vẽ, bạn cần có đối tượng Paint chỉ định cách tạo kiểu khi vẽ và một đối tượng Path chỉ định nội dung đang được vẽ.

Bước 1. Khởi tạo đối tượng Vẽ

  1. Trong MyCanvasView.kt, ở cấp độ tệp trên cùng, hãy xác định một hằng số cho chiều rộng nét.
private const val STROKE_WIDTH = 12f // has to be float
  1. Ở cấp lớp MyCanvasView, hãy xác định một biến drawColor để giữ màu để vẽ, và khởi tạo biến đó bằng tài nguyên colorPaint mà bạn đã xác định trước đó.
private val drawColor = ResourcesCompat.getColor(resources, R.color.colorPaint, null)
  1. Ở cấp lớp bên dưới, hãy thêm một biến paint cho đối tượng Paint và khởi tạo biến đó như sau.
// Set up the paint with which to draw.
private val paint = Paint().apply {
   color = drawColor
   // Smooths out edges of what is drawn without affecting shape.
   isAntiAlias = true
   // Dithering affects how colors with higher-precision than the device are down-sampled.
   isDither = true
   style = Paint.Style.STROKE // default: FILL
   strokeJoin = Paint.Join.ROUND // default: MITER
   strokeCap = Paint.Cap.ROUND // default: BUTT
   strokeWidth = STROKE_WIDTH // default: Hairline-width (really thin)
}
  • color của paintdrawColor mà bạn đã xác định trước đó.
  • isAntiAlias xác định xem có áp dụng tính năng làm mượt cạnh hay không. Khi bạn đặt isAntiAlias thành true, hãy làm phẳng các cạnh được vẽ mà không làm ảnh hưởng đến hình dạng.
  • isDither, khi true, ảnh hưởng đến cách màu sắc có độ chính xác cao hơn thiết bị được lấy mẫu. Ví dụ: chế độ tạo màu là phương tiện phổ biến nhất để giảm dải màu xuống 256 (hoặc ít hơn) màu.
  • style đặt loại tranh vẽ thành một nét vẽ, về cơ bản là một đường kẻ. Paint.Style chỉ định xem kiểu gốc được vẽ, được tô màu hay cả hai (cùng màu). Tùy chọn mặc định là lấp đầy đối tượng áp dụng màu sơn. (" Tô" màu trong
  • strokeJoin của Paint.Join chỉ định cách các đường và phân đoạn đường cong kết hợp với nhau trên một đường dẫn được đánh dấu. Mặc định là MITER.
  • strokeCap đặt hình dạng của phần cuối của dòng thành giới hạn. Paint.Cap chỉ định cách bắt đầu và kết thúc của đường kẻ và đường dẫn. Mặc định là BUTT.
  • strokeWidth chỉ định chiều rộng của nét vẽ bằng pixel. Theo mặc định, chiều rộng của đường viền tóc sẽ mỏng, vì vậy, chiều rộng này được đặt thành hằng số STROKE_WIDTH mà bạn đã xác định trước đó.

Bước 2. Khởi tạo đối tượng Đường dẫn

Path là đường dẫn mà người dùng đang vẽ.

  1. Trong MyCanvasView, hãy thêm một biến path và khởi tạo bằng đối tượng Path để lưu trữ đường dẫn đang được vẽ khi người dùng chạm vào màn hình trên màn hình. Nhập android.graphics.Path cho Path.
private var path = Path()

Bước 1. Phản hồi chuyển động trên màn hình

Phương thức onTouchEvent() trên chế độ xem được gọi bất cứ khi nào người dùng chạm vào màn hình.

  1. Trong MyCanvasView, hãy ghi đè phương thức onTouchEvent() để lưu vào bộ nhớ đệm các tọa độ xy của hàm đã chuyển trong event. Sau đó, dùng biểu thức when để xử lý các sự kiện chuyển động khi chạm vào màn hình, di chuyển trên màn hình và thả tay chạm trên màn hình. Đây là những sự kiện cần quan tâm khi vẽ một đường trên màn hình. Đối với mỗi loại sự kiện, hãy gọi một phương thức hữu ích, như được hiển thị trong mã bên dưới. Hãy xem tài liệu về lớp MotionEvent để biết danh sách đầy đủ các sự kiện chạm.
override fun onTouchEvent(event: MotionEvent): Boolean {
   motionTouchEventX = event.x
   motionTouchEventY = event.y

   when (event.action) {
       MotionEvent.ACTION_DOWN -> touchStart()
       MotionEvent.ACTION_MOVE -> touchMove()
       MotionEvent.ACTION_UP -> touchUp()
   }
   return true
}
  1. Ở cấp lớp, hãy thêm các biến motionTouchEventXmotionTouchEventY bị thiếu để lưu vào bộ nhớ đệm các tọa độ x và y của sự kiện chạm hiện tại (tọa độ MotionEvent). Hãy khởi chạy các giá trị này thành 0f.
private var motionTouchEventX = 0f
private var motionTouchEventY = 0f
  1. Tạo các cuốn sách cho 3 hàm touchStart(), touchMove()touchUp().
private fun touchStart() {}

private fun touchMove() {}

private fun touchUp() {}
  1. Mã của bạn phải tạo và chạy, nhưng bạn sẽ không thấy bất kỳ thứ gì khác với nền được tô màu.

Bước 2. Triển khai TouchStart()

Phương thức này được gọi khi người dùng chạm vào màn hình lần đầu tiên.

  1. Ở cấp lớp, hãy thêm biến để lưu vào bộ nhớ đệm các giá trị x và y mới nhất. Sau khi người dùng ngừng di chuyển và nhấc ngón tay lên, đây là điểm bắt đầu cho đường dẫn tiếp theo (phân đoạn tiếp theo của đường để vẽ).
private var currentX = 0f
private var currentY = 0f
  1. Triển khai phương thức touchStart() như sau. Đặt lại path, di chuyển đến các tọa độ x-y của sự kiện chạm (motionTouchEventXmotionTouchEventY), rồi chỉ định currentXcurrentY cho giá trị đó.
private fun touchStart() {
   path.reset()
   path.moveTo(motionTouchEventX, motionTouchEventY)
   currentX = motionTouchEventX
   currentY = motionTouchEventY
}

Bước 3. Triển khai TouchMove()

  1. Ở cấp lớp, hãy thêm biến touchTolerance và đặt biến đó thành ViewConfiguration.get(context).scaledTouchSlop.
private val touchTolerance = ViewConfiguration.get(context).scaledTouchSlop

Khi sử dụng đường dẫn, bạn không cần phải vẽ từng pixel và mỗi lần yêu cầu làm mới màn hình. Thay vào đó, bạn có thể (và sẽ) nội suy đường dẫn giữa các điểm để có hiệu suất tốt hơn.

  • Nếu ngón tay hầu như không di chuyển, thì không cần phải vẽ.
  • Nếu ngón tay đã di chuyển nhỏ hơn khoảng cách touchTolerance, đừng vẽ.
  • scaledTouchSlop trả về khoảng cách tính bằng pixel mà một lần chạm có thể lang thang trước khi hệ thống cho rằng người dùng đang cuộn.
  1. Xác định phương thức touchMove(). Tính khoảng cách đã đi (dx, dy), tạo một đường cong giữa hai điểm và lưu trữ điểm này trong path, cập nhật tổng số currentXcurrentY đang chạy, sau đó vẽ path. Sau đó, gọi invalidate() để buộc vẽ lại màn hình bằng path mới cập nhật.
private fun touchMove() {
   val dx = Math.abs(motionTouchEventX - currentX)
   val dy = Math.abs(motionTouchEventY - currentY)
   if (dx >= touchTolerance || dy >= touchTolerance) {
       // QuadTo() adds a quadratic bezier from the last point,
       // approaching control point (x1,y1), and ending at (x2,y2).
       path.quadTo(currentX, currentY, (motionTouchEventX + currentX) / 2, (motionTouchEventY + currentY) / 2)
       currentX = motionTouchEventX
       currentY = motionTouchEventY
       // Draw the path in the extra bitmap to cache it.
       extraCanvas.drawPath(path, paint)
   }
   invalidate()
}

Phương pháp này chi tiết hơn:

  1. Tính khoảng cách đã di chuyển (dx, dy).
  2. Nếu chuyển động vượt quá dung sai của cảm ứng, hãy thêm một đoạn vào đường dẫn.
  3. Đặt điểm bắt đầu cho phân đoạn tiếp theo thành điểm cuối của phân đoạn này.
  4. Sử dụng quadTo() thay vì lineTo() để tạo một đường kẻ được vẽ trơn tru mà không có góc. Xem Bezier cong.
  5. Gọi invalidate() để (cuối cùng gọi onDraw() và) vẽ lại chế độ xem.

Bước 4: Triển khai TouchUp()

Khi người dùng chạm đi, tất cả những gì cần làm là đặt lại đường dẫn để đường dẫn không bị vẽ lại. Không có mục nào được vẽ nên không cần vô hiệu hóa.

  1. Triển khai phương thức touchUp().
private fun touchUp() {
   // Reset the path so it doesn't get drawn again.
   path.reset()
}
  1. Chạy mã và dùng ngón tay để vẽ trên màn hình. Lưu ý rằng nếu bạn xoay thiết bị, màn hình sẽ bị xóa do trạng thái vẽ không được lưu. Đối với ứng dụng mẫu này, đây là thiết kế nhằm cung cấp cho người dùng một cách đơn giản để xóa màn hình.

Bước 5: Vẽ một khung xung quanh bản phác thảo

Khi người dùng vẽ trên màn hình, ứng dụng của bạn sẽ tạo đường dẫn và lưu đường dẫn đó trong bitmap extraBitmap. Phương thức onDraw() hiển thị bitmap phụ trong canvas của chế độ xem. Bạn có thể vẽ thêm trong onDraw(). Ví dụ: bạn có thể vẽ các hình dạng sau khi vẽ bitmap.

Ở bước này, bạn vẽ một khung xung quanh cạnh của hình ảnh.

  1. Trong MyCanvasView, hãy thêm một biến có tên là frame chứa đối tượng Rect.
private lateinit var frame: Rect
  1. Vào cuối onSizeChanged(), hãy xác định một phần lồng ghép và thêm mã để tạo Rect sẽ được dùng cho khung này, bằng cách sử dụng các phương diện mới và phần lồng ghép.
// Calculate a rectangular frame around the picture.
val inset = 40
frame = Rect(inset, inset, width - inset, height - inset)
  1. Trong onDraw(), sau khi vẽ bitmap, hãy vẽ một hình chữ nhật.
// Draw a frame around the canvas.
canvas.drawRect(frame, paint)
  1. Chạy ứng dụng của bạn. Hãy để ý thấy khung.

Việc cần làm (không bắt buộc): Lưu trữ dữ liệu trong một đường dẫn

Trong ứng dụng hiện tại, thông tin bản vẽ được lưu trữ trong một bitmap. Mặc dù đây là giải pháp tốt, nhưng đây không phải là cách duy nhất có thể áp dụng để lưu trữ thông tin bản vẽ. Cách bạn lưu trữ lịch sử vẽ sẽ tùy thuộc vào ứng dụng và các yêu cầu khác nhau của bạn. Ví dụ: nếu đang vẽ các hình dạng, bạn có thể lưu một danh sách các hình dạng có vị trí và kích thước của chúng. Đối với ứng dụng MiniPaint, bạn có thể lưu đường dẫn dưới dạng Path. Dưới đây là phác thảo chung về cách thực hiện, nếu bạn muốn thử.

  1. Trong MyCanvasView, hãy xóa tất cả mã cho extraCanvasextraBitmap.
  2. Thêm các biến cho đường dẫn cho đến thời điểm hiện tại và đường dẫn đang được vẽ.
// Path representing the drawing so far
private val drawing = Path()

// Path representing what's currently being drawn
private val curPath = Path()
  1. Trong onDraw(), thay vì vẽ bitmap, hãy vẽ các đường dẫn đã lưu trữ và hiện tại.
// Draw the drawing so far
canvas.drawPath(drawing, paint)
// Draw any current squiggle
canvas.drawPath(curPath, paint)
// Draw a frame around the canvas
canvas.drawRect(frame, paint)
  1. Trong touchUp(), hãy thêm đường dẫn hiện tại vào đường dẫn trước đó và đặt lại đường dẫn hiện tại.
// Add the current path to the drawing so far
drawing.addPath(curPath)
// Rewind the current path for the next touch
curPath.reset()
  1. Hãy chạy ứng dụng của bạn và chắc chắn rằng sẽ không có sự khác biệt nào.

Tải mã xuống cho lớp học lập trình đã hoàn thành.

$  git clone https://github.com/googlecodelabs/android-kotlin-drawing-canvas


Hoặc bạn có thể tải kho lưu trữ xuống dưới dạng tệp Zip, giải nén và mở tệp đó trong Android Studio.

Tải tệp zip xuống

  • Canvas là giao diện vẽ 2D cung cấp các phương thức vẽ.
  • Canvas có thể được liên kết với một bản sao View hiển thị thông tin đó.
  • Đối tượng Paint lưu giữ thông tin về kiểu và màu về cách vẽ hình học (chẳng hạn như đường kẻ, hình chữ nhật, hình bầu dục và đường dẫn) và văn bản.
  • Một mẫu phổ biến để làm việc với canvas là tạo chế độ xem tùy chỉnh và ghi đè các phương thức onDraw()onSizeChanged().
  • Ghi đè phương thức onTouchEvent() để ghi lại những phản hồi của người dùng và phản hồi các thao tác đó bằng cách vẽ nội dung.
  • Bạn có thể dùng một bitmap bổ sung để lưu vào bộ nhớ đệm những thông tin có thể thay đổi theo thời gian. Ngoài ra, bạn có thể lưu trữ các hình dạng hoặc một đường dẫn.

Khóa học từ Udacity:

Tài liệu dành cho nhà phát triển Android:

Phần này liệt kê các bài tập về nhà có thể được giao cho học viên đang làm việc qua lớp học lập trình này trong khóa học do người hướng dẫn tổ chức. Người hướng dẫn có thể làm những việc sau:

  • Giao bài tập về nhà nếu được yêu cầu.
  • Trao đổi với học viên cách nộp bài tập về nhà.
  • Chấm điểm bài tập về nhà.

Người hướng dẫn có thể sử dụng những đề xuất này ít hay nhiều tùy ý. Do đó, họ có thể thoải mái giao bất kỳ bài tập về nhà nào khác mà họ cảm thấy phù hợp.

Nếu bạn đang tự mình làm việc qua lớp học lập trình này, hãy thoải mái sử dụng các bài tập về nhà này để kiểm tra kiến thức của bạn.

Trả lời những câu hỏi này

Câu hỏi 1

Các thành phần nào sau đây là bắt buộc để làm việc với Canvas? Hãy chọn mọi câu phù hợp.

Bitmap

Paint

Path

View

Câu hỏi 2

Lệnh gọi tới invalidate() thực hiện điều gì (nói chung là)?

▢ Vô hiệu hóa và khởi động lại ứng dụng của bạn.

▢ Xóa bản vẽ khỏi bitmap.

▢ Cho biết rằng mã trước đó không được chạy.

▢ Cho hệ thống biết rằng phải vẽ lại màn hình.

Câu hỏi 3

Chức năng của đối tượng Canvas, BitmapPaint là gì?

▢ Bề mặt vẽ 2D, bitmap hiển thị trên màn hình, thông tin tạo kiểu để vẽ.

▢ Bề mặt vẽ 3D, bitmap dùng để lưu đường dẫn, lưu thông tin định kiểu để vẽ.

▢ Bề mặt vẽ 2D, bitmap hiển thị trên màn hình, định kiểu cho chế độ xem.

▢ Bộ nhớ đệm để vẽ thông tin, bitmap dùng để vẽ, tạo kiểu thông tin để vẽ.

Để xem đường liên kết đến các lớp học lập trình khác trong khóa học này, hãy xem trang đích Nâng cao cho Android trong Kotlin.