إدخال البيانات عبر وحدة تحكُّم دورانية باستخدام Compose


من مكتبة Compose for Wear OS

يشير إدخال البيانات عبر وحدة تحكّم دورانية إلى البيانات التي يتم إدخالها من أجزاء الساعة التي تدور أو تتحرّك. في المتوسّط، يقضي المستخدمون بضع ثوانٍ فقط في التفاعل مع ساعاتهم. يمكنك تحسين تجربة المستخدم من خلال السماح له بإنجاز مهام مختلفة بسرعة باستخدام طريقة إدخال البيانات عبر وحدة تحكم دورانية.

تشمل المصادر الرئيسية الثلاثة لإدخال البيانات عبر وحدة تحكم دورانية في معظم الساعات زر الجانب الدوّار (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
            }
        }
    }
}

بعد ذلك، استخدِم دالة معاودة الاتصال عند تلقّي الأحداث، كما هو موضّح في المقتطف التالي.

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

يُرجى العِلم أنّ المثال السابق يستخدم قيم وحدات البكسل من أجل التبسيط، ومن المرجّح أن تكون هذه القيم حساسة للغاية إذا تم استخدامها فعليًا.