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


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

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

גלילה

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

הרכיבים ScalingLazyColumn, ‏ TransformingLazyColumn ו-Picker תומכים בתנועת הגלילה כברירת מחדל, כל עוד צריך למקם את הרכיבים האלה בתוך AppScaffold ו-ScreenScaffold ולהעביר את מצב הרשימה בין ScreenScaffold לבין הרכיב, כמו TransformingLazyColumn.

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

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

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

יצירת מצב מותאם אישית שמנוהל במודל התצוגה, וקריאה חוזרת (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(),
) { ... }