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ượngPaint
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.
- 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
). - Chế độ xem này, như tất cả chế độ xem, đều có canvas riêng (
canvas
). - Để 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. - 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. - Để 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. - Sau đó, bạn vẽ trên canvas bộ nhớ đệm (
extraCanvas
) và vẽ vào bộ nhớ đệm (extraBitmap
). - Để 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
- Tạo một dự án mới trong Kotlin có tên là MiniPaint bằng mẫu Empty Hoạt động.
- 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>
- Mở
styles.xml
- Trong phần mẹ của kiểu
AppTheme
đã cho, hãy thayDarkActionBar
bằngNoActionBar
. 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ẽ.
- 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
. - Đặt lớp
MyCanvasView
mở rộng lớpView
và chuyển vàocontext: 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
.
- 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>
- Mở
MainActivity.kt
- Trong
onCreate()
, hãy xóasetContentView(R.layout.activity_main)
. - Tạo một thực thể của
MyCanvasView
.
val myCanvasView = MyCanvasView(this)
- 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ênmyCanvasView
. 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
- Thêm nội dung mô tả nội dung.
myCanvasView.contentDescription = getString(R.string.canvasContentDescription)
- Dưới đây, hãy đặt chế độ xem nội dung thành
myCanvasView
.
setContentView(myCanvasView)
- 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.
- 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ọextraCanvas
vàextraBitmap
. Đâ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
- 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ànhcolorBackground
mà bạn đã xác định trước đó.
private val backgroundColor = ResourcesCompat.getColor(resources, R.color.colorBackground, null)
- Trong
MyCanvasView
, hãy ghi đè phương thứconSizeChanged()
. 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)
}
- Bên trong
onSizeChanged()
, hãy tạo một bản sao củaBitmap
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 choextraBitmap
. Đố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)
- Tạo một phiên bản
Canvas
từextraBitmap
và chỉ định phiên bản đó choextraCanvas
.
extraCanvas = Canvas(extraBitmap)
- Chỉ định màu nền để tô màu
extraCanvas
.
extraCanvas.drawColor(backgroundColor)
- 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àosuper
.
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()
.
- Ghi đè
onDraw()
và vẽ nội dung củaextraBitmap
đã lưu vào bộ nhớ đệm trên canvas được liên kết với chế độ xem. Phương thứcdrawBitmap()
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
choPaint
, 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.
- 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ẽ
- 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
- Ở cấp lớp
MyCanvasView
, hãy xác định một biếndrawColor
để giữ màu để vẽ, và khởi tạo biến đó bằng tài nguyêncolorPaint
mà bạn đã xác định trước đó.
private val drawColor = ResourcesCompat.getColor(resources, R.color.colorPaint, null)
- Ở cấp lớp bên dưới, hãy thêm một biến
paint
cho đối tượngPaint
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ủapaint
làdrawColor
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 đặtisAntiAlias
thànhtrue
, 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
, khitrue
, ả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 trongstrokeJoin
củaPaint.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ẽ.
- Trong
MyCanvasView
, hãy thêm một biếnpath
và khởi tạo bằng đối tượngPath
để 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ậpandroid.graphics.Path
choPath
.
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.
- Trong
MyCanvasView
, hãy ghi đè phương thứconTouchEvent()
để lưu vào bộ nhớ đệm các tọa độx
vày
của hàm đã chuyển trongevent
. Sau đó, dùng biểu thứcwhen
để 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ớpMotionEvent
để 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
}
- Ở cấp lớp, hãy thêm các biến
motionTouchEventX
vàmotionTouchEventY
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ành0f
.
private var motionTouchEventX = 0f
private var motionTouchEventY = 0f
- Tạo các cuốn sách cho 3 hàm
touchStart()
,touchMove()
vàtouchUp()
.
private fun touchStart() {}
private fun touchMove() {}
private fun touchUp() {}
- 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.
- Ở 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
- Triển khai phương thức
touchStart()
như sau. Đặt lạipath
, di chuyển đến các tọa độ x-y của sự kiện chạm (motionTouchEventX
vàmotionTouchEventY
), rồi chỉ địnhcurrentX
vàcurrentY
cho giá trị đó.
private fun touchStart() {
path.reset()
path.moveTo(motionTouchEventX, motionTouchEventY)
currentX = motionTouchEventX
currentY = motionTouchEventY
}
Bước 3. Triển khai TouchMove()
- Ở cấp lớp, hãy thêm biến
touchTolerance
và đặt biến đó thànhViewConfiguration.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.
- 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 trongpath
, cập nhật tổng sốcurrentX
vàcurrentY
đang chạy, sau đó vẽpath
. Sau đó, gọiinvalidate()
để buộc vẽ lại màn hình bằngpath
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:
- Tính khoảng cách đã di chuyển (
dx, dy
). - 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.
- Đặ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.
- 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. - Gọi
invalidate()
để (cuối cùng gọionDraw()
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.
- Triển khai phương thức
touchUp()
.
private fun touchUp() {
// Reset the path so it doesn't get drawn again.
path.reset()
}
- 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.
- Trong
MyCanvasView
, hãy thêm một biến có tên làframe
chứa đối tượngRect
.
private lateinit var frame: Rect
- Vào cuối
onSizeChanged()
, hãy xác định một phần lồng ghép và thêm mã để tạoRect
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)
- 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)
- 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ử.
- Trong
MyCanvasView
, hãy xóa tất cả mã choextraCanvas
vàextraBitmap
. - 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()
- 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)
- 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()
- 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.
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 saoView
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()
và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:
- Lớp
Canvas
- Lớp
Bitmap
- Lớp
View
- Lớp
Paint
- Cấu hình
Bitmap.config
- Lớp
Path
- Trang Wikipedia về đường cong Bezier
- Canvas và bản vẽ
- Loạt bài viết Đồ họa kiến trúc (nâng cao)
- tài nguyên có thể vẽ
- onDraw()
- onSizeChanged()
MotionEvent
ViewConfiguration.get(context).scaledTouchSlop
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
, Bitmap
và Paint
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.