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

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

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

स्क्रोल करें

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

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

val listState = rememberScalingLazyListState()
Scaffold(
    positionIndicator = {
        PositionIndicator(scalingLazyListState = listState)
    }
) {
    // ...
}

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

val listState = rememberScalingLazyListState()
Scaffold(
    positionIndicator = {
        PositionIndicator(scalingLazyListState = 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(),
) { ... }