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


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

שלושת המקורות העיקריים של חוגה להזנת נתונים ברוב השעונים כוללים את הכפתור הצדדי המסתובב (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
        // ...
    }
}

פעולות בהתאמה אישית

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

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

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

class VolumeRange(
    val max: Int = 10,
    val min: Int = 0
)

private object VolumeViewModel {
    class MyViewModel : ViewModel() {
        private val _volumeState = mutableIntStateOf(0)
        val volumeState: State<Int>
            get() = _volumeState

        // ...
        fun onVolumeChangeByScroll(pixels: Float) {
            _volumeState.value = when {
                pixels > 0 -> minOf(volumeState.value + 1, VolumeRange().max)
                pixels < 0 -> maxOf(volumeState.value - 1, VolumeRange().min)
                else -> volumeState.value
            }
        }
    }
}

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

val focusRequester: FocusRequester = remember { FocusRequester() }
val volumeViewModel: VolumeViewModel.MyViewModel =
    viewModel()
val volumeState by volumeViewModel.volumeState

TransformingLazyColumn(
    modifier = Modifier
        .fillMaxSize()
        .onRotaryScrollEvent {
            volumeViewModel.onVolumeChangeByScroll(it.verticalScrollPixels)
            true
        }
        .focusRequester(focusRequester)
        .focusable(),
) {
    // You can use volumeState here, for example:
    item {
        Text("Volume: $volumeState")
    }
}

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