סיבוב קלט באמצעות 'כתיבה'

חוגה להזנת נתונים מתייחסת לקלט מחלקים בשעון שמסתובבים. בממוצע, המשתמשים מבצעים אינטראקציה עם השעון רק למשך כמה שניות. כדי לשפר את חוויית המשתמש, אפשר להשתמש בקלט רוטרי כדי לאפשר למשתמש לבצע במהירות משימות שונות.

שלושת המקורות העיקריים של קלט רוטורי ברוב השעונים כוללים את הלחצן הצדדי המסתובב (RSB) ואת הלוח הקדמי הפיזי או הלוח הקדמי המגעי, שהוא אזור מגע עגול סביב המסך. ההתנהגות הצפויה עשויה להשתנות בהתאם לסוג הקלט, אבל חשוב להקפיד לתמוך בקלט מסתובב בכל האינטראקציות החיוניות.

גלילה

רוב המשתמשים מצפים שאפליקציות יתמכו בתנועת הגלילה. כשהתוכן גולל במסך, כדאי לתת למשתמשים משוב חזותי בתגובה לאינטראקציות מסתובבות. משוב חזותי יכול לכלול חיווי מיקום לגלילה אנכית או חיווי דפים.

ScalingLazyColumn ו-Picker תומכים בתנועת הגלילה כברירת מחדל, כל עוד צריך למקם את הרכיבים האלה בתוך Scaffold. Scaffold מכיל את מבנה הפריסה הבסיסי של אפליקציות ל-Wear OS, וכבר יש בו מקום למחוון גלילה. כדי להציג את התקדמות הגלילה, יוצרים אינדיקטור מיקום על סמך אובייקט מצב הרשימה, כפי שמתואר בקטע הקוד הבא:

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

אפשר להגדיר התנהגות של הצמדה ל-ScalingLazyColumn באמצעות ScalingLazyColumnDefaults.snapFlingBehavior, כפי שמתואר בקטע הקוד הבא:

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

יצירת מצב מותאם אישית שמנוהל במודל התצוגה, וקריאה חוזרת (callback) בהתאמה אישית שמשמשת לעיבוד אירועי גלילה סיבוביים.

// 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)
    }
}

כדי לפשט את הדוגמה הקודמת, השתמשנו בערכים של פיקסלים שסביר להניח שהם רגישים מדי אם משתמשים בהם בפועל.

משתמשים בקריאה החוזרת (callback) אחרי שמקבלים את האירועים, כפי שמתואר בקטע הקוד הבא.

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

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