কম্পোজ দিয়ে এক হাতে অঙ্গভঙ্গি


Wear OS 7 (API লেভেল 37) এবং এর পরবর্তী সংস্করণগুলোতে, Compose for Wear OS-এর অন্তর্ভুক্ত একটি API-এর সাথে এক-হাতের জেসচার ফ্রেমওয়ার্ক ব্যবহারকারীদের আপনার অ্যাপের সাথে স্পর্শ ছাড়াই ইন্টারঅ্যাক্ট করার সুযোগ দেয়।

প্রাথমিকভাবে পিক্সেল ওয়াচ ডিভাইসগুলোতে (পিক্সেল ওয়াচ ৩ এবং পরবর্তী সংস্করণ) সমর্থিত হলেও, এই ফ্রেমওয়ার্কটি এখন সকল OEM-এর জন্য উপলব্ধ। এই API গ্রহণ করার মাধ্যমে, হার্ডওয়্যার সাপোর্টের প্রসারের সাথে সাথে আপনার অ্যাপের জেসচার সাপোর্টও ইকোসিস্টেম জুড়ে স্বয়ংক্রিয়ভাবে প্রসারিত হয়।

ইউজার ইন্টারফেসকে (UI) অতিরিক্ত তথ্যে ভারাক্রান্ত না করে ব্যবহারকারীদের উপলব্ধ জেসচারগুলো খুঁজে পেতে সাহায্য করার জন্য, Wear OS ফ্রেমওয়ার্ক অ্যানিমেটেড জেসচার ইন্ডিকেটর প্রদান করে। এই ভিজ্যুয়াল ইঙ্গিতগুলো তুলে ধরে যে কোথায় একটি জেসচার সম্পাদন করা যেতে পারে, এবং একই সাথে সিস্টেম ব্যবহারকারীর পছন্দ অনুযায়ী স্বয়ংক্রিয়ভাবে সেগুলোর প্রদর্শনের গতি ও নিঃশব্দ হওয়ার হার নিয়ন্ত্রণ করে।

সমর্থিত অঙ্গভঙ্গি এবং ক্রিয়া

Wear OS জেসচার ফ্রেমওয়ার্ক দুই ধরনের জেসচার সমর্থন করে:

  • প্রাথমিক ক্রিয়া (ডাবল পিঞ্চ): স্ক্রিনের প্রধান ক্রিয়াকে বোঝায়, যেমন কল রিসিভ করা বা মিডিয়া প্লেব্যাক চালু বা বন্ধ করা।
  • খারিজ করার ক্রিয়া (কব্জি ঘোরানো): এর মাধ্যমে পেছনে যাওয়া, কোনো ডায়ালগ খারিজ করা, বা কোনো প্রম্পট বাতিল করা যায়।

কম্পোজে অঙ্গভঙ্গি কনফিগার করুন

যদিও এক-হাতের জেসচার এপিআই আপনার ইউআই-কে উন্নত করতে পারে, এটা মনে রাখা জরুরি যে কিছু হার্ডওয়্যার এবং ওইএম এই জেসচারগুলো সমর্থন করে না। যদি এপিআই শনাক্ত করে যে আপনার অ্যাপটি এই ধরনের কোনো অসমর্থিত ডিভাইসে চলছে, তাহলে লাইব্রেরিটি সাধারণ টাচ ইন্টারঅ্যাকশনকে প্রভাবিত না করেই স্বয়ংক্রিয়ভাবে কোনো অপারেশন করে না।

