টাইল শুধু তথ্য দেখানোর চেয়ে আরও অনেক কিছু করতে পারে; এটি ইন্টার্যাক্টিভও হতে পারে।
textButton()-এর মতো কোনও এলিমেন্টকে ট্যাপের মাধ্যমে প্রতিক্রিয়া জানাতে, clickable() ব্যবহার করে ক্লিক
হ্যান্ডলার তৈরি করুন এবং এটিকে লেআউট এলিমেন্টের সাথে অ্যাসোসিয়েট করুন।
দুটি প্রধান উপায়ে কোনও অ্যাকশন ট্রিগার করার জন্য আপনি Clickable কনফিগার করতে পারবেন:
- সরাসরি অ্যাক্টিভিটি লঞ্চ করা: এমন কেসের ক্ষেত্রে
launchAction()ব্যবহার করুন যেখানে আপনাকে অবিলম্বে কোনও অ্যাক্টিভিটি খুলতে হবে। - আপনার টাইল পরিষেবাতে ডেলিগেট করা: আপনার
TileService-এর মধ্যে লজিক ট্রিগার করতেloadAction()ব্যবহার করুন। এটি আরও নমনীয় পদ্ধতি যা আপনাকে টাইল কন্টেন্ট রিফ্রেশ করতে, এর স্ট্যাটাস আপডেট করতে বা আরও জটিল অ্যাক্টিভিটি লঞ্চ করতে দেয়।
এক্সপোর্ট করা অ্যাক্টিভিটি লঞ্চ করা
কোনও ব্যবহারকারী ট্যাপ করলে সাথে সাথে অ্যাক্টিভিটি লঞ্চ করতে চাইলে, 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) }, )
একাধিক ইন্ট্যার্যাক্টিভ এলিমেন্টের মধ্যে পার্থক্য করা
আপনার টাইলে একাধিক ইন্ট্যার্যাক্টিভ এলিমেন্ট থাকলে, আপনি Clickable মডিফায়ারের সাথে একটি ID
অ্যাসোসিয়েট করতে পারবেন:
textButton( labelContent = { text("Deep Link me!".layoutString, typography = BODY_LARGE) }, onClick = clickable(id = "foo", action = loadAction()), )
onTileRequest()-এর মধ্যে, কী অ্যাকশন পারফর্ম করতে হবে তা সিদ্ধান্ত নিতে আপনি
requestParams.currentState.lastClickableId ব্যবহার করে এই আইডি চেক করতে পারবেন।
উদাহরণ: ডিপ লিঙ্ক সহ অ্যাক্টিভিটি লঞ্চ করা
ডিপ লিঙ্ক সহ অ্যাক্টিভিটি লঞ্চ করার জন্য এই প্যাটার্ন আদর্শ। ব্যবহারকারী
টাইল আবার লোড করেন, আপনার পরিষেবা 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() ব্যবহার করতে পারবেন।
এটি করতে, loadAction()-এ একটি DynamicDataMap পাস করুন যাতে নতুন
স্টেট ভ্যালু থাকে।
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")] } // ... }