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

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

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

स्क्रोल करें

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

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

  1. FocusRequester का इस्तेमाल करके, साफ़ तौर पर फ़ोकस का अनुरोध करें. इस्तेमाल की जाने वाली चीज़ें ज़्यादा मुश्किल मामलों, जैसे कि एक से ज़्यादा मामलों के लिए HierarchicalFocusCoordinator HorizontalPager में ScalingLazyColumns ऑब्जेक्ट.

  2. सिस्टम से मिलने वाले इवेंट को रोकने के लिए, onRotaryScrollEvent मॉडिफ़ायर जोड़ें तब जनरेट होता है, जब कोई उपयोगकर्ता क्राउन बटन को घुमाता है या स्क्रीन के चारों ओर की जगह को घुमाता है. रोटरी इवेंट इसका पिक्सल मान सेट होता है और यह वर्टिकल या हॉरिज़ॉन्टल रूप से स्क्रोल करता है. मॉडिफ़ायर भी इसमें कॉलबैक होता है, जो यह बताता है कि इवेंट हो चुका है या नहीं. साथ ही, यह इवेंट को लागू होने से रोकता है उसके माता-पिता को उपयोग कर सकते हैं.

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

    val focusRequester = rememberActiveFocusRequester()
    val coroutineScope = rememberCoroutineScope()

    ScalingLazyColumn(
        modifier = Modifier
            .onRotaryScrollEvent {
                coroutineScope.launch {
                    listState.scrollBy(it.verticalScrollPixels)
                    listState.animateScrollBy(0f)
                }
                true
            }
            .focusRequester(focusRequester)
            .focusable()
            .fillMaxSize(),
        state = listState
    ) {
        // Content goes here
        // ...
    }
}

डिस्क्रीट वैल्यू

अलग-अलग वैल्यू को अडजस्ट करने के लिए, रोटरी इंटरैक्शन का इस्तेमाल करें. जैसे, अडजस्ट करना सेटिंग में चमक या टाइम पिकर में संख्या चुनें. ऐसा करते समय अलार्म.

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

var selectedColumn by remember { mutableIntStateOf(0) }

val hoursFocusRequester = remember { FocusRequester() }
val minutesRequester = remember { FocusRequester() }
// ...
Scaffold(modifier = Modifier.fillMaxSize()) {
    Row(
        // ...
        // ...
    ) {
        // ...
        Picker(
            readOnly = selectedColumn != 0,
            modifier = Modifier.size(64.dp, 100.dp)
                .onRotaryScrollEvent {
                    coroutineScope.launch {
                        hourState.scrollBy(it.verticalScrollPixels)
                    }
                    true
                }
                .focusRequester(hoursFocusRequester)
                .focusable(),
            onSelected = { selectedColumn = 0 },
            // ...
            // ...
        )
        // ...
        Picker(
            readOnly = selectedColumn != 1,
            modifier = Modifier.size(64.dp, 100.dp)
                .onRotaryScrollEvent {
                    coroutineScope.launch {
                        minuteState.scrollBy(it.verticalScrollPixels)
                    }
                    true
                }
                .focusRequester(minutesRequester)
                .focusable(),
            onSelected = { selectedColumn = 1 },
            // ...
            // ...
        )
        LaunchedEffect(selectedColumn) {
            listOf(
                hoursFocusRequester,
                minutesRequester
            )[selectedColumn]
                .requestFocus()
        }
    }
}

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

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

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

// 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(),
) { ... }

अन्य संसाधन

हॉरोलॉजिस्ट का इस्तेमाल करें, जो एक Google ओपन सोर्स प्रोजेक्ट है. यह प्रोजेक्ट Wear OS के लिए उपलब्ध, Compose की सुविधा के साथ काम करने वाली Wear लाइब्रेरी और Wear OS के अन्य एपीआई. हॉरोलॉजिस्ट, बेहतर इस्तेमाल के लिए लागू करता है और डिवाइस से जुड़ी कई ख़ास जानकारी के बारे में जान सकते हैं.

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

ज़्यादा जानकारी के लिए, GitHub पर हॉरोलॉजिस्ट देखें.