أزرار الرموز

تعرض أزرار الرموز الإجراءات التي يمكن للمستخدمين اتخاذها. يجب أن تستخدم أزرار الرموز رمزًا بمعنى واضح، وعادةً ما تمثل الإجراءات الشائعة أو المستخدمة بشكل متكرر.

هناك نوعان من أزرار الرموز:

  • تلقائي: يمكن لهذه الأزرار فتح عناصر أخرى، مثل قائمة أو بحث.
  • التبديل: يمكن أن تمثّل هذه الأزرار إجراءات ثنائية يمكن تفعيلها أو إيقافها، مثل "المفضّلة" أو "الإشارة المرجعية".
‫5 أزرار برموز مختلفة (الإعدادات، والمزيد، وما إلى ذلك) بعضها ممتلئ، مما يشير إلى الاختيار، وبعضها محدد.
الشكل 1. أزرار الرموز، بعضها ملوَّن بالكامل (للإشارة إلى الاختيار) وبعضها مخطَّط

مساحة عرض واجهة برمجة التطبيقات

استخدِم الدالة المركّبة IconButton لتنفيذ أزرار الرموز العادية. لإنشاء أنماط مرئية مختلفة، مثل الأنماط الممتلئة أو الممتلئة بدرجات لونية أو المحدّدة، استخدِم FilledIconButton وFilledTonalIconButton وOutlinedIconButton على التوالي.

تشمل المَعلمات الرئيسية لـ "IconButton" ما يلي:

  • ‫onClick: دالة lambda يتم تنفيذها عندما ينقر المستخدم على زر الرمز.
  • ‫enabled: قيمة منطقية تتحكّم في حالة تفعيل الزر. عندما تكون القيمة false، لا يستجيب الزر لإدخال المستخدم.
  • ‫content: المحتوى المركّب داخل الزر، ويكون عادةً Icon.

مثال أساسي: زر رمز التبديل

يوضّح لك هذا المثال كيفية تنفيذ زر رمز التبديل. يتغيّر مظهر زرّ التبديل الذي يتضمّن رمزًا استنادًا إلى ما إذا تم اختياره أو إلغاء اختياره.

@Preview
@Composable
fun ToggleIconButtonExample() {
    // isToggled initial value should be read from a view model or persistent storage.
    var isToggled by rememberSaveable { mutableStateOf(false) }

    IconButton(
        onClick = { isToggled = !isToggled }
    ) {
        Icon(
            painter = if (isToggled) painterResource(R.drawable.favorite_filled) else painterResource(R.drawable.favorite),
            contentDescription = if (isToggled) "Selected icon button" else "Unselected icon button."
        )
    }
}

نقاط رئيسية حول الرمز

  • تحدّد الدالة المركّبة ToggleIconButtonExample عنصر IconButton يمكن تفعيله أو إيقافه.
    • تنشئ الدالة mutableStateOf(false) كائن MutableState يحتوي على قيمة منطقية، تكون في البداية false. يجعل هذا isToggled عنصر احتفاظ بالحالة، ما يعني أنّ Compose يعيد تركيب واجهة المستخدم كلما تغيّرت قيمتها.
    • يضمن rememberSaveable استمرار حالة isToggled في جميع تغييرات الضبط، مثل تدوير الشاشة.
  • تحدّد دالة onClick Lambda في IconButton سلوك الزر عند النقر عليه، حيث يتم تبديل الحالة بين true وfalse.
  • تُحمّل المَعلمة painter في الدالة المركّبة Icon بشكل مشروط painterResource مختلفًا استنادًا إلى حالة isToggled. يؤدي هذا إلى تغيير المظهر المرئي للرمز.
    • إذا كانت قيمة isToggled هي true، يتم تحميل رمز القلب الممتلئ القابل للرسم.
    • إذا كانت قيمة isToggled هي false، يتم تحميل العنصر القابل للرسم على شكل قلب محدّد.
  • يتم أيضًا تعديل contentDescription في Icon استنادًا إلى حالة isToggled لتوفير معلومات مناسبة حول تسهيل الاستخدام.

النتيجة

تعرض الصورة التالية زر رمز التبديل من المقتطف السابق في حالته غير المحدّدة:

زر رمز تبديل مفضّل (قلب) في حالته غير المحدّدة (غير ممتلئ).
الشكل 2. زر تبديل "المفضّلة" في حالة عدم اختياره

مثال متقدّم: إجراءات متكرّرة عند الضغط

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

