Android i ChromeOS oferują różne interfejsy API, które pomagają tworzyć aplikacje zapewniające użytkownikom niezwykłą wygodę korzystania z rysika. Klasa MotionEvent
udostępnia informacje o korzystaniu z rysika z ekranem, w tym o naciskaniu rysika, orientacji, przechyleniu, najeżdżaniu kursorem i wykrywaniu dłoni. Grafika i biblioteki przewidywania ruchu z małym opóźnieniem ulepszają renderowanie rysikiem na ekranie, zapewniając efekt przypominający pióro i papier.
MotionEvent
Klasa MotionEvent
reprezentuje interakcje użytkownika, takie jak pozycja i ruch wskaźników dotykowych na ekranie. W przypadku wpisywania rysika MotionEvent
pokazuje też dane dotyczące nacisku, orientacji, przechylenia i najechania kursorem.
Dane zdarzenia
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) }
}
}
},
)
}
Obiekt MotionEvent
dostarcza dane związane z tymi aspektami zdarzenia interfejsu:
- Działania: fizyczna interakcja z urządzeniem – dotykanie ekranu, przesuwanie wskaźnika nad powierzchnią ekranu, najeżdżanie kursorem na powierzchnię ekranu
- Wskaźniki: identyfikatory obiektów wchodzących w interakcję z ekranem – palec, styl, mysz
- Oś: typ danych – współrzędne X i Y, ciśnienie, przechylenie, orientacja i ukierunkowanie (odległość)
działania.
Aby wdrożyć obsługę rysika, musisz wiedzieć, jakie działanie wykonuje użytkownik.
MotionEvent
udostępnia szeroki zakres stałych ACTION
, które definiują zdarzenia ruchu. Najważniejsze działania związane z rysikiem to:
Działanie | Opis |
---|---|
ACTION_DOWN ACTION_POINTER_DOWN |
Wskaźnik dotknął ekranu. |
ACTION_MOVE | Wskaźnik porusza się po ekranie. |
ACTION_UP ACTION_POINTER_UP |
Wskaźnik nie styka się już z ekranem |
ACTION_CANCEL | Poprzedni lub obecny ruch ma zostać anulowany. |
Aplikacja może wykonywać zadania takie jak uruchamianie nowego pociągnięcia (ACTION_DOWN
), rysowanie linii za pomocą ACTION_MOVE,
i kończenie kreski po uruchomieniu ACTION_UP
.
Zbiór działań MotionEvent
(od ACTION_DOWN
do ACTION_UP
) dla danego wskaźnika nazywany jest zestawem ruchu.
Wskaźniki
Większość ekranów jest obsługujących wielodotyk: system przypisuje wskaźnik do każdego palca, stylu, myszy i innego obiektu wskazującego, które wchodzi w interakcję z ekranem. Indeks wskaźnika pozwala uzyskać informacje o osi dla określonego wskaźnika, np. położenie pierwszego palca dotykającego ekranu lub drugiego.
Indeksy wskaźników mieszczą się w zakresie od 0 do liczby wskaźników zwracanych przez MotionEvent#pointerCount()
minus 1.
Dostęp do wartości osi wskaźników można uzyskać za pomocą metody getAxisValue(axis,
pointerIndex)
.
W przypadku pominięcia indeksu wskaźnika system zwraca wartość pierwszego wskaźnika – wskaźnika 0 (0).
Obiekty MotionEvent
zawierają informacje o typie używanego wskaźnika. Typ wskaźnika możesz uzyskać, wykonując iterację przez indeksy i wywołując metodę getToolType(pointerIndex)
.
Więcej informacji o wskaźnikach znajdziesz w sekcji Obsługa gestów wielodotykowych.
Dane wejściowe rysika
Za pomocą TOOL_TYPE_STYLUS
możesz filtrować dane wejściowe rysika:
Kotlin
val isStylus = TOOL_TYPE_STYLUS == event.getToolType(pointerIndex)
Java
boolean isStylus = TOOL_TYPE_STYLUS == event.getToolType(pointerIndex);
Rysik może też zgłosić, że jest używany jako gumka w aplikacji TOOL_TYPE_ERASER
:
Kotlin
val isEraser = TOOL_TYPE_ERASER == event.getToolType(pointerIndex)
Java
boolean isEraser = TOOL_TYPE_ERASER == event.getToolType(pointerIndex);
Dane osi rysika
ACTION_DOWN
i ACTION_MOVE
podają dane na temat rysika, czyli współrzędne x i y, nacisk, orientację, przechylenie i najechanie kursorem.
Aby umożliwić dostęp do tych danych, interfejs API MotionEvent
udostępnia parametr getAxisValue(int)
, gdzie parametr może być dowolnym z tych identyfikatorów osi:
Axis | Zwracana wartość getAxisValue() |
---|---|
AXIS_X |
Współrzędna X zdarzenia ruchu. |
AXIS_Y |
Współrzędna Y zdarzenia ruchu. |
AXIS_PRESSURE |
W przypadku ekranu dotykowego lub touchpada nacisk wywierany przez palec, rysik lub inny wskaźnik. W przypadku myszy lub kulki ma wartość 1, gdy naciśnięty zostanie przycisk główny, lub 0, jeśli nie jest to możliwe. |
AXIS_ORIENTATION |
W przypadku ekranu dotykowego lub touchpada jest to orientacja palca, rysika lub innego wskaźnika względem pionowej płaszczyzny urządzenia. |
AXIS_TILT |
Kąt nachylenia rysika w radianach. |
AXIS_DISTANCE |
Odległość rysika od ekranu. |
Na przykład MotionEvent.getAxisValue(AXIS_X)
zwraca współrzędną x pierwszego wskaźnika.
Zobacz też Obsługiwanie gestów dotykowych.
Pozycja
Współrzędne x i y można pobierać, używając następujących wywołań:
MotionEvent#getAxisValue(AXIS_X)
lubMotionEvent#getX()
MotionEvent#getAxisValue(AXIS_Y)
lubMotionEvent#getY()
Ciśnienie
Presję wskaźnika można pobierać za pomocą funkcji MotionEvent#getAxisValue(AXIS_PRESSURE)
lub, w przypadku pierwszego wskaźnika, MotionEvent#getPressure()
.
W przypadku ekranów dotykowych lub touchpadów wartość ciśnienia jest wartością z zakresu od 0 (bez ciśnienia) do 1, ale w zależności od kalibracji ekranu mogą być zwracane wyższe wartości.
Orientacja
Orientacja wskazuje kierunek, w którym wskazuje rysik.
Orientację wskaźnika można pobrać za pomocą funkcji getAxisValue(AXIS_ORIENTATION)
lub getOrientation()
(w przypadku pierwszego wskaźnika).
W przypadku rysika orientacja jest zwracana jako wartość radiana z zakresu od 0 do pi (π) w prawo lub od 0 do -pi w lewo.
Orientacja umożliwia zastosowanie prawdziwego pędzla. Jeśli np. stylu reprezentuje płaski pędzel, szerokość pędzla płaskiego zależy od orientacji stylu.
Przechylenie
Pochylenie określa nachylenie rysika względem ekranu.
Pochylenie zwraca dodatni kąt rysika w radianach, gdzie 0 jest prostopadłe do ekranu, a π/2 jest płaska na powierzchni.
Kąt nachylenia można pobrać za pomocą funkcji getAxisValue(AXIS_TILT)
(bez skrótu do pierwszego wskaźnika).
Pochylenie pozwala odwzorować obiekt z jak największą liczbą rzeczywistych narzędzi, np. naśladować cieniowanie przechylonym ołówkiem.
Najechanie
Odległość rysika od ekranu można sprawdzić za pomocą getAxisValue(AXIS_DISTANCE)
. Zwraca wartość od 0,0 (kontakt z ekranem) do wyższych wartości, gdy rysik odsuwa się od ekranu. Odległość między ekranem a końcówką (punktem) rysika zależy od producenta ekranu i rysika. Implementacje mogą się różnić, dlatego nie polegaj na precyzyjnych wartościach kluczowych funkcji aplikacji.
Najechanie rysikiem pozwala wyświetlić podgląd rozmiaru pędzla lub wskazać przycisk, który zostanie wybrany.
Uwaga: funkcja tworzenia zawiera modyfikatory, które wpływają na interaktywny stan elementów interfejsu:
hoverable
: skonfiguruj komponent tak, aby można go najeżdżać kursorem, korzystając ze zdarzeń wejścia i wyjścia wskaźnika.indication
: rysuje efekty wizualne związane z tym komponentem w przypadku interakcji.
Odrzucenie dłoni, nawigacja i niechciane dane wejściowe
Czasami ekrany wielodotykowe mogą rejestrować niepożądane dotknięcia, np. gdy użytkownik w naturalny sposób opiera dłoń o ekran, aby uzyskać pomoc podczas pisma odręcznego.
Odrzucenie urządzenia Palm to mechanizm, który wykrywa to zachowanie i powiadamia Cię, że ostatni zestaw MotionEvent
powinien zostać anulowany.
Dlatego musisz przechowywać historię danych wejściowych użytkownika, aby możliwe było usuwanie niechcianych dotknięć z ekranu i renderowanie prawidłowych danych wejściowych użytkownika.
ACTION_CANCEL i FLAG_CANCELED
ACTION_CANCEL
i FLAG_CANCELED
informują, że poprzedni zbiór MotionEvent
powinien zostać anulowany od ostatniego ACTION_DOWN
. Dzięki temu możesz na przykład cofnąć ostatnią kreskę aplikacji do rysowania dla danego wskaźnika.
ACTION_CANCEL
Dodano w Androidzie 1.0 (poziom API 1)
ACTION_CANCEL
oznacza, że poprzedni zestaw zdarzeń ruchu ma zostać anulowany.
ACTION_CANCEL
jest wyzwalany, gdy zostanie wykryty dowolny z tych elementów:
- Gesty do nawigacji
- Odrzucenie dłoni
Po wywołaniu ACTION_CANCEL
aktywny wskaźnik należy wskazać za pomocą getPointerId(getActionIndex())
. Następnie usuń kreskę utworzoną za pomocą tego wskaźnika z historii danych wejściowych i ponownie wyrenderuj scenę.
OZNACZONE_ANULOWANIE
Dodano w Androidzie 13 (poziom API 33)
FLAG_CANCELED
oznacza, że wskaźnik w górę był niezamierzony. Flaga jest zwykle ustawiana, gdy użytkownik przypadkowo dotknie ekranu, na przykład przez chwycenie urządzenia lub położenie dłoni na ekranie.
Dostęp do wartości flagi możesz uzyskać w ten sposób:
Kotlin
val cancel = (event.flags and FLAG_CANCELED) == FLAG_CANCELED
Java
boolean cancel = (event.getFlags() & FLAG_CANCELED) == FLAG_CANCELED;
Jeśli flaga jest ustawiona, musisz cofnąć ostatnie ustawienie parametru MotionEvent
, od ostatniego ustawienia ACTION_DOWN
od tego wskaźnika.
Podobnie jak ACTION_CANCEL
, wskaźnik można znaleźć razem z elementem getPointerId(actionIndex)
.
Pełny ekran, od krawędzi do krawędzi i gesty nawigacyjne
Jeśli aplikacja jest wyświetlana na pełnym ekranie i w pobliżu krawędzi, np. obszar roboczy aplikacji do rysowania lub robienia notatek, przesunięcie palcem od dołu do góry, by wyświetlić nawigację, lub przeniesienie aplikacji w tle może spowodować niechciany gest w obszarze roboczym.
Aby zapobiec niepożądanym kliknięciom w aplikacji za pomocą gestów, możesz zastosować wstawki i ACTION_CANCEL
.
Zapoznaj się też z sekcją Odrzucenie palca, nawigacja i niechciane dane wejściowe.
Użyj metody setSystemBarsBehavior()
oraz BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
z WindowInsetsController
, aby zapobiec wywoływaniu niepożądanych zdarzeń dotknięcia za pomocą gestów nawigacyjnych:
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 );
Więcej informacji o zarządzaniu wstawianiem elementów i gestami znajdziesz tutaj:
- Ukrywanie pasków systemowych w trybie pojemnym
- Zapewnianie zgodności z nawigacją przy użyciu gestów
- Wyświetlanie treści w aplikacji od krawędzi do krawędzi
Małe opóźnienie
Opóźnienie to czas potrzebny sprzętowi, systemowi i aplikacjom na przetworzenie i wyrenderowanie danych wejściowych użytkownika.
Czas oczekiwania = przetwarzanie danych wejściowych sprzętu i systemu operacyjnego + przetwarzanie aplikacji + komponowanie systemu
- renderowanie sprzętowe
Źródło opóźnienia
- Rejestrowanie rysika na ekranie dotykowym (sprzęt): pierwsze połączenie bezprzewodowe, gdy rysik i system operacyjny komunikują się ze sobą w celu rejestracji i synchronizacji.
- Częstotliwość próbkowania dotykowego (sprzęt): liczba razy na sekundę, przez jaką ekran dotykowy sprawdza, czy wskaźnik dotyka powierzchni. Wartość z zakresu od 60 do 1000 Hz.
- Przetwarzanie danych wejściowych (aplikacja): stosowanie kolorów, efektów graficznych i przekształceń na podstawie danych wejściowych użytkownika.
- Renderowanie graficzne (system operacyjny i sprzęt): zamiana buforów, przetwarzanie sprzętowe.
Grafika z małym opóźnieniem
Biblioteka graficzna Jetpacka o małych opóźnieniach skraca czas przetwarzania między danymi wprowadzanymi przez użytkownika a renderowaniem na ekranie.
Biblioteka skraca czas przetwarzania dzięki unikaniu renderowania wielobuforowego i wykorzystywaniu techniki renderowania bufora przedniego, która oznacza zapisywanie danych bezpośrednio na ekranie.
Renderowanie z buforem przednim
Przedni bufor to pamięć używana przez ekran do renderowania. Dzięki temu aplikacje rysują bezpośrednio na ekranie. Biblioteka o małych opóźnieniach umożliwia aplikacjom renderowanie bezpośrednio w przednim buforze. Poprawia to wydajność, ponieważ zapobiega zastępowaniu buforów, co może mieć miejsce w przypadku zwykłego renderowania z użyciem wielu buforów lub podwójnego buforowania (najczęstszy przypadek).
Renderowanie z buforem przednim to świetna metoda renderowania małego obszaru ekranu, ale nie służy do odświeżania całego ekranu. W przypadku renderowania z buforem przednim aplikacja renderuje treść w buforze, z którego odczytuje wyświetlacz. W rezultacie może dojść do renderowania artefaktów lub wyrażania podrażnienia (patrz poniżej).
Biblioteka o krótkim czasie oczekiwania jest dostępna na urządzeniach z Androidem 10 (poziom interfejsu API 29) i nowszym oraz na urządzeniach z ChromeOS z Androidem 10 (poziom interfejsu API 29) lub nowszym.
Zależności
Biblioteka o małych opóźnieniach udostępnia komponenty implementacji renderowania z przodu. Biblioteka jest dodawana jako zależność w pliku build.gradle
modułu aplikacji:
dependencies {
implementation "androidx.graphics:graphics-core:1.0.0-alpha03"
}
Wywołania zwrotne GLFrontBufferRenderer
Biblioteka o małych opóźnieniach zawiera interfejs GLFrontBufferRenderer.Callback
, który definiuje te metody:
Biblioteka o małym czasie oczekiwania nie zależy od typu danych używanych w GLFrontBufferRenderer
.
Biblioteka przetwarza je jako strumień setek punktów danych, więc zaprojektuj dane tak, aby zoptymalizować wykorzystanie pamięci i jej przydzielanie.
Wywołania zwrotne
Aby włączyć wywołania zwrotne renderowania, zaimplementuj funkcję GLFrontBufferedRenderer.Callback
i zastąp onDrawFrontBufferedLayer()
i onDrawDoubleBufferedLayer()
.
GLFrontBufferedRenderer
używa wywołań zwrotnych, aby renderować dane w najbardziej zoptymalizowany sposób.
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. } };
Deklarowanie instancji GLFrontBufferedRenderer
Przygotuj GLFrontBufferedRenderer
, podając utworzone wcześniej SurfaceView
i wywołania zwrotne. GLFrontBufferedRenderer
optymalizuje renderowanie na początku i podwójny bufor przy użyciu wywołań zwrotnych:
Kotlin
var glFrontBufferRenderer = GLFrontBufferedRenderer<DATA_TYPE>(surfaceView, callbacks)
Java
GLFrontBufferedRenderer<DATA_TYPE> glFrontBufferRenderer = new GLFrontBufferedRenderer<DATA_TYPE>(surfaceView, callbacks);
Renderowanie
Renderowanie bufora przedniego rozpoczyna się po wywołaniu metody renderFrontBufferedLayer()
, która wywołuje wywołanie zwrotne onDrawFrontBufferedLayer()
.
Renderowanie z podwójnym buforem jest wznawiane po wywołaniu funkcji commit()
, która uruchomi wywołanie zwrotne onDrawMultiDoubleBufferedLayer()
.
W poniższym przykładzie proces renderuje się w przedniej części bufora (szybkie renderowanie), gdy użytkownik zaczyna rysować na ekranie (ACTION_DOWN
), a potem przesuwa wskaźnik (ACTION_MOVE
). Proces renderuje się w podwójnym buforze, gdy wskaźnik opuszcza powierzchnię ekranu (ACTION_UP
).
Możesz użyć metody requestUnbufferedDispatch()
, aby poprosić, aby system wejściowych nie grupował zdarzeń ruchu, a zamiast nich wysyłał je, gdy tylko są dostępne:
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; }
Co robić, a czego nie robić
Niewielkie fragmenty ekranu, pismo odręczne, rysowanie, szkicowanie.
Aktualizacja na pełnym ekranie, przesunięcie, powiększenie. Może to spowodować rozdarcie.
Łzawienie
Rozdarcie pojawia się, gdy ekran odświeża się, gdy jednocześnie modyfikowany jest bufor ekranu. W jednej części ekranu widoczne są nowe dane, a w innej stare dane.
Przewidywanie ruchu
Biblioteka prognozowania ruchu Jetpacka zmniejsza postrzegane opóźnienie, szacując ścieżkę ruchu użytkownika i dostarczając tymczasowe, sztuczne punkty do mechanizmu renderowania.
Biblioteka prognoz ruchu pobiera dane wejściowe użytkownika jako obiekty MotionEvent
.
Obiekty zawierają informacje o współrzędnych x i y, ciśnieniu i czasie, które są wykorzystywane przez funkcję prognozowania ruchu do przewidywania przyszłych obiektów MotionEvent
.
Prognozowane obiekty (MotionEvent
) są tylko szacunkowe. Prognozowane zdarzenia mogą zmniejszyć postrzegane czasy oczekiwania, ale dane prognozowane muszą zostać zastąpione rzeczywistymi danymi MotionEvent
po ich otrzymaniu.
Biblioteka prognoz ruchu jest dostępna na urządzeniach z Androidem 4.4 (poziom interfejsu API 19) i nowszym oraz na urządzeniach z ChromeOS z Androidem 9 (poziom interfejsu API 28) lub nowszym.
Zależności
Biblioteka prognoz ruchu umożliwia ich implementację. Biblioteka jest dodawana jako zależność w pliku build.gradle
modułu aplikacji:
dependencies {
implementation "androidx.input:input-motionprediction:1.0.0-beta01"
}
Implementacja
Biblioteka prognoz ruchu zawiera interfejs MotionEventPredictor
, który definiuje te metody:
record()
: przechowuje obiektyMotionEvent
jako rejestr działań użytkownikapredict()
: Zwraca przewidywaną wartośćMotionEvent
Zadeklaruj wystąpienie elementu MotionEventPredictor
Kotlin
var motionEventPredictor = MotionEventPredictor.newInstance(view)
Java
MotionEventPredictor motionEventPredictor = MotionEventPredictor.newInstance(surfaceView);
Podaj dane prognozy
Kotlin
motionEventPredictor.record(motionEvent)
Java
motionEventPredictor.record(motionEvent);
Prognoza
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; }
Co należy, a czego nie należy robić w przypadku prognozowania ruchu
Po dodaniu nowego punktu prognozy usuń punkty prognozy.
Nie używaj punktów prognozy do końcowego renderowania.
Notatki
ChromeOS umożliwia aplikacji deklarowanie niektórych działań związanych z notatkami.
Aby zarejestrować aplikację w ChromeOS jako aplikację do robienia notatek, zapoznaj się z artykułem Zgodność urządzeń wejściowych.
Informacje o tym, jak zarejestrować aplikację na Androidzie jako aplikację do sporządzania notatek, znajdziesz w artykule Tworzenie aplikacji do notatek.
W Androidzie 14 (poziom interfejsu API 34) wprowadziliśmy intencję ACTION_CREATE_NOTE
, która umożliwia aplikacji rozpoczynanie robienia notatek na ekranie blokady.
Cyfrowe rozpoznawanie tuszu za pomocą ML Kit
Dzięki cyfrowemu rozpoznawaniu pisma cyfrowego ML Kit aplikacja rozpoznaje odręczny tekst na cyfrowej powierzchni w setkach języków. Możesz też klasyfikować szkice.
ML Kit udostępnia klasę Ink.Stroke.Builder
umożliwiającą tworzenie obiektów Ink
, które mogą być przetwarzane przez modele systemów uczących się w celu konwertowania pisma odręcznego na tekst.
Oprócz rozpoznawania pisma odręcznego model rozpoznaje gesty takie jak usunięcie czy zakreślenie.
Więcej informacji znajdziesz w sekcji Cyfrowe rozpoznawanie tuszu.
Dodatkowe materiały
Przewodniki dla programistów
- Tworzenie aplikacji do robienia notatek
- Rozpoznawanie tuszu cyfrowego za pomocą ML Kit na Androidzie