Compose की सुविधा के साथ रोटरी इनपुट


रोटरी इनपुट का मतलब है कि आपकी स्मार्टवॉच के उन हिस्सों से इनपुट लेना जो घूमते हैं या रोटेट होते हैं. औसतन, उपयोगकर्ता अपनी स्मार्टवॉच से इंटरैक्ट करने में कुछ ही सेकंड बिताते हैं. रोटरी इनपुट का इस्तेमाल करके, उपयोगकर्ता अनुभव को बेहतर बनाया जा सकता है. इससे उपयोगकर्ता, कई टास्क तेज़ी से पूरे कर पाते हैं.

ज़्यादातर स्मार्टवॉच में रोटरी इनपुट के तीन मुख्य सोर्स होते हैं. इनमें रोटेटिंग साइड बटन (आरएसबी) और फ़िज़िकल बेज़ल या टच बेज़ल शामिल है. टच बेज़ल, स्क्रीन के चारों ओर एक गोलाकार टच ज़ोन होता है. इनपुट के टाइप के आधार पर, उम्मीद के मुताबिक काम करने का तरीका अलग-अलग हो सकता है. हालांकि, पक्का करें कि सभी ज़रूरी इंटरैक्शन के लिए, रोटरी इनपुट की सुविधा काम करती हो.

स्क्रोल करें

ज़्यादातर उपयोगकर्ताओं को उम्मीद होती है कि ऐप्लिकेशन में स्क्रोल करने का जेस्चर काम करे. स्क्रीन पर कॉन्टेंट स्क्रोल होने पर, रोटरी इंटरैक्शन के जवाब में उपयोगकर्ताओं को विज़ुअल फ़ीडबैक दें. विज़ुअल फ़ीडबैक में, वर्टिकल स्क्रोल के लिए स्क्रोल इंडिकेटर या पेज इंडिकेटर शामिल हो सकते हैं.

ScalingLazyColumn, TransformingLazyColumn, और Picker में स्क्रोल करने के लिए, डिफ़ॉल्ट रूप से जेस्चर का इस्तेमाल किया जा सकता है. इसके लिए, आपको इन कॉम्पोनेंट को AppScaffold और ScreenScaffold के अंदर रखना होगा. साथ ही, ScreenScaffold और कॉम्पोनेंट के बीच सूची की स्थिति को पास करना होगा. जैसे, TransformingLazyColumn.

AppScaffold और ScreenScaffold, Wear OS ऐप्लिकेशन के लिए बुनियादी लेआउट स्ट्रक्चर उपलब्ध कराता है. साथ ही, इसमें स्क्रोल इंडिकेटर के लिए पहले से ही एक स्लॉट होता है, जिसमें डिफ़ॉल्ट तौर पर लागू होने वाला स्क्रोल इंडिकेटर होता है. स्क्रोलिंग की प्रोग्रेस को पसंद के मुताबिक बनाने के लिए, सूची की स्थिति वाले ऑब्जेक्ट के आधार पर स्क्रोल इंडिकेटर बनाएं. इसके लिए, यहां दिया गया कोड स्निपेट इस्तेमाल करें:

val listState = rememberTransformingLazyColumnState()
ScreenScaffold(
    scrollState = listState,
    scrollIndicator = {
        ScrollIndicator(state = listState)
    }
) {
    // ...
}

यहां दिए गए कोड स्निपेट में दिखाए गए तरीके से, ScalingLazyColumn का इस्तेमाल करके ScalingLazyColumn के लिए स्नैप बिहेवियर कॉन्फ़िगर किया जा सकता है:ScalingLazyColumnDefaults.snapFlingBehavior

val listState = rememberScalingLazyListState()
ScreenScaffold(
    scrollState = listState,
    scrollIndicator = {
        ScrollIndicator(state = listState)
    }
) {

    val state = rememberScalingLazyListState()
    ScalingLazyColumn(
        modifier = Modifier.fillMaxWidth(),
        state = state,
        flingBehavior = ScalingLazyColumnDefaults.snapFlingBehavior(state = state)
    ) {
        // Content goes here
        // ...
    }
}

पसंद के मुताबिक की जाने वाली कार्रवाइयां

आपके पास अपने ऐप्लिकेशन में, रोटरी इनपुट के हिसाब से काम करने वाली कस्टम कार्रवाइयां बनाने का विकल्प भी होता है. उदाहरण के लिए, मीडिया ऐप्लिकेशन में ज़ूम इन और ज़ूम आउट करने या आवाज़ को कंट्रोल करने के लिए, रोटरी इनपुट का इस्तेमाल करें.

अगर आपके कॉम्पोनेंट में वॉल्यूम कंट्रोल जैसे स्क्रोलिंग इवेंट की सुविधा नहीं है, तो स्क्रोलिंग इवेंट को खुद मैनेज किया जा सकता है.

// VolumeScreen.kt

val focusRequester: FocusRequester = remember { FocusRequester() }

Column(
    modifier = Modifier
        .fillMaxSize()
        .onRotaryScrollEvent {
            // handle rotary scroll events
            true
        }
        .focusRequester(focusRequester)
        .focusable(),
) { ... }

व्यू मॉडल में मैनेज की गई कस्टम स्थिति और कस्टम कॉलबैक बनाएं. इसका इस्तेमाल रोटरी स्क्रोल इवेंट को प्रोसेस करने के लिए किया जाता है.

// VolumeViewModel.kt

object VolumeRange(
    public val max: Int = 10
    public val min: Int = 0
)

val volumeState: MutableStateFlow<Int> = ...

fun onVolumeChangeByScroll(pixels: Float) {
    volumeState.value = when {
        pixels > 0 -> min (volumeState.value + 1, VolumeRange.max)
        pixels < 0 -> max (volumeState.value - 1, VolumeRange.min)
    }
}

आसान बनाने के लिए, ऊपर दिए गए उदाहरण में पिक्सल वैल्यू का इस्तेमाल किया गया है. अगर इनका इस्तेमाल किया जाता है, तो ये ज़्यादा संवेदनशील हो सकती हैं.

इवेंट मिलने के बाद, कॉलबैक का इस्तेमाल करें. इसके लिए, यहां दिया गया स्निपेट देखें.

val focusRequester: FocusRequester = remember { FocusRequester() }
val volumeState by volumeViewModel.volumeState.collectAsState()

Column(
    modifier = Modifier
        .fillMaxSize()
        .onRotaryScrollEvent {
            volumeViewModel
                .onVolumeChangeByScroll(it.verticalScrollPixels)
            true
        }
        .focusRequester(focusRequester)
        .focusable(),
) { ... }