카드는 정보를 표시하는 것 외에도 상호작용할 수 있습니다.
textButton()
와 같은 요소가 탭에 응답하도록 하려면 clickable()
를 사용하여 클릭 핸들러를 생성하고 레이아웃 요소와 연결합니다.
다음 두 가지 기본 방법으로 Clickable
를 구성하여 작업을 트리거할 수 있습니다.
- 활동 직접 실행: 활동을 즉시 열어야 하는 경우에
launchAction()
를 사용합니다. - 카드 서비스에 위임:
loadAction()
를 사용하여TileService
내에서 로직을 트리거합니다. 이 접근 방식은 카드의 콘텐츠를 새로고침하거나, 상태를 업데이트하거나, 더 복잡한 활동을 실행할 수 있는 보다 유연한 접근 방식입니다.
내보낸 활동 실행
사용자가 탭하면 즉시 활동이 실행되어야 하는 경우 launchAction()
를 사용합니다.
활동을 식별할 ComponentName
를 제공합니다. 활동을 내보내야 합니다. 이 접근 방식을 사용하면 작업과 함께 Intent
추가 항목을 전달할 수 있습니다.
하지만 맞춤 Intent
플래그는 설정할 수 없습니다.
다음 예는 두 개의 추가 항목인 name
및 age
를 사용하여 TileActivity
를 실행하는 Clickable
를 만드는 방법을 보여줍니다.
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), ), ) ), )
실행된 활동 내에서 인텐트 추가 항목에서 값을 가져옵니다.
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") // ... }
카드 서비스에서 상호작용 처리
보다 유연한 상호작용을 위해 loadAction()
를 사용하세요. 사용자가 loadAction
로 구성된 요소를 탭하면 시스템은 TileService.onTileRequest()
를 다시 호출합니다. 이렇게 하면 서비스에서 로직을 실행하여 타일을 업데이트하고, 상태를 변경하고, 더 복잡한 작업을 실행할 수 있습니다.
카드 콘텐츠 새로고침
loadAction
의 가장 간단한 용도는 새로고침을 알리는 것입니다. 인수 없이 loadAction
를 호출합니다. 탭하면 시스템에서 onTileRequest()
를 호출하여 서비스가 업데이트된 콘텐츠가 포함된 새 레이아웃을 반환할 수 있습니다.
textButton( onClick = clickable(loadAction()), labelContent = { text("Refresh".layoutString) }, )
여러 상호작용 요소 구분
카드에 여러 개의 상호작용 요소가 포함된 경우 ID를 Clickable
수정자와 연결할 수 있습니다.
textButton( labelContent = { text("Deep Link me!".layoutString, typography = BODY_LARGE) }, onClick = clickable(id = "foo", action = loadAction()), )
onTileRequest()
내에서 requestParams.currentState.lastClickableId
를 사용하여 이 ID를 확인하여 실행할 작업을 결정할 수 있습니다.
예: 딥 링크로 활동 실행
이 패턴은 딥 링크로 활동을 실행하는 데 적합합니다. 사용자가 카드를 탭하면 카드가 새로고침되고 서비스에서 ID를 검사한 후 새 활동을 실행합니다. 백 스택을 제어하려면 TaskStackBuilder
를 사용하여 사용자에게 더 나은 탐색 환경을 제공하세요. 사용자가 요소를 탭하면 딥 링크된 화면 (예시의 message_detail/1
화면)으로 바로 이동합니다. .addNextIntentWithParentStack()
가 사용되었으므로 상위 활동도 백 스택에 추가됩니다. 즉, 사용자가 뒤로 스와이프하면 바로 카드로 종료되는 대신 앱의 기본 화면 (예: MessageList
)으로 이동합니다. 다시 스와이프하면 타일로 돌아갑니다.
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) // ... }
그런 다음 TileActivity
에서 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") } } }
TaskStackBuilder
를 사용하여 사용자에게 더 나은 탐색 환경을 제공하세요.
사용자가 요소를 탭하면 딥 링크된 화면(이 예에서는 message_detail/1
화면)으로 바로 이동합니다. .addNextIntentWithParentStack()
가 사용되었으므로 상위 활동도 백 스택에 추가됩니다. 즉, 사용자가 뒤로 스와이프하면 카드로 즉시 종료되지 않고 앱의 기본 화면(예: MessageList
)으로 이동합니다. 다시 스와이프하면 카드로 돌아갑니다.
카드 내에서 상태 업데이트
카드에는 키-값 쌍을 저장하고 새로고침 시에도 유지되는 StateBuilders.State
객체가 있습니다. loadAction()
를 사용하여 사용자가 카드와 상호작용할 때 이 상태를 업데이트할 수 있습니다.
이렇게 하려면 새 상태 값이 포함된 DynamicDataMap
를 loadAction()
에 전달합니다.
textButton( labelContent = { text("loadAction()".layoutString, typography = BODY_LARGE) }, onClick = clickable( action = loadAction( dynamicDataMapOf( stringAppDataKey("name") mapTo "Javier", intAppDataKey("age") mapTo 37, ) ) ), )
이 작업으로 인해 onTileRequest()
가 트리거되면 requestParams.currentState.stateMap
에서 업데이트된 데이터를 읽을 수 있습니다. 이는 카운터 증분 또는 설정 전환과 같이 카드의 데이터를 직접 수정하는 상호작용에 유용합니다.
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")] } // ... }