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

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

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

أنشئ حالة مخصّصة تُدار في نموذج العرض، وطريقة استدعاء مخصّصة تُستخدَم لمعالجة أحداث التمرير الدوّري.

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

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

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

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

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