کاشیها میتوانند کارهایی بیشتر از نمایش اطلاعات انجام دهند؛ آنها همچنین میتوانند تعاملی باشند.
برای اینکه عنصری مثل textButton() به تکضربها پاسخ دهد، بااستفاده از clickable() یک کنترلکننده کلیک تولید کنید و آن را با عنصر چیدمان مرتبط کنید.
میتوانید Clickable را برای راهاندازی کنش به دو روش اصلی پیکربندی کنید:
- راهاندازی مستقیم فعالیت: از
launchAction()برای مواردی که نیاز دارید فعالیت را فوراً باز کنید استفاده کنید. - واگذاری به سرویس کاشی: از
loadAction()برای راهاندازی منطق درTileServiceاستفاده کنید. این رویکرد انعطافپذیرتری است که به شما امکان میدهد محتوای کاشی را بازآوری کنید، وضعیت آن را بهروز کنید، یا فعالیت پیچیدهتری راهاندازی کنید.
راهاندازی فعالیت صادرشده
اگر تکضرب کاربر باید بلافاصله فعالیتی را راهاندازی کند، از launchAction() استفاده کنید.
برای شناسایی فعالیت، ComponentName ارائه دهید. فعالیت باید
صادر شود. با این رویکرد، میتوانید Intent مورد اضافی را با کنش ارسال کنید.
بااینحال، تنظیم پرچمهای سفارشی Intent امکانپذیر نیست.
مثال زیر نحوه ایجاد Clickable برای راهاندازی TileActivity
با دو مورد اضافی، name و 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), ), ) ), )
در فعالیت راهاندازیشده، مقادیر را از موارد اضافی هدف بازیابی کنید:
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) }, )
تشخیص تفاوت بین چند عنصر تعاملی
اگر کاشی شما حاوی چندین عنصر تعاملی است، میتوانید شناسه را با
اصلاحکننده Clickable مرتبط کنید:
textButton( labelContent = { text("Deep Link me!".layoutString, typography = BODY_LARGE) }, onClick = clickable(id = "foo", action = loadAction()), )
در onTileRequest()، میتوانید این شناسه را بااستفاده از
requestParams.currentState.lastClickableId بررسی کنید تا تصمیم بگیرید چه اقدامی انجام شود.
مثال: راهاندازی فعالیت با پیوند عمیق
این الگو برای راهاندازی فعالیت با پیوند عمیق ایدهآل است. کاربر با تکضرب زدن کاشی را مجدد بار میکند، سرویس شما شناسه را بازرسی میکند، و سپس فعالیت جدید را راهاندازی میکند. برای کنترل پشته برگشت، از 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")] } // ... }