Các tính năng nâng cao của bút cảm ứng

Android và ChromeOS cung cấp nhiều API để giúp bạn xây dựng những ứng dụng cung cấp cho người dùng một trải nghiệm bút cảm ứng vượt trội. Chiến lược phát hành đĩa đơn Lớp MotionEvent hiển thị thông tin về hoạt động tương tác của bút cảm ứng với màn hình, bao gồm cả áp lực của bút cảm ứng, hướng, độ nghiêng, khoảng cách di và khả năng phát hiện tì tay. Đồ hoạ và chuyển động có độ trễ thấp thư viện dự đoán giúp cải thiện khả năng kết xuất bút cảm ứng trên màn hình để cung cấp tự nhiên, giống như trên giấy và bút.

MotionEvent

Lớp MotionEvent biểu thị các hoạt động tương tác đầu vào của người dùng, chẳng hạn như vị trí và chuyển động của con trỏ cảm ứng trên màn hình. Để nhập bằng bút cảm ứng, MotionEvent cũng hiển thị dữ liệu về áp lực, hướng, độ nghiêng và khoảng cách di.

Dữ liệu sự kiện

To access MotionEvent data, add a pointerInput modifier to components:

@Composable
fun Greeting() {
    Text(
        text = "Hello, Android!", textAlign = TextAlign.Center, style = TextStyle(fontSize = 5.em),
        modifier = Modifier
            .pointerInput(Unit) {
                awaitEachGesture {
                    while (true) {
                        val event = awaitPointerEvent()
                        event.changes.forEach { println(it) }
                    }
                }
            },
    )
}

Đối tượng MotionEvent cung cấp dữ liệu liên quan đến các khía cạnh sau của giao diện người dùng sự kiện:

  • Thao tác: Hoạt động tương tác vật lý với thiết bị – chạm vào màn hình, di chuyển con trỏ qua bề mặt màn hình, di con trỏ qua màn hình nền tảng
  • Con trỏ: Giá trị nhận dạng của các đối tượng tương tác với màn hình – ngón tay, bút cảm ứng, chuột
  • Trục: Loại dữ liệu – toạ độ x và y, áp lực, độ nghiêng, hướng, và di chuột (khoảng cách)

Thao tác

Để triển khai tính năng hỗ trợ bút cảm ứng, bạn cần nắm được thao tác của người dùng hiệu quả nhất.

MotionEvent cung cấp nhiều hằng số ACTION để xác định chuyển động các sự kiện. Sau đây là những thao tác quan trọng nhất đối với bút cảm ứng:

Hành động Nội dung mô tả
ACTION_DOWN
ACTION_POINTER_DOWN
Con trỏ đã tiếp xúc với màn hình.
ACTION_MOVE Con trỏ đang di chuyển trên màn hình.
ACTION_UP
ACTION_POINTER_UP
Con trỏ không tiếp xúc với màn hình nữa
ACTION_CANCEL Khi tập hợp chuyển động trước đó hoặc hiện tại bị huỷ.

Ứng dụng của bạn có thể thực hiện các thao tác như bắt đầu một nét vẽ mới khi ACTION_DOWN xảy ra, vẽ nét vẽ bằng ACTION_MOVE, và kết thúc nét vẽ khi ACTION_UP đã được kích hoạt.

Tập hợp các hành động MotionEvent từ ACTION_DOWN đến ACTION_UP cho một hoạt động cụ thể con trỏ được gọi là tập hợp chuyển động.

Con trỏ

Hầu hết màn hình đều có nhiều điểm chạm: hệ thống chỉ định một con trỏ cho mỗi ngón tay, bút cảm ứng, chuột hoặc vật thể trỏ khác tương tác với màn hình. Một con trỏ chỉ mục cho phép bạn nhận thông tin trục của một con trỏ cụ thể, chẳng hạn như vị trí của ngón tay đầu tiên chạm vào màn hình hoặc ngón tay thứ hai.

Chỉ mục con trỏ nằm trong khoảng từ 0 đến số lượng con trỏ được trả về MotionEvent#pointerCount() âm 1.