@Composable
fun MomentaryIconButton(
    unselectedImage: Int,
    selectedImage: Int,
    contentDescription: String,
    modifier: Modifier = Modifier,
    stepDelay: Long = 100L, // Minimum value is 1L milliseconds.
    onClick: () -> Unit
) {
    val interactionSource = remember { MutableInteractionSource() }
    val isPressed by interactionSource.collectIsPressedAsState()
    val pressedListener by rememberUpdatedState(onClick)

    LaunchedEffect(isPressed) {
        while (isPressed) {
            delay(stepDelay.coerceIn(1L, Long.MAX_VALUE))
            pressedListener()
        }
    }

    IconButton(
        modifier = modifier,
        onClick = onClick,
        interactionSource = interactionSource
    ) {
        Icon(
            painter = if (isPressed) painterResource(id = selectedImage) else painterResource(id = unselectedImage),
            contentDescription = contentDescription,
        )
    }
}

نقاط رئيسية حول الرمز

  • تأخذ الدالة MomentaryIconButton معلَمة unselectedImage: Int، وهي معرّف المورد القابل للرسم للرمز عندما لا يتم الضغط على الزر، وselectedImage: Int، وهي معرّف المورد القابل للرسم للرمز عندما يتم الضغط على الزر.
  • ويستخدم interactionSource لتتبُّع تفاعلات "الضغط" من المستخدم تحديدًا.
  • تكون قيمة isPressed صحيحة عندما يتم الضغط على الزر بشكل نشط وتكون خاطئة في الحالات الأخرى. عندما تكون قيمة isPressed هي true، يدخل LaunchedEffect في حلقة تكرار.
    • داخل هذه الحلقة، يتم استخدام delay (مع stepDelay) لإنشاء فواصل زمنية بين الإجراءات التي يتم تفعيلها. يضمن coerceIn أن يكون التأخير لمدة 1 مللي ثانية على الأقل لمنع التكرار اللانهائي.
    • يتم استدعاء pressedListener بعد كل تأخير داخل التكرار الحلقي. يؤدي ذلك إلى تكرار الإجراء.
  • يستخدم pressedListener دالة rememberUpdatedState لضمان أنّ دالة lambda onClick (الإجراء المطلوب تنفيذه) هي دائمًا الأحدث من آخر عملية تركيب.
  • يغيّر Icon صورته المعروضة بناءً على ما إذا كان الزر مضغوطًا حاليًا أم لا.
    • إذا كانت قيمة isPressed صحيحة، يتم عرض selectedImage.
    • وإلا، سيتم عرض unselectedImage.

بعد ذلك، استخدِم هذا الـ MomentaryIconButton في مثال. يوضّح المقتطف التالي زرَّين برموز يتحكّمان في عدّاد:

@Preview()
@Composable
fun MomentaryIconButtonExample() {
    var pressedCount by remember { mutableIntStateOf(0) }

    Row(
        modifier = Modifier.fillMaxWidth(),
        verticalAlignment = Alignment.CenterVertically
    ) {
        MomentaryIconButton(
            unselectedImage = R.drawable.fast_rewind,
            selectedImage = R.drawable.fast_rewind_filled,
            stepDelay = 100L,
            onClick = { pressedCount -= 1 },
            contentDescription = "Decrease count button"
        )
        Spacer(modifier = Modifier)
        Text("advanced by $pressedCount frames")
        Spacer(modifier = Modifier)
        MomentaryIconButton(
            unselectedImage = R.drawable.fast_forward,
            selectedImage = R.drawable.fast_forward_filled,
            contentDescription = "Increase count button",
            stepDelay = 100L,
            onClick = { pressedCount += 1 }
        )
    }
}

نقاط رئيسية حول الرمز

  • تعرض الدالة المركّبة MomentaryIconButtonExample عنصر Row يحتوي على مثيلَين من MomentaryIconButton ودالة مركّبة Text لإنشاء واجهة مستخدم لزيادة قيمة العدّاد وخفضها.
  • ويحتفظ بمتغيّر حالة pressedCount قابل للتغيير باستخدام remember وmutableIntStateOf، ويتم ضبطه على 0. عندما يتغيّر pressedCount، تتم إعادة تركيب أي دوال مركّبة تراقبه (مثل الدالة المركّبة Text) لتعكس القيمة الجديدة.
  • يؤدي النقر على أول MomentaryIconButton أو الضغط عليه مع الاستمرار إلى خفض pressedCount.
  • يزيد MomentaryIconButton الثاني pressedCount عند النقر عليه أو الضغط مع الاستمرار.
  • يستخدم كلا الزرَّين stepDelay مدتها 100 ملي ثانية، ما يعني أنّ الإجراء onClick يتكرر كل 100 ملي ثانية أثناء الضغط على الزر.

النتيجة

يعرض الفيديو التالي واجهة المستخدم مع أزرار الرموز والعدّاد:

الشكل 3. واجهة مستخدم لعدّاد يتضمّن زرَّين (علامة الجمع وعلامة الطرح) لزيادة قيمة العدّاد وخفضها

مراجع إضافية