Mendukung fitur stilus lanjutan

Stilus ini memungkinkan pengguna berinteraksi dengan aplikasi dengan nyaman dan dengan akurasi yang tepat untuk membuat catatan, membuat sketsa, bekerja dengan aplikasi produktivitas, serta untuk bersantai dan bersenang-senang dengan game dan aplikasi hiburan.

Android dan ChromeOS menawarkan berbagai API untuk mem-build pengalaman stilus yang luar biasa ke dalam aplikasi. Class MotionEvent memberikan informasi tentang interaksi pengguna dengan layar, termasuk tekanan stilus, orientasi, kemiringan, pengarahan kursor, dan deteksi telapak tangan. Grafis latensi rendah dan library prediksi gerakan meningkatkan rendering di layar stilus untuk memberikan pengalaman seperti pena dan kertas yang alami.

MotionEvent

Class MotionEvent mewakili interaksi input pengguna seperti posisi dan gerakan pointer sentuh di layar. Untuk input stilus, MotionEvent juga menampilkan data tekanan, orientasi, kemiringan, dan pengarahan kursor.

Data peristiwa

Untuk mengakses data MotionEvent di aplikasi berbasis tampilan, siapkan onTouchListener:

Kotlin

val onTouchListener = View.OnTouchListener { view, event ->
  // Process motion event.
}

Java

View.OnTouchListener listener = (view, event) -> {
  // Process motion event.
};

Pemroses menerima objek MotionEvent dari sistem sehingga aplikasi Anda dapat memprosesnya.

Objek MotionEvent memberikan data yang terkait dengan aspek peristiwa UI berikut:

  • Tindakan: Interaksi fisik dengan perangkat—menyentuh layar, menggerakkan kursor ke permukaan layar, mengarahkan kursor ke permukaan layar
  • Pointer: ID objek yang berinteraksi dengan layar—jari, stilus, mouse
  • Sumbu: Jenis data—koordinat x dan y, tekanan, kemiringan, orientasi, dan arahkan kursor (jarak)

Tindakan

Untuk menerapkan dukungan stilus, Anda harus memahami tindakan yang dilakukan pengguna.

MotionEvent menyediakan berbagai konstanta ACTION yang menentukan peristiwa gerakan. Tindakan paling penting untuk stilus mencakup hal-hal berikut:

Tindakan Deskripsi
ACTION_DOWN
ACTION_POINTER_DOWN
Pointer telah melakukan kontak dengan layar.
ACTION_MOVE Pointer bergerak di layar.
ACTION_UP
ACTION_POINTER_UP
Pointer tidak lagi terhubung dengan layar
ACTION_CANCEL Saat kumpulan gerakan sebelumnya atau saat ini harus dibatalkan.

Aplikasi Anda dapat melakukan tugas seperti memulai goresan baru saat ACTION_DOWN terjadi, menggambar goresan dengan ACTION_MOVE,, dan menyelesaikan goresan saat ACTION_UP dipicu.

Kumpulan tindakan MotionEvent dari ACTION_DOWN hingga ACTION_UP untuk pointer tertentu disebut kumpulan gerakan.

Pointer

Sebagian besar layar multi-sentuh: sistem menetapkan pointer untuk setiap jari, stilus, mouse, atau objek pointer lainnya yang berinteraksi dengan layar. Indeks pointer memungkinkan Anda mendapatkan informasi sumbu untuk pointer tertentu, seperti posisi jari pertama yang menyentuh layar atau yang kedua.

Indeks pointer berkisar antara nol hingga jumlah pointer yang ditampilkan oleh MotionEvent#pointerCount() dikurangi 1.

Nilai sumbu pointer dapat diakses dengan metode getAxisValue(axis, pointerIndex). Jika indeks pointer dihilangkan, sistem akan mengembalikan nilai untuk pointer pertama, pointer nol (0).

Objek MotionEvent berisi informasi tentang jenis pointer yang digunakan. Anda bisa mendapatkan jenis pointer dengan melakukan iterasi melalui indeks pointer dan memanggil metode getToolType(pointerIndex).

Untuk mempelajari pointer lebih lanjut, lihat Menangani gestur multi-kontrol.

Input stilus

Anda dapat memfilter input stilus dengan TOOL_TYPE_STYLUS:

Kotlin

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

Java

boolean isStylus = TOOL_TYPE_STYLUS == event.getToolType(pointerIndex);

Stilus juga dapat melaporkan bahwa stilus digunakan sebagai penghapus dengan TOOL_TYPE_ERASER:

Kotlin

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

Java

boolean isEraser = TOOL_TYPE_ERASER == event.getToolType(pointerIndex);

Data sumbu stilus

ACTION_DOWN dan ACTION_MOVE memberikan data sumbu tentang stilus, yaitu koordinat x dan y, tekanan, orientasi, kemiringan, dan pengarahan kursor.

Untuk mengaktifkan akses ke data ini, MotionEvent API menyediakan getAxisValue(int), dengan parameternya merupakan salah satu ID sumbu berikut:

Sumbu Nilai yang ditampilkan getAxisValue()
AXIS_X Koordinat X dari suatu peristiwa gerakan.
AXIS_Y Koordinat Y dari suatu peristiwa gerakan.
AXIS_PRESSURE Untuk layar sentuh atau touchpad, tekanan diaplikasikan oleh jari, stilus, atau pointer lainnya. Untuk mouse atau trackball, 1 jika tombol utama ditekan, 0 jika sebaliknya.
AXIS_ORIENTATION Untuk layar sentuh atau touchpad, orientasi jari, stilus, atau pointer lainnya terkait dengan bidang vertikal perangkat.
AXIS_TILT Sudut kemiringan stilus dalam radian.
AXIS_DISTANCE Jarak stilus dari layar.

Misalnya, MotionEvent.getAxisValue(AXIS_X) menampilkan koordinat x untuk pointer pertama.

Lihat juga Menangani gestur multi-kontrol.

Posisi

Anda dapat mengambil koordinat x dan y pointer dengan panggilan berikut:

Gambar stilus di layar dengan koordinat x dan y yang dipetakan.
Gambar 1. Koordinat X dan y dari pointer stilus.

Tekanan

Anda dapat mengambil tekanan pointer dengan panggilan berikut:

getAxisValue(AXIS_PRESSURE) atau getPressure() untuk pointer pertama.

Nilai tekanan untuk layar sentuh atau touchpad adalah nilai antara 0 (tanpa tekanan) dan 1, tetapi nilai yang lebih tinggi dapat ditampilkan, bergantung pada kalibrasi layar.

Goresan stilus yang merepresentasikan kontinum tekanan rendah hingga tinggi. Gaya goresan sempit dan lemah di sebelah kiri, menunjukkan tekanan rendah. Goresan menjadi lebih lebar dan lebih gelap dari kiri ke kanan hingga menjadi paling luas dan paling gelap di ujung kanan, menunjukkan tekanan tertinggi.
Gambar 2. Representasi tekanan—tekanan rendah di kiri, tekanan tinggi di kanan.

Orientasi

Orientasi menunjukkan arah stilus yang ditunjuk.

Orientasi pointer dapat diambil menggunakan getAxisValue(AXIS_ORIENTATION) atau getOrientation() (untuk pointer pertama).

Untuk stilus, orientasi ditampilkan sebagai nilai radian antara 0 hingga pi (π) searah jarum jam atau 0 hingga -pi berlawanan arah jarum jam.

Orientasi memungkinkan Anda menerapkan kuas sungguhan. Misalnya, jika stilus mewakili kuas datar, lebar kuas datar bergantung pada orientasi stilus.

Gambar 3. Stilus menunjuk ke kiri sekitar minus 0,57 radian.

Kemiringan

Kemiringan mengukur kemiringan stilus relatif terhadap layar.

Kemiringan menampilkan sudut positif stilus dalam radian, dengan nol tegak lurus terhadap layar dan π/2 datar di permukaan.

Sudut kemiringan dapat diambil menggunakan getAxisValue(AXIS_TILT) (tanpa pintasan untuk pointer pertama).

Kemiringan dapat digunakan untuk mereproduksi alat di dunia nyata semirip mungkin, seperti meniru bayangan dengan pensil miring.

Stilus miring ke sekitar 40 derajat dari permukaan layar.
Gambar 4. Stilus miring sekitar 0,785 radian, atau 45 derajat dari tegak lurus.

Melayang

Jarak stilus dari layar dapat diperoleh dengan getAxisValue(AXIS_DISTANCE). Metode ini menampilkan nilai dari 0.0, kontak dengan layar, ke nilai yang lebih tinggi saat stilus bergerak menjauh dari layar. Jarak melayang antara layar dan ujung pena (titik) stilus bergantung pada produsen layar dan stilus. Karena implementasinya dapat bervariasi, jangan mengandalkan nilai yang tepat untuk fungsi yang penting bagi aplikasi.

Stilus dalam keadaan melayang dapat digunakan untuk melihat pratinjau ukuran kuas atau menunjukkan bahwa tombol akan dipilih.

Gambar 5. Stilus melayang di atas layar. Aplikasi bereaksi meskipun stilus tidak menyentuh permukaan layar.

Catatan: Compose menawarkan sekumpulan elemen pengubah untuk mengubah status elemen UI:

  • hoverable: Mengonfigurasi komponen agar dapat diarahkan menggunakan peristiwa masuk dan keluar pointer.
  • indication: Menggambar efek visual untuk komponen ini saat interaksi terjadi.

Penolakan telapak tangan, navigasi, dan input yang tidak diinginkan

Terkadang layar multi-sentuh dapat mencatat sentuhan yang tidak diinginkan, misalnya, saat pengguna secara alami meletakkan tangannya di layar untuk mendapatkan dukungan saat menulis tangan. Penolakan telapak tangan adalah mekanisme yang mendeteksi perilaku ini dan memberi tahu Anda bahwa kumpulan MotionEvent terakhir harus dibatalkan.

Oleh karena itu, Anda harus menyimpan histori input pengguna agar sentuhan yang tidak diinginkan dapat dihapus dari layar dan input pengguna yang sah dapat dirender ulang.

ACTION_CANCEL dan FLAG_CANCELED

ACTION_CANCEL dan FLAG_CANCELED dirancang untuk menginformasikan bahwa MotionEvent yang ditetapkan sebelumnya harus dibatalkan dari ACTION_DOWN terakhir sehingga Anda misalnya, dapat mengurungkan goresan terakhir untuk aplikasi menggambar untuk pointer tertentu.

ACTION_CANCEL

Ditambahkan di Android 1.0 (API level 1)

ACTION_CANCEL menunjukkan kumpulan peristiwa gerakan sebelumnya yang harus dibatalkan.

ACTION_CANCEL dipicu saat salah satu dari hal berikut terdeteksi:

  • Gestur navigasi
  • Penolakan telapak tangan

Saat ACTION_CANCEL dipicu, Anda harus mengidentifikasi pointer aktif dengan getPointerId(getActionIndex()). Kemudian, hapus goresan yang dibuat dengan pointer tersebut dari histori input, dan render ulang scene.

FLAG_CANCELED

Ditambahkan di Android 13 (API level 33)

FLAG_CANCELED menunjukkan bahwa pointer naik merupakan sentuhan yang tidak disengaja oleh pengguna. Flag ini biasanya disetel saat pengguna tanpa sengaja menyentuh layar, misalnya dengan menggenggam perangkat atau meletakkan telapak tangan di layar.

Anda mengakses nilai flag sebagai berikut:

Kotlin

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

Java

boolean cancel = (event.getFlags() & FLAG_CANCELED) == FLAG_CANCELED;

Jika tanda ini disetel, Anda harus mengurungkan kumpulan MotionEvent terakhir, dari ACTION_DOWN terakhir dari pointer ini.

Seperti ACTION_CANCEL, pointer dapat ditemukan dengan getPointerId(actionIndex).

Gambar 6. Goresan stilus dan sentuhan telapak tangan membuat kumpulan MotionEvent. Sentuhan telapak tangan dibatalkan, dan layar dirender ulang.

Gestur layar penuh, tata letak layar penuh, dan navigasi

Jika aplikasi dalam mode layar penuh dan memiliki elemen yang dapat ditindaklanjuti di dekat tepi, seperti kanvas aplikasi menggambar atau membuat catatan, menggeser dari bagian bawah layar untuk menampilkan navigasi atau memindahkan aplikasi ke latar belakang dapat mengakibatkan sentuhan yang tidak diinginkan di atas kanvas.

Gambar 7. Geser gestur untuk memindahkan aplikasi ke latar belakang.

Untuk mencegah gestur memicu sentuhan yang tidak diinginkan di aplikasi, Anda dapat memanfaatkan inset dan ACTION_CANCEL.

Lihat juga Penolakan, navigasi, dan input yang tidak diinginkan di atas.

Gunakan metode setSystemBarsBehavior() dan BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE dari WindowInsetsController untuk mencegah gestur navigasi menyebabkan peristiwa sentuh yang tidak diinginkan:

Kotlin

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

Java

// Configure the behavior of the hidden system bars.
windowInsetsController.setSystemBarsBehavior(
    WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
);

Untuk mempelajari pengelolaan inset dan gestur lebih lanjut, lihat:

Latensi rendah

Latensi adalah waktu yang dibutuhkan oleh hardware, sistem, dan aplikasi untuk memproses dan merender input pengguna.

Latensi = pemrosesan input hardware dan OS + pemrosesan aplikasi + komposisi sistem + rendering hardware

Latensi menyebabkan goresan yang dirender tertinggal di belakang posisi stilus. Jeda antara goresan yang dirender dan posisi stilus mewakili latensi.
Gambar 8. Latensi menyebabkan goresan yang dirender tertinggal di belakang posisi stilus.

Sumber latensi

  • Mendaftarkan stilus dengan layar sentuh (hardware): Koneksi nirkabel awal saat stilus dan OS berkomunikasi untuk didaftarkan dan disinkronkan.
  • Frekuensi sampling sentuhan (hardware): jumlah per detik layar sentuh akan memeriksa apakah pointer menyentuh permukaan, berkisar antara 60 hingga 1000 Hz.
  • Pemrosesan input (aplikasi): Menerapkan warna, efek grafis, dan transformasi pada input pengguna.
  • Rendering grafis (OS + hardware): Pertukaran buffer, pemrosesan hardware.

Grafis latensi rendah

Library grafis latensi rendah Jetpack mengurangi waktu pemrosesan antara input pengguna dan rendering di layar.

Library mengurangi waktu pemrosesan dengan menghindari rendering multi-buffer dan memanfaatkan teknik rendering buffer depan sehingga dapat menulis langsung ke layar.

Rendering buffer depan

Buffer depan adalah memori yang digunakan layar untuk rendering. Rendering buffer depan ini merupakan aplikasi terdekat yang bisa menggambar secara langsung ke layar. Library latensi rendah memungkinkan aplikasi merender langsung ke buffer depan. Dengan ini, performa akan meningkat dengan cara mencegah pertukaran buffering, yang dapat terjadi untuk rendering multi-buffer reguler atau rendering buffer ganda (kasus yang paling umum).

Aplikasi menulis ke buffer layar dan membaca dari buffer layar.
Gambar 9. Rendering buffering depan.
Aplikasi menulis ke multi-buffer yang ditukar dengan buffer layar. Aplikasi membaca dari buffer layar.
Gambar 10. Rendering multi-buffer.

Meskipun rendering buffer depan merupakan teknik yang baik untuk merender area kecil di layar, rendering ini tidak dirancang untuk memuat ulang seluruh layar. Dengan rendering buffer depan, aplikasi dapat merender konten ke buffer tempat layar dibaca. Karenanya, ada kemungkinan rendering artefak atau tearing (lihat di bawah).

Library latensi rendah tersedia dari Android 10 (API level 29) dan yang lebih tinggi, serta di perangkat ChromeOS yang menjalankan Android 10 (API level 29) dan yang lebih tinggi.

Dependensi

Library latensi rendah menyediakan komponen untuk implementasi rendering buffer depan. Library ini ditambahkan sebagai dependensi dalam file build.gradle modul aplikasi:

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

Callback GLFrontBufferRenderer

Library latensi rendah menyertakan antarmuka GLFrontBufferRenderer.Callback, yang menentukan metode berikut:

Library latensi rendah tidak memiliki opini terkait jenis data yang Anda gunakan dengan GLFrontBufferRenderer.

Namun, library ini akan memproses data sebagai aliran dari ratusan titik data; oleh karena itu, desain data Anda agar dapat mengoptimalkan penggunaan dan alokasi memori.

Callback

Untuk mengaktifkan callback rendering, terapkan GLFrontBufferedRenderer.Callback lalu ganti onDrawFrontBufferedLayer() dan onDrawDoubleBufferedLayer(). GLFrontBufferedRenderer menggunakan callback untuk merender data Anda dengan cara yang paling optimal.

Kotlin

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.
   }
}

Java

GLFrontBufferedRenderer.Callback<DATA_TYPE> callbacks =
    new GLFrontBufferedRenderer.Callback<DATA_TYPE>() {
        @Override
        public void onDrawFrontBufferedLayer(@NonNull EGLManager eglManager,
            @NonNull BufferInfo bufferInfo,
            @NonNull float[] transform,
            DATA_TYPE data_type) {
                // OpenGL for front buffer, short, affecting small area of the screen.
        }

    @Override
    public void onDrawDoubleBufferedLayer(@NonNull EGLManager eglManager,
        @NonNull BufferInfo bufferInfo,
        @NonNull float[] transform,
        @NonNull Collection<? extends DATA_TYPE> collection) {
            // OpenGL full scene rendering.
    }
};
Mendeklarasikan instance GLFrontBufferedRenderer

Siapkan GLFrontBufferedRenderer dengan menyediakan SurfaceView dan callback yang Anda buat sebelumnya. GLFrontBufferedRenderer mengoptimalkan rendering ke buffer depan dan ganda menggunakan callback:

Kotlin

var glFrontBufferRenderer = GLFrontBufferedRenderer<DATA_TYPE>(surfaceView, callbacks)

Java

GLFrontBufferedRenderer<DATA_TYPE> glFrontBufferRenderer =
    new GLFrontBufferedRenderer<DATA_TYPE>(surfaceView, callbacks);
Rendering

Rendering buffer depan dimulai saat Anda memanggil metode renderFrontBufferedLayer(), yang memicu callback onDrawFrontBufferedLayer().

Rendering buffer ganda akan dilanjutkan saat Anda memanggil fungsi commit() yang memicu callback onDrawMultiDoubleBufferedLayer().

Pada contoh berikut, proses dirender ke buffer depan (rendering cepat) saat pengguna mulai menggambar di layar (ACTION_DOWN) dan menggerakkan pointer (ACTION_MOVE). Proses merender ke buffer ganda saat pointer meninggalkan permukaan layar (ACTION_UP).

Anda dapat menggunakan requestUnbufferedDispatch() untuk meminta agar sistem input tidak mengelompokkan peristiwa gerakan, tetapi segera mengirimkannya setelah tersedia:

Kotlin

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()
   }
}

Java

switch (motionEvent.getAction()) {
   case MotionEvent.ACTION_DOWN: {
       // Deliver input events as soon as they arrive.
       surfaceView.requestUnbufferedDispatch(motionEvent);

       // Pointer is in contact with the screen.
       glFrontBufferRenderer.renderFrontBufferedLayer(DATA_TYPE);
   }
   break;
   case MotionEvent.ACTION_MOVE: {
       // Pointer is moving.
       glFrontBufferRenderer.renderFrontBufferedLayer(DATA_TYPE);
   }
   break;
   case MotionEvent.ACTION_UP: {
       // Pointer is not in contact in the screen.
       glFrontBufferRenderer.commit();
   }
   break;
   case MotionEvent.ACTION_CANCEL: {
       // Cancel front buffer; remove last motion set from the screen.
       glFrontBufferRenderer.cancel();
   }
   break;
}

Merendering anjuran dan larangan

Anjuran

Sebagian kecil layar, tulisan tangan, gambar, dan sketsa.

Larangan

Pembaruan layar penuh, penggeseran, zoom. Dapat mengakibatkan tearing.

Tearing

Tearing terjadi saat layar dimuat ulang saat buffer layar diubah secara bersamaan. Sebagian layar menampilkan data baru, sementara layar yang lain menampilkan data lama.

Bagian atas dan bawah gambar Android tidak sejajar karena adanya tearing saat layar dimuat ulang.
Gambar 11. Tearing terjadi saat layar dimuat ulang dari atas ke bawah.

Prediksi gerakan

Library prediksi gerakan Jetpack mengurangi latensi yang dirasakan dengan memperkirakan jalur goresan yang dibuat pengguna dan menyediakan titik buatan sementara ke perender.

Library prediksi gerakan mendapatkan input pengguna yang sebenarnya sebagai objek MotionEvent. Objek ini berisi informasi tentang koordinat x dan y, tekanan, serta waktu, yang dimanfaatkan oleh prediktor gerakan untuk memprediksi objek MotionEvent di masa mendatang.

Objek MotionEvent yang diprediksi hanyalah perkiraan. Peristiwa yang diprediksi dapat mengurangi latensi yang dirasakan, tetapi data yang diprediksi harus diganti dengan data MotionEvent sebenarnya setelah diterima.

Library prediksi gerakan tersedia mulai dari Android 4.4 (API level 19) dan yang lebih tinggi, serta di perangkat ChromeOS yang menjalankan Android 9 (API level 28) dan yang lebih tinggi.

Latensi menyebabkan goresan yang dirender tertinggal di belakang posisi stilus. Jeda antara goresan dan stilus diisi dengan titik prediksi. Jeda yang tersisa adalah latensi yang dirasakan.
Gambar 12. Latensi dikurangi oleh prediksi gerakan.

Dependensi

Library prediksi gerakan menyediakan implementasi prediksi. Library ini ditambahkan sebagai dependensi dalam file build.gradle modul aplikasi:

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

Implementasi

Library prediksi gerakan menyertakan antarmuka MotionEventPredictor yang menentukan metode berikut:

  • record(): Menyimpan objek MotionEvent sebagai catatan tindakan pengguna
  • predict(): Menampilkan prediksi MotionEvent
Deklarasikan instance MotionEventPredictor

Kotlin

var motionEventPredictor = MotionEventPredictor.newInstance(view)

Java

MotionEventPredictor motionEventPredictor = MotionEventPredictor.newInstance(surfaceView);
Melakukan feed pada prediktor menggunakan data

Kotlin

motionEventPredictor.record(motionEvent)

Java

motionEventPredictor.record(motionEvent);
Prediksi

Kotlin

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

Java

switch (motionEvent.getAction()) {
   case MotionEvent.ACTION_MOVE: {
       MotionEvent predictedMotionEvent = motionEventPredictor.predict();
       if(predictedMotionEvent != null) {
           // use predicted MotionEvent to inject a new artificial point
       }
   }
   break;
}

Anjuran dan larangan terkait gerakan

Anjuran

Hapus titik prediksi jika titik prediksi baru ditambahkan.

Larangan

Jangan gunakan titik prediksi untuk rendering akhir.

Aplikasi pencatatan

ChromeOS memungkinkan aplikasi Anda mendeklarasikan beberapa tindakan pencatatan.

Untuk mendaftarkan aplikasi sebagai aplikasi pencatat di ChromeOS, lihat Kompatibilitas input.

Untuk mendaftarkan aplikasi sebagai pembuat catatan di Android, lihat Membuat aplikasi pencatat.

Android 14 (API level 34), memperkenalkan intent ACTION_CREATE_NOTE yang memungkinkan aplikasi Anda memulai aktivitas pencatatan di layar kunci.

Pengenalan tinta digital dengan ML Kit

Dengan pengenalan tinta digital ML Kit, aplikasi Anda dapat mengenali teks tulisan tangan pada platform digital dalam ratusan bahasa. Anda juga dapat mengklasifikasikan sketsa.

ML Kit menyediakan class Ink.Stroke.Builder untuk membuat objek Ink yang dapat diproses oleh model machine learning sehingga tulisan tangan dapat dikonversi menjadi teks.

Selain pengenalan tulis tangan, model ini dapat mengenali gestur, seperti hapus dan lingkaran.

Lihat Pengenalan tinta digital untuk mempelajari lebih lanjut.

Referensi lainnya

Panduan developer

Codelab