Bạn có thể truy cập vào các giá trị trục của con trỏ bằng phương thức getAxisValue(axis, pointerIndex). Khi chỉ mục con trỏ bị bỏ qua, hệ thống sẽ trả về giá trị cho con trỏ, con trỏ 0 (0).

Các đối tượng MotionEvent chứa thông tin về loại con trỏ đang sử dụng. Bạn có thể lấy loại con trỏ bằng cách lặp lại qua các chỉ mục con trỏ và gọi thời gian getToolType(pointerIndex) .

Để tìm hiểu thêm về con trỏ, hãy xem bài viết Xử lý nhiều điểm chạm cử chỉ.

Phương thức nhập bằng bút cảm ứng

Bạn có thể lọc tìm phương thức nhập bằng bút cảm ứng thông qua TOOL_TYPE_STYLUS:

val isStylus = TOOL_TYPE_STYLUS == event.getToolType(pointerIndex)

Bút cảm ứng cũng có thể báo cáo rằng bút được dùng làm tẩy thông qua TOOL_TYPE_ERASER:

val isEraser = TOOL_TYPE_ERASER == event.getToolType(pointerIndex)

Dữ liệu trục bút cảm ứng

ACTION_DOWNACTION_MOVE cung cấp dữ liệu trục về bút cảm ứng, cụ thể là x và toạ độ y, áp lực, hướng, độ nghiêng và thao tác di.

Để cho phép truy cập vào dữ liệu này, API MotionEvent cung cấp getAxisValue(int), trong đó tham số là bất kỳ giá trị nhận dạng trục nào sau đây:

Trục Giá trị trả về của getAxisValue()
AXIS_X Toạ độ X của một sự kiện chuyển động.
AXIS_Y Toạ độ Y của một sự kiện chuyển động.
AXIS_PRESSURE Đối với màn hình cảm ứng hoặc bàn di chuột, áp lực chịu tác động của ngón tay, bút cảm ứng hoặc con trỏ khác. Đối với chuột hoặc bi xoay, giá trị áp lực sẽ là 1 nếu bạn nhấn nút chính, là 0 nếu không nhấn.
AXIS_ORIENTATION Đối với màn hình cảm ứng hoặc bàn di chuột, hướng của ngón tay, bút cảm ứng hoặc con trỏ khác so với mặt phẳng thẳng đứng của thiết bị.
AXIS_TILT Góc nghiêng của bút cảm ứng tính bằng radian.
AXIS_DISTANCE Khoảng cách của bút cảm ứng so với màn hình.

Ví dụ: MotionEvent.getAxisValue(AXIS_X) trả về toạ độ x cho con trỏ đầu tiên.

Xem thêm bài viết Xử lý nhiều điểm chạm cử chỉ.

Vị trí

Bạn có thể truy xuất toạ độ x và y của một con trỏ bằng các lệnh gọi sau:

Bút cảm ứng đang vẽ trên màn hình với toạ độ x và y được ánh xạ.
Hình 1. Toạ độ x và y trên màn hình của con trỏ bút cảm ứng.

Áp lực

Bạn có thể truy xuất áp lực của con trỏ bằng MotionEvent#getAxisValue(AXIS_PRESSURE) hoặc đối với con trỏ đầu tiên, MotionEvent#getPressure().

Giá trị áp lực cho màn hình cảm ứng hoặc bàn di chuột là một giá trị nằm trong khoảng 0 (không áp lực) và 1, nhưng có thể trả về giá trị cao hơn tuỳ thuộc vào màn hình lấy mẫu.

Nét vẽ bằng bút cảm ứng biểu thị miền liên tục của áp lực từ thấp đến cao. Nét vẽ hẹp và mờ ở bên trái, cho biết áp lực thấp. Nét vẽ ngày càng rộng hơn và đậm hơn từ trái sang phải cho đến khi rộng nhất và đậm nhất ở phía xa bên phải, cho biết áp lực cao nhất.
Hình 2. Hình biểu diễn lực – lực ít ở bên trái, lực nhiều ở bên phải.

Hướng

Hướng cho biết bút cảm ứng trỏ tới hướng nào.

Bạn có thể truy xuất hướng của con trỏ bằng cách sử dụng getAxisValue(AXIS_ORIENTATION) hoặc getOrientation() (đối với con trỏ đầu tiên).

Đối với bút cảm ứng, hướng được trả về dưới dạng một giá trị radian từ 0 đến pi (π) theo chiều kim đồng hồ hoặc 0 đến -pi ngược chiều kim đồng hồ.

Hướng cho phép bạn triển khai một bút vẽ thực tế. Ví dụ: nếu bút cảm ứng biểu thị một cọ vẽ dẹt, chiều rộng của cọ vẽ dẹt đó phụ thuộc vào hướng của bút cảm ứng.

Hình 3. Bút cảm ứng đang trỏ sang trái khoảng -0,57 radian.

Độ nghiêng

Độ nghiêng đo độ nghiêng của bút cảm ứng so với màn hình.

Độ nghiêng trả về góc dương của bút cảm ứng tính bằng radian, trong đó 0 bằng vuông góc với màn và π/2 bằng phẳng trên bề mặt.

Bạn có thể truy xuất góc nghiêng bằng getAxisValue(AXIS_TILT) (không có phím tắt cho con trỏ đầu tiên).

Độ nghiêng có thể được dùng để tái tạo các công cụ gần giống thực tế nhất có thể, chẳng hạn như đang mô phỏng hiệu ứng đổ bóng bằng một chiếc bút chì nghiêng.

Bút cảm ứng được đặt nghiêng khoảng 40 độ so với bề mặt màn hình.
Hình 4. Bút cảm ứng được đặt nghiêng khoảng 0,785 radian hoặc 45 độ so với điểm vuông góc.

Khoảng cách di

Có thể lấy khoảng cách của bút cảm ứng so với màn hình bằng getAxisValue(AXIS_DISTANCE). Phương thức này trả về một giá trị từ 0 (liên hệ với màn hình) thành giá trị cao hơn khi bút cảm ứng di chuyển ra khỏi màn hình. Di chuột khoảng cách giữa màn hình và đầu ngòi bút (điểm) của bút cảm ứng phụ thuộc vào nhà sản xuất của cả màn hình lẫn bút cảm ứng. Vì việc triển khai có thể khác nhau, không dựa vào các giá trị chính xác cho chức năng quan trọng của ứng dụng.

Bạn có thể dùng thao tác di bằng bút cảm ứng để xem trước kích thước của bút vẽ hoặc cho biết rằng sẽ được chọn.

Hình 5. Bút cảm ứng di qua màn hình. Ứng dụng phản ứng ngay cả khi bút cảm ứng chưa chạm vào bề mặt màn hình.

Lưu ý: Compose cung cấp các đối tượng sửa đổi ảnh hưởng đến trạng thái tương tác của các thành phần trên giao diện người dùng:

  • hoverable: Định cấu hình thành phần có thể di chuột bằng cách sử dụng các sự kiện nhập và thoát bằng con trỏ.
  • indication: Vẽ các hiệu ứng hình ảnh cho thành phần này khi diễn ra hoạt động tương tác.

Tính năng chống tì tay, điều hướng và hoạt động đầu vào không mong muốn

Đôi khi, màn hình cảm ứng đa điểm có thể đăng ký những thao tác chạm không mong muốn, chẳng hạn như khi người dùng tự nhiên đặt tay lên màn hình để đỡ trong khi viết tay. Tính năng chống tì tay là cơ chế phát hiện hành vi này và thông báo cho bạn rằng tập hợp MotionEvent gần đây nhất sẽ bị huỷ.

Do đó, bạn phải lưu nhật ký hoạt động đầu vào của người dùng để những thao tác chạm không mong muốn có thể được xoá khỏi màn hình và hoạt động đầu vào hợp lệ của người dùng có thể kết xuất lại.

ACTION_CANCEL và FLAG_CANCELED

ACTION_CANCELFLAG_CANCELED là cả hai đều được thiết kế để cho bạn biết rằng tập hợp MotionEvent trước đó sẽ được bị huỷ từ ACTION_DOWN cuối cùng, để bạn có thể, ví dụ: hoàn tác nét vẽ cho ứng dụng vẽ cho một con trỏ cụ thể.

ACTION_CANCEL

Đã thêm vào Android 1.0 (API cấp 1)

ACTION_CANCEL cho biết tập hợp sự kiện chuyển động trước đó sẽ bị huỷ.

ACTION_CANCEL được kích hoạt khi phát hiện bất kỳ mục nào sau đây:

  • Cử chỉ điều hướng
  • Tính năng chống tì tay

Khi ACTION_CANCEL được kích hoạt, bạn cần xác định con trỏ đang hoạt động bằng getPointerId(getActionIndex()) Sau đó, loại bỏ nét vẽ được tạo bằng con trỏ đó khỏi nhật ký hoạt động đầu vào rồi kết xuất lại cảnh.

FLAG_CANCELED

Đã thêm vào Android 13 (API cấp 33)

FLAG_CANCELED cho biết rằng việc dịch chuyển con trỏ lên là thao tác chạm không chủ ý của người dùng. Cờ là thường được đặt khi người dùng vô tình chạm vào màn hình, chẳng hạn như bằng cách nắm chặt thiết bị hoặc đặt lòng bàn tay lên màn hình.

Bạn truy cập vào giá trị của cờ này như sau:

val cancel = (event.flags and FLAG_CANCELED) == FLAG_CANCELED

Nếu cờ này được đặt, bạn cần phải hoàn tác tập hợp MotionEvent gần đây nhất, từ ACTION_DOWN qua con trỏ này.

Giống như ACTION_CANCEL, bạn có thể tìm thấy con trỏ bằng getPointerId(actionIndex).

Hình 6. Nét vẽ bằng bút cảm ứng và thao tác chạm lòng bàn tay tạo ra tập hợp MotionEvent. Thao tác chạm lòng bàn tay bị huỷ và màn hình hiển thị được kết xuất lại.

Cử chỉ điều hướng, tràn viền và toàn màn hình

Nếu một ứng dụng ở chế độ toàn màn hình và có các phần tử có thể thao tác ở gần cạnh, chẳng hạn như canvas của một ứng dụng ghi chú hoặc bản vẽ, vuốt từ cuối màn hình để hiển thị thanh điều hướng hoặc chuyển ứng dụng vào chế độ nền có thể dẫn đến thao tác chạm không mong muốn trên canvas.

Hình 7. Cử chỉ vuốt để chuyển một ứng dụng vào nền.

Để ngăn các cử chỉ kích hoạt thao tác chạm không mong muốn trong ứng dụng của bạn, bạn có thể thực hiện tận dụng lợi thế của phần lồng ghépACTION_CANCEL.

Hãy xem thêm bài viết Tính năng chống tì tay, điều hướng và hoạt động đầu vào không mong muốn .

Sử dụng setSystemBarsBehavior()BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE trong số WindowInsetsController để ngăn các cử chỉ điều hướng gây ra sự kiện chạm không mong muốn:

// Configure the behavior of the hidden system bars.
windowInsetsController.systemBarsBehavior =
    WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE

Để tìm hiểu thêm về tính năng quản lý phần lồng ghép và cử chỉ, hãy xem:

Độ trễ thấp

Độ trễ là thời gian mà phần cứng, hệ thống và ứng dụng cần để xử lý và kết xuất hoạt động đầu vào của người dùng.

Độ trễ = thời gian xử lý hoạt động đầu vào phần cứng và hệ điều hành + xử lý ứng dụng + kết hợp hệ thống

  • kết xuất phần cứng
Độ trễ khiến nét vẽ được kết xuất bị trễ so với vị trí của bút cảm ứng. Khoảng cách giữa nét vẽ được kết xuất và vị trí của bút cảm ứng biểu thị độ trễ.
Hình 8. Độ trễ khiến nét vẽ được kết xuất bị trễ so với vị trí của bút cảm ứng.

Nguồn gây ra độ trễ

  • Đăng ký bút cảm ứng với màn hình cảm ứng (phần cứng): Kết nối không dây ban đầu khi bút cảm ứng và hệ điều hành giao tiếp với nhau để đăng ký và đồng bộ hoá.
  • Tốc độ lấy mẫu thao tác chạm (phần cứng): Số lần mỗi giây trên màn hình cảm ứng kiểm tra xem con trỏ có chạm vào bề mặt hay không, nằm trong khoảng từ 60 đến 1000 Hz.
  • Xử lý hoạt động đầu vào (ứng dụng): Áp dụng hiệu ứng màu, đồ hoạ và chuyển đổi khi người dùng nhập.
  • Kết xuất đồ hoạ (hệ điều hành + phần cứng): Hoán đổi vùng đệm, xử lý phần cứng.

Đồ hoạ có độ trễ thấp

Thư viện đồ hoạ có độ trễ thấp của Jetpack giúp giảm thời gian xử lý từ hoạt động đầu vào của người dùng đến khi kết xuất trên màn hình.

Thư viện này giúp giảm thời gian xử lý bằng cách tránh kết xuất nhiều vùng đệm và tận dụng kỹ thuật kết xuất vùng đệm trước, tức là ghi trực tiếp vào màn hình.

Kết xuất vùng đệm trước

Vùng đệm trước là bộ nhớ mà màn hình dùng để kết xuất. Đó là địa điểm gần nhất có thể vẽ trực tiếp lên màn hình. Thư viện có độ trễ thấp cho phép để kết xuất trực tiếp vào vùng đệm trước. Điều này giúp cải thiện hiệu suất bằng ngăn hoán đổi vùng đệm. Điều này có thể xảy ra khi kết xuất nhiều vùng đệm thông thường hoặc kết xuất vùng đệm kép (trường hợp phổ biến nhất).

Ứng dụng ghi vào vùng đệm màn hình và đọc từ vùng đệm màn hình.
Hình 9. Kết xuất vùng đệm trước.
Ứng dụng ghi vào nhiều vùng đệm, hoán đổi với vùng đệm màn hình. Ứng dụng đọc từ vùng đệm màn hình.
Hình 10. Kết xuất nhiều vùng đệm.

Mặc dù kết xuất vùng đệm trước là kỹ thuật tuyệt vời để kết xuất một vùng nhỏ của màn hình, nó không được thiết kế để dùng để làm mới toàn bộ màn hình. Bằng kết xuất vùng đệm trước, ứng dụng sẽ kết xuất nội dung vào một vùng đệm mà từ đó màn hình đang đọc. Kết quả là, có thể hiển thị cấu phần phần mềm hoặc xé hình (xem bên dưới).

Thư viện có độ trễ thấp được cung cấp trên Android 10 (API cấp 29) trở lên và trên thiết bị ChromeOS chạy Android 10 (API cấp 29) trở lên.

Phần phụ thuộc

Thư viện có độ trễ thấp cung cấp các thành phần để kết xuất vùng đệm trước trong quá trình triển khai. Thư viện này được thêm làm phần phụ thuộc trong mô-đun của ứng dụng Tệp build.gradle:

dependencies {
    implementation "androidx.graphics:graphics-core:1.0.0-alpha03"
}

Lệnh gọi lại GLFrontBufferRenderer

Thư viện có độ trễ thấp bao gồm GLFrontBufferRenderer.Callback giao diện, xác định các phương thức sau:

Thư viện có độ trễ thấp không có quan điểm về loại dữ liệu mà bạn sử dụng GLFrontBufferRenderer.

Tuy nhiên, thư viện này xử lý dữ liệu ở dạng luồng gồm hàng trăm điểm dữ liệu; và vì vậy, hãy thiết kế dữ liệu của bạn để tối ưu hoá việc sử dụng và phân bổ bộ nhớ.

Lệnh gọi lại

Để bật lệnh gọi lại kết xuất, hãy triển khai GLFrontBufferedRenderer.Callback và ghi đè onDrawFrontBufferedLayer()onDrawDoubleBufferedLayer(). GLFrontBufferedRenderer dùng các lệnh gọi lại để kết xuất dữ liệu của bạn theo cách hiệu quả nhất tối ưu nhất có thể.

val callback = object: GLFrontBufferedRenderer.Callback<DATA_TYPE> {
   override fun onDrawFrontBufferedLayer(
       eglManager: EGLManager,
       bufferInfo: BufferInfo,
       transform: FloatArray,
       param: DATA_TYPE
   ) {
       // OpenGL for front buffer, short, affecting small area of the screen.
   }
   override fun onDrawMultiDoubleBufferedLayer(
       eglManager: EGLManager,
       bufferInfo: BufferInfo,
       transform: FloatArray,
       params: Collection<DATA_TYPE>
   ) {
       // OpenGL full scene rendering.
   }
}
Khai báo một thực thể của GLFrontBufferedRenderer

Chuẩn bị GLFrontBufferedRenderer bằng cách cung cấp SurfaceView và các lệnh gọi lại mà bạn đã tạo trước đó. GLFrontBufferedRenderer tối ưu hoá quá trình kết xuất vào vùng đệm trước và vùng đệm kép thông qua các lệnh gọi lại:

var glFrontBufferRenderer = GLFrontBufferedRenderer<DATA_TYPE>(surfaceView, callbacks)
Kết xuất

Quá trình kết xuất tại vùng đệm trước bắt đầu khi bạn gọi hàm renderFrontBufferedLayer() để kích hoạt lệnh gọi lại onDrawFrontBufferedLayer().

Quá trình kết xuất vùng đệm kép sẽ tiếp tục khi bạn gọi phương thức commit() , kích hoạt lệnh gọi lại onDrawMultiDoubleBufferedLayer().

Trong ví dụ bên dưới, quá trình này sẽ kết xuất vào vùng đệm trước (nhanh kết xuất) khi người dùng bắt đầu vẽ trên màn hình (ACTION_DOWN) và di chuyển con trỏ xung quanh (ACTION_MOVE). Quá trình này kết xuất vào vùng đệm kép khi con trỏ rời khỏi bề mặt màn hình (ACTION_UP).

Bạn có thể sử dụng requestUnbufferedDispatch() để yêu cầu hệ thống đầu vào không phân lô các sự kiện chuyển động mà gửi các sự kiện đó ngay khi có sẵn:

when (motionEvent.action) {
   MotionEvent.ACTION_DOWN -> {
       // Deliver input events as soon as they arrive.
       view.requestUnbufferedDispatch(motionEvent)
       // Pointer is in contact with the screen.
       glFrontBufferRenderer.renderFrontBufferedLayer(DATA_TYPE)
   }
   MotionEvent.ACTION_MOVE -> {
       // Pointer is moving.
       glFrontBufferRenderer.renderFrontBufferedLayer(DATA_TYPE)
   }
   MotionEvent.ACTION_UP -> {
       // Pointer is not in contact in the screen.
       glFrontBufferRenderer.commit()
   }
   MotionEvent.CANCEL -> {
       // Cancel front buffer; remove last motion set from the screen.
       glFrontBufferRenderer.cancel()
   }
}

Việc nên làm và không nên làm khi kết xuất

✓ Nên

Các phần nhỏ của màn hình, viết tay, vẽ, phác thảo.

➜ Không nên

Cập nhật ở chế độ toàn màn hình, kéo, thu phóng. Có thể dẫn đến hiện tượng xé hình.

Xé hình

Hiện tượng xé hình xảy ra khi màn hình làm mới trong lúc vùng đệm màn hình đang được sửa đổi cùng một lúc. Một phần của màn hình cho thấy dữ liệu mới, trong khi một phần khác cho thấy dữ liệu cũ.

Các phần phía trên và dưới của hình ảnh Android bị lệch do hiện tượng xé hình khi làm mới màn hình.
Hình 11. Hiện tượng xé hình khi màn hình được làm mới từ trên xuống dưới.

Dự đoán chuyển động

Dự đoán chuyển động của Jetpack thư viện sẽ giúp giảm độ trễ dự kiến bằng cách ước tính đường vẽ của người dùng và đưa ra kết quả tạm thời, điểm nhân tạo vào trình kết xuất.

Thư viện dự đoán chuyển động nhận hoạt động đầu vào thực của người dùng ở dạng đối tượng MotionEvent. Các đối tượng này chứa thông tin về toạ độ x và y, áp suất và thời gian, tính năng này được công cụ dự đoán chuyển động tận dụng để dự đoán MotionEvent trong tương lai .

Các đối tượng MotionEvent được dự đoán chỉ là giá trị ước tính. Số sự kiện được dự đoán có thể giảm độ trễ dự kiến, nhưng dữ liệu dự đoán phải được thay thế bằng MotionEvent thực tế sau khi nhận được.

Thư viện dự đoán chuyển động có trên Android 4.4 (API cấp 19) và cao hơn và trên thiết bị ChromeOS chạy Android 9 (API cấp 28) trở lên.

Độ trễ khiến nét vẽ được kết xuất bị trễ so với vị trí của bút cảm ứng. Khoảng cách giữa nét vẽ và bút cảm ứng được lấp đầy bằng các điểm dự đoán. Khoảng cách còn lại là độ trễ dự kiến.
Hình 12. Độ trễ giảm nhờ thư viện dự đoán chuyển động.

Phần phụ thuộc

Thư viện dự đoán chuyển động cung cấp phương thức triển khai tính năng dự đoán. Chiến lược phát hành đĩa đơn thêm thư viện làm phần phụ thuộc trong tệp build.gradle của mô-đun ứng dụng:

dependencies {
    implementation "androidx.input:input-motionprediction:1.0.0-beta01"
}

Triển khai

Thư viện dự đoán chuyển động bao gồm MotionEventPredictor giao diện, xác định các phương thức sau:

  • record(): Lưu trữ các đối tượng MotionEvent ở dạng bản ghi thao tác của người dùng
  • predict(): Trả về MotionEvent được dự đoán
Khai báo một thực thể của MotionEventPredictor
var motionEventPredictor = MotionEventPredictor.newInstance(view)
Cung cấp dữ liệu cho công cụ dự đoán
motionEventPredictor.record(motionEvent)
Dự đoán

when (motionEvent.action) {
   MotionEvent.ACTION_MOVE -> {
       val predictedMotionEvent = motionEventPredictor?.predict()
       if(predictedMotionEvent != null) {
            // use predicted MotionEvent to inject a new artificial point
       }
   }
}

Việc nên làm và không nên làm khi dự đoán chuyển động

✓ Nên

Loại bỏ các điểm dự đoán khi một điểm dự đoán mới được thêm vào.

➜ Không nên

Không dùng các điểm dự đoán cho hoạt động kết xuất cuối cùng.

Ứng dụng ghi chú

ChromeOS cho phép ứng dụng của bạn khai báo một số thao tác ghi chú.

Để đăng ký một ứng dụng làm ứng dụng ghi chú trên ChromeOS, hãy xem bài viết Phương thức nhập khả năng tương thích.

Để đăng ký một ứng dụng làm ghi chú trên Android, hãy xem bài viết Tạo ghi chú ứng dụng.

Android 14 (API cấp 34), đã ra mắt ACTION_CREATE_NOTE ý định, cho phép ứng dụng của bạn bắt đầu một hoạt động ghi chú trên khoá màn hình.

Nhận dạng mực kỹ thuật số bằng Bộ công cụ học máy

Bằng mực kỹ thuật số cho Bộ công cụ học máy nhận dạng, ứng dụng của bạn có thể nhận dạng văn bản viết tay trên một bề mặt kỹ thuật số trong hàng trăm ngôn ngữ. Bạn cũng có thể phân loại các bản phác thảo.

Bộ công cụ học máy cung cấp Ink.Stroke.Builder để tạo các đối tượng Ink mà các mô hình học máy có thể xử lý để chuyển đổi chữ viết tay thành văn bản.

Ngoài tính năng nhận dạng chữ viết tay, mô hình này còn có thể nhận dạng cử chỉ, chẳng hạn như xoá và khoanh tròn.

Xem bài viết Mực kỹ thuật số nhận dạng để tìm hiểu thêm.

Tài nguyên khác

Hướng dẫn cho nhà phát triển

Lớp học lập trình