সাধারণ কম্পোজ বিহেভিয়ারের মতোই, আপনি মডিফায়ার ব্যবহার করে UI এলিমেন্টগুলিতে এক-হাতের জেসচার সক্রিয় করতে পারেন। আপনি যে কাজটি করতে চান—হয় প্রাইমারি অথবা ডিসমিস—এবং সিস্টেম-স্তরের ব্যবহারকারীর পছন্দ, যেমন হিন্ট প্রদর্শনের ছন্দ এবং ফ্রিকোয়েন্সি মিউটিং-এর সাথে সমন্বয় করার জন্য একটি gestureId অনুসারে আপনার অ্যাপের জেসচারগুলি কনফিগার করেন। আপনি একটি OneHandedGestureConfiguration অবজেক্ট তৈরি করে এই কনফিগারেশনটি প্রকাশ করেন; আমরা এটি তৈরি করার জন্য rememberOneHandedGestureConfiguration ফাংশনটি ব্যবহার করার পরামর্শ দিই। OneHandedGestureConfiguration এই আপনি জেসচারের অগ্রাধিকারও নির্ধারণ করতে পারেন।

rememberOneHandedGestureConfiguration ফাংশনটি অ্যাপ্লিকেশনের স্টেট প্রকাশ না করেই রিকম্পোজিশন জুড়ে ব্যবহারকারীর ইন্টারঅ্যাকশনের ইতিহাস ট্র্যাক করে। আপনার অ্যাপ একবার কনফিগারেশনটি তৈরি করে ফেললে, সেটিকে আপনার ইন্টারেক্টিভ কম্পোজেবলের Modifier.oneHandedGesture ফাংশনে পাস করতে হবে।

ব্যবহারকারীদের উপলব্ধ জেসচারগুলো খুঁজে পেতে সাহায্য করার জন্য, লাইব্রেরিটি OneHandedGestureClickIndicator মেথডটি প্রদান করে। এই মেথডটি একটি র‍্যাপার হিসেবে কাজ করে যা এর অন্তর্নিহিত বিষয়বস্তুকে প্রতিস্থাপন করে ব্যবহারকারীকে জানিয়ে দেয় যে একটি জেসচার অ্যাকশন উপলব্ধ আছে।

ইন্টারেক্টিভ উপাদান

বাটনের মতো কোনো ইন্টারেক্টিভ কন্ট্রোলে জেসচার সক্রিয় করতে, OneHandedGestureAction.Primary উল্লেখ করে একটি কনফিগারেশন তৈরি করুন এবং oneHandedGesture মডিফায়ারটি প্রয়োগ করুন। কন্ট্রোল এবং মডিফায়ার উভয় ক্ষেত্রেই একই MutableInteractionSource পাস করুন, যাতে জেসচার ইভেন্টগুলো কন্ট্রোলে ভিজ্যুয়াল প্রেস ফিডব্যাক প্রদর্শন করে।

জেসচার ইন্ডিকেটরটি চালু করতে, OneHandedGestureClickIndicatorState এর একটি ইনস্ট্যান্স তৈরি করুন এবং সেটিকে মনে রাখুন। এরপর, ভিজ্যুয়াল ফিডব্যাক চালু করতে, oneHandedGesture মডিফায়ার দ্বারা প্রদত্ত onGestureAvailable কলব্যাকের মধ্যে showIndicator কল করুন, যা সিস্টেমকে একটি ইন্ডিকেশন ইভেন্ট ঘটার সংকেত দেয়। একবার কল করা হলে, কম্পোনেন্টটি অল্প সময়ের জন্য তার সাধারণ কন্টেন্টকে একটি জেসচার অ্যানিমেশন দিয়ে প্রতিস্থাপন করে।

var isPlaying by remember { mutableStateOf(false) }
val onClick = { isPlaying = !isPlaying }

val gestureConfig = rememberOneHandedGestureConfiguration(
    action = OneHandedGestureAction.Primary
)
val indicatorState = remember { OneHandedGestureClickIndicatorState() }
val coroutineScope = rememberCoroutineScope()
val interactionSource = remember { MutableInteractionSource() }

Button(
    onClick = onClick,
    interactionSource = interactionSource,
    modifier = Modifier
        .fillMaxWidth()
        .oneHandedGesture(
            gestureConfiguration = gestureConfig,
            interactionSource = interactionSource,
            onGestureLabel = if (isPlaying) "pause" else "play",
            onGestureAvailable = { coroutineScope.launch { indicatorState.showIndicator() } },
            onGesture = onClick
        )
) {
    OneHandedGestureClickIndicator(
        gestureConfiguration = gestureConfig,
        state = indicatorState
    ) {
        Text(if (isPlaying) "Pause" else "Play", modifier = Modifier.fillMaxWidth())
    }
}

স্ক্রোলযোগ্য কন্টেইনার

স্ক্রোলযোগ্য স্ক্রিন বা তালিকার জন্য, OneHandedGestureAction.Primary উল্লেখ করে একটি কনফিগারেশন তৈরি করুন এবং আপনার কন্টেইনারে oneHandedGesture মডিফায়ারটি প্রয়োগ করে scrollDown মতো একটি স্ক্রোলিং হেল্পার কল করুন।

স্ক্রলিং অ্যাকশনের জন্য ভিজ্যুয়াল ফিডব্যাক দিতে, আপনি OneHandedGestureScrollIndicator ব্যবহার করতে পারেন। এই কম্পোনেন্টটি একটি সাধারণ স্ক্রল ইন্ডিকেটর হিসেবে কাজ করে যা স্ক্রলের অবস্থান দেখায়, তবে এটি ব্যবহারকারীর জন্য একটি স্ক্রল জেসচার উপলব্ধ আছে তাও নির্দেশ করতে পারে। এই ইন্ডিকেটরটি সাধারণত একটি ScreenScaffold এর scrollIndicator স্লটে পাস করা হয় এবং এটি একটি স্ক্রলযোগ্য কন্টেইনারের (যেমন TransformingLazyColumn ) স্টেটের সাথে যুক্ত থাকে। এটি তার ভিজ্যুয়াল ট্রানজিশনগুলো পরিচালনা করার জন্য একটি OneHandedGestureScrollIndicatorState ও পর্যবেক্ষণ করে।

ভিজ্যুয়াল ফিডব্যাক চালু করতে, এই স্টেটে showIndicator কল করুন—সাধারণত oneHandedGesture মডিফায়ারের onGestureAvailable কলব্যাকের ভিতরে। একবার চালু হলে, ইন্ডিকেটরটি ব্যবহারকারীকে সতর্ক করার জন্য সাময়িকভাবে তার সাধারণ ভিজ্যুয়াল স্টেটকে একটি জেসচার অ্যানিমেশন সিকোয়েন্স দিয়ে প্রতিস্থাপন করে।

val scrollState = rememberTransformingLazyColumnState()
val gestureConfig = rememberOneHandedGestureConfiguration(
    action = OneHandedGestureAction.Primary,
    priority = OneHandedGesturePriority.Scrollable
)
val indicatorState = remember(gestureConfig) { OneHandedGestureScrollIndicatorState() }
val coroutineScope = rememberCoroutineScope()

ScreenScaffold(
    scrollState = scrollState,
    scrollIndicator = {
        OneHandedGestureScrollIndicator(
            gestureConfiguration = gestureConfig,
            indicatorState = indicatorState,
            scrollState = scrollState,
            modifier = Modifier.align(Alignment.CenterEnd)
        )
    }
) { contentPadding ->
    TransformingLazyColumn(
        state = scrollState,
        contentPadding = contentPadding,
        modifier = Modifier
            .fillMaxSize()
            .oneHandedGesture(
                gestureConfiguration = gestureConfig,
                onGestureLabel = "scroll",
                onGestureAvailable = {
                    coroutineScope.launch { indicatorState.showIndicator() }
                },
                onGesture = { OneHandedGestureDefaults.scrollDown(scrollState) }
            )
    ) {
        items(10) { index ->
            Text("Item $index", modifier = Modifier.padding(8.dp))
        }
    }
}

একাধিক অঙ্গভঙ্গি একত্রিত করুন

আপনার OneHandedGestureConfiguration অবজেক্টে gesturePriority যোগ করে আপনি একই প্রাথমিক অ্যাকশন দিয়ে স্ক্রোল জেসচার এবং ক্লিক জেসচার উভয়ই কনফিগার করতে পারেন:

  • OneHandedGesturePriority.Clickable (সর্বোচ্চ): Button বা Card টাইপের মতো ইন্টারেক্টিভ কন্ট্রোলগুলিতে এটি নির্ধারণ করুন, যাতে স্ক্রিনে দৃশ্যমান হলে সেগুলি জেসচার গ্রহণ করতে পারে।
  • OneHandedGesturePriority.Scrollable (মাঝারি): স্ক্রোলযোগ্য বা পেজযোগ্য কন্টেইনারে এটি প্রয়োগ করুন, যাতে সেগুলো ক্লিকযোগ্য চাইল্ড কন্টেইনারের জন্য জায়গা ছেড়ে দেয়, কিন্তু কোনো ক্লিকযোগ্য কন্ট্রোল দৃশ্যমান না থাকলে স্ক্রোল করে।
  • OneHandedGesturePriority.Unspecified (সর্বনিম্ন): একটি অনির্ধারিত অগ্রাধিকার। যে জেসচারের কোনো priority সেট করা নেই, তার জন্য এটি ডিফল্ট মান।

একটি ভেতরের বাটনে priority = OneHandedGesturePriority.Clickable এবং এর প্যারেন্ট লিস্টে priority = OneHandedGesturePriority.Scrollable স্পষ্টভাবে সেট করার মাধ্যমে, সিস্টেম এই জেসচার-প্রায়োরিটি আচরণটি প্রদর্শন করতে পারে। যখন ব্যবহারকারী এক-হাতের জেসচারের মাধ্যমে মূল কাজটি ট্রিগার করেন, তখন এটি প্রথমে লিস্টটি নিচে স্ক্রল করে বাটনটি দৃশ্যমান করে, এবং তারপর বাটনটির ক্লিক অ্যাকশনটি ক্যাপচার করে।

ADB ব্যবহার করে অঙ্গভঙ্গি পরীক্ষা ও ডিবাগ করুন

আপনি অ্যান্ড্রয়েড ডিবাগ ব্রিজ ( adb ) এবং IWearGestureService সিস্টেম সার্ভিস ব্যবহার করে, কব্জির শারীরিক নড়াচড়া না করেই কোনো ফিজিক্যাল ডিভাইস বা এমুলেটরে এক হাতের জেসচার পরীক্ষা করতে পারেন।

অঙ্গভঙ্গি সিমুলেশন সক্ষম করুন

ADB ব্যবহার করে অঙ্গভঙ্গি অনুকরণ করার আগে, আপনার ডিভাইস সেটিংস এবং সীমাবদ্ধতা ওভাররাইডগুলি কনফিগার করুন:

  1. আপনার Wear OS ডিভাইসটিতে Wear OS 7 (API লেভেল 37) বা তার উচ্চতর সংস্করণ চলছে কিনা তা যাচাই করুন:

    adb shell getprop ro.build.version.sdk
    
  2. আপনি যদি এমন কোনো ফিজিক্যাল ডিভাইসে পরীক্ষা করেন যা আপনার কব্জিতে নেই বা চার্জারে রাখা আছে, তাহলে অফ-বডি কনস্ট্রেইন্টটি ওভাররাইড করুন যাতে জেসচার ফ্রেমওয়ার্কটি সক্রিয় থাকে:

    adb shell cmd IWearGestureService override-constraints offbody-state
    

ADB ব্যবহার করে অঙ্গভঙ্গি ইভেন্ট ট্রিগার করুন

ডাবল পিঞ্চ জেসচার (যা পিক্সেল ওয়াচের Primary অ্যাকশন) অনুকরণ করতে, নিম্নলিখিত ADB শেল কমান্ডটি চালান:

adb shell cmd IWearGestureService gesture DoublePinch

কব্জি ঘোরানোর অঙ্গভঙ্গি (যা পিক্সেল ঘড়িতে Dismiss অ্যাকশন) অনুকরণ করতে, নিম্নলিখিত ADB শেল কমান্ডটি চালান:

adb shell cmd IWearGestureService gesture WristTurn

অঙ্গভঙ্গি ইঙ্গিত ট্র্যাকিং রিসেট করুন

সিস্টেমটি ব্যবহারকারীর ইন্টারঅ্যাকশনের ইতিহাস ট্র্যাক করে এবং গ্লোবাল ক্যাডেন্স সেটিং (যেমন Always বা Daily )-এর উপর ভিত্তি করে ফ্লোটিং জেসচার হিন্ট প্রদর্শন করে। আপনার অ্যাপের জেসচার ইন্ডিকেটর ডিবাগ করার সময়, এই ট্র্যাকিং হিস্ট্রিটি রিসেট করুন, যাতে আপনার প্যাকেজের জন্য হিন্টগুলো আবার দেখা যায়:

  • userdebug বিল্ড বা এমুলেটরগুলিতে:

    adb shell cmd IWearGestureService hint clear <your_package_name>
    
  • খুচরা ( user ) বিল্ডগুলিতে:

    রুট অ্যাক্সেসবিহীন বাণিজ্যিক ডিভাইসগুলিতে, সিস্টেম পারমিশনের কারণে hint clear ব্লক করা থাকে। হিন্ট ডিসকভারি রিসেট করতে অ্যাপটির লোকাল ডেটা ক্লিয়ার করুন:

    adb shell pm clear <your_package_name>
    

ডিফল্ট সীমাবদ্ধতা পুনরুদ্ধার করুন

টেস্টিং শেষ হলে সমস্ত ডিবাগ কনস্ট্রেইন্ট ওভাররাইড রিসেট করতে:

adb shell cmd IWearGestureService override-constraints reset

জেসচার ইনজেকশনের সমস্যা সমাধান করুন

যদি আপনার অ্যাপ সিমুলেটেড জেসচার গ্রহণ না করে:

  1. ঘড়ির স্ক্রিনটি সচল এবং চালু আছে কিনা তা যাচাই করুন। স্ক্রিন বন্ধ থাকলে বা অ্যাম্বিয়েন্ট মোডে থাকলে জেসচার ফ্রেমওয়ার্ক অ্যাপ্লিকেশনগুলিতে জেসচার পাঠায় না। ADB ব্যবহার করে ডিসপ্লে চালু করতে, চালান:

    adb shell input keyevent KEYCODE_WAKEUP
    
  2. আপনার অ্যাপটি একটি সক্রিয় জেসচার সাবস্ক্রাইবার হিসেবে নিবন্ধিত আছে এবং বর্তমানে উইন্ডো ফোকাস ধরে রেখেছে কিনা তা পরীক্ষা করুন:

    adb shell cmd IWearGestureService get-active-gestures -readable
    

    যখন আপনার অ্যাপের জেসচার স্ক্রিন ফোরগ্রাউন্ডে থাকে এবং স্ক্রিনটি সক্রিয় থাকে, তখন এই কমান্ডটি [DoublePinch] অথবা [DoublePinch, WristTurn] রিটার্ন করে। যদি একটি খালি তালিকা ( [] ) রিটার্ন করা হয়, তবে আপনার উইন্ডোতে ফোকাস আছে কিনা অথবা অফ-বডি কনস্ট্রেইন্ট অ্যাক্টিভেশনকে বাধা দিচ্ছে কিনা তা পরীক্ষা করুন।

  3. অভ্যন্তরীণ জেসচার সার্ভিসের অবস্থা এবং সক্রিয় সাবস্ক্রাইবার টোকেনগুলো পরিদর্শন করুন:

    adb shell dumpsys IWearGestureService
    

অতিরিক্ত সম্পদ

কখন এবং কোথায় এক-হাতের অঙ্গভঙ্গি ব্যবহার করতে হবে সে সম্পর্কে ডিজাইন নির্দেশনার জন্য, এক-হাতের অঙ্গভঙ্গি দেখুন।

{% হুবহু %} {% endverbatim %} {% হুবহু %} {% endverbatim %}