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

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

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

גלילה

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

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

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

אפשר להגדיר התנהגות Snaps ל-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(),
) { ... }