Kafelki mogą nie tylko wyświetlać informacje, ale też być interaktywne.
Aby element, np. textButton()
, reagował na kliknięcia, wygeneruj metodę obsługi kliknięcia za pomocą elementu clickable()
i połącz ją z elementem układu.
Możesz skonfigurować Clickable
, aby wywoływało działanie na 2 główne sposoby:
- Uruchomienie aktywności bezpośrednio: kliknij
launchAction()
, gdy chcesz otworzyć aktywność natychmiast. - Przekazywanie zadań do usługi kafelków: użyj funkcji
loadAction()
, aby wywołać logikę wTileService
. Dzięki temu możesz odświeżać zawartość kafelka, aktualizować jego stan lub uruchamiać bardziej złożoną aktywność.
Uruchamianie wyeksportowanej aktywności
Jeśli kliknięcie przez użytkownika powinno natychmiast uruchamiać działanie, użyj launchAction()
.
Podaj wartość ComponentName
, aby zidentyfikować aktywność. Aktywność musi zostać wyeksportowana. Dzięki temu możesz przekazać Intent
elementy dodatkowe podczas działania.
Nie można jednak ustawić niestandardowych flag Intent
.
Z tego przykładu dowiesz się, jak utworzyć Clickable
, aby uruchomić TileActivity
z 2 dodatkami: name
i age
:
textButton( labelContent = { text("launchAction()".layoutString, typography = BODY_LARGE) }, onClick = clickable( action = launchAction( ComponentName( "com.example.wear", "com.example.wear.snippets.m3.tile.TileActivity", ), mapOf( "name" to ActionBuilders.stringExtra("Bartholomew"), "age" to ActionBuilders.intExtra(21), ), ) ), )
W uruchomionej aktywności pobierz wartości z intent extras:
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // When this activity is launched from the tile InteractionLaunchAction, // "name" will be "Bartholomew" and "age" will be 21 val name = intent.getStringExtra("name") val age = intent.getStringExtra("age") // ... }
Obsługa interakcji w usłudze kafelka
Aby umożliwić bardziej elastyczne interakcje, użyj elementu loadAction()
. Gdy użytkownik kliknie element skonfigurowany za pomocą elementu loadAction
, system ponownie wywoła funkcję TileService.onTileRequest()
. Dzięki temu możesz uruchamiać w usłudze logikę, która aktualizuje kafelek, zmienia jego stan i wykonuje bardziej złożone zadania.
Odświeżanie zawartości kafelka
Najprostszym zastosowaniem elementu loadAction
jest sygnalizowanie odświeżenia. Wywołaj funkcję loadAction
bez argumentów. Po kliknięciu system wywołuje funkcję onTileRequest()
, co pozwala Twojej usłudze zwrócić nowy układ z aktualnymi treściami.
textButton( onClick = clickable(loadAction()), labelContent = { text("Refresh".layoutString) }, )
Różnicowanie między wieloma elementami interaktywnymi
Jeśli kafelek zawiera wiele elementów interaktywnych, możesz powiązać identyfikator za pomocą modyfikatora Clickable
:
textButton( labelContent = { text("Deep Link me!".layoutString, typography = BODY_LARGE) }, onClick = clickable(id = "foo", action = loadAction()), )
W onTileRequest()
możesz sprawdzić ten identyfikator za pomocą requestParams.currentState.lastClickableId
, aby podjąć decyzję, jakie działanie wykonać.
Przykład: uruchamianie aktywności za pomocą precyzyjnego linku
Ten schemat jest idealny do uruchamiania działań za pomocą precyzyjnego linku. Kliknięcie przez użytkownika powoduje ponowne załadowanie kafelka, a usługa sprawdza identyfikator i uruchamia nową aktywność. Aby kontrolować poziomy w steku, użyj elementu TaskStackBuilder
, aby zapewnić użytkownikom lepszą nawigację. Gdy użytkownik kliknie element, zostanie przekierowany bezpośrednio na ekran z precyzyjnym linkiem (ekran message_detail/1
na przykładzie). Ponieważ użyto .addNextIntentWithParentStack()
, aktywność nadrzędna jest również dodawana do stosu. Oznacza to, że jeśli użytkownik przesunie palcem w lewo, przejdzie do ekranu głównego aplikacji (MessageList
na przykładzie), zamiast natychmiast zamknąć kafelek. Przesunięcie palcem w drugą stronę spowoduje powrót do kafelka.
override fun onTileRequest( requestParams: RequestBuilders.TileRequest ): ListenableFuture<Tile?> { val lastClickableId = requestParams.currentState.lastClickableId if (lastClickableId == "foo") { TaskStackBuilder.create(this) .addNextIntentWithParentStack( Intent( Intent.ACTION_VIEW, "googleandroidsnippets://app/message_detail/1".toUri(), this, TileActivity::class.java, ) ) .startActivities() } // ... User didn't tap a button (either first load or tapped somewhere else) // ... }
Następnie w TileActivity
skonfiguruj nawigację zgodnie ze wzorcem googleandroidsnippets://app/message_detail/{id}
.
AppScaffold { val navController = rememberSwipeDismissableNavController() SwipeDismissableNavHost( navController = navController, startDestination = "message_list", ) { // ... composable( route = "message_detail/{id}", deepLinks = listOf( navDeepLink { uriPattern = "googleandroidsnippets://app/message_detail/{id}" } ), ) { val id = it.arguments?.getString("id") ?: "0" MessageDetails(details = "message $id") } } }
Aby ułatwić użytkownikom nawigację, użyj TaskStackBuilder
.
Gdy użytkownik kliknie element, zostanie przekierowany bezpośrednio na ekran z precyzyjnym linkiem. W tym przykładzie jest to ekran message_detail/1
. Ponieważ użyto elementu .addNextIntentWithParentStack()
, aktywność nadrzędna została również dodana do stosu. Oznacza to, że jeśli użytkownik przesunie palcem w lewo, przejdzie na ekran główny aplikacji (w tym przykładzie jest to MessageList
), zamiast od razu wrócić na kafelek. Przesunięcie palcem w drugą stronę spowoduje powrót do kafelka.
Aktualizacja stanu na kafelku
Twoja kafelka ma obiekt StateBuilders.State
, który przechowuje pary klucz-wartość i zachowuje się po ponownym załadowaniu. Aby zaktualizować ten stan, gdy użytkownik wejdzie w interakcję z płytką, możesz użyć loadAction()
.
Aby to zrobić, prześlij do loadAction()
obiekt DynamicDataMap
zawierający nowe wartości stanu.
textButton( labelContent = { text("loadAction()".layoutString, typography = BODY_LARGE) }, onClick = clickable( action = loadAction( dynamicDataMapOf( stringAppDataKey("name") mapTo "Javier", intAppDataKey("age") mapTo 37, ) ) ), )
Gdy to działanie spowoduje uruchomienie onTileRequest()
, możesz odczytać zaktualizowane dane z requestParams.currentState.stateMap
. Jest to przydatne w przypadku interakcji, które bezpośrednio modyfikują dane na kafelku, np. zwiększają licznik lub przełączają ustawienie.
override fun onTileRequest( requestParams: RequestBuilders.TileRequest ): ListenableFuture<Tile> { // When triggered by loadAction(), "name" will be "Javier", and "age" will // be 37. with(requestParams.currentState.stateMap) { val name = this[stringAppDataKey("name")] val age = this[intAppDataKey("age")] } // ... }