لتحسين أداء تركيبة المكونات التفاعلية التي تستخدم
Modifier.clickable
، تم تقديم واجهات برمجة تطبيقات جديدة. تتيح واجهات برمجة التطبيقات هذه المزيد
عمليات تنفيذ Indication
فعالة، مثل التموجات.
androidx.compose.foundation:foundation:1.7.0+
و
تتضمن androidx.compose.material:material-ripple:1.7.0+
واجهة برمجة التطبيقات التالية
التغييرات:
تمّت إزالة هذا العمود |
الاستبدال |
---|---|
|
|
|
تم توفير واجهات برمجة تطبيقات ملاحظة: في هذا السياق، "مكتبات Material" يشير إلى |
|
يمكنك إجراء ذلك بإحدى طريقتين:
|
تصف هذه الصفحة تأثير تغيير السلوك وتعليمات الانتقال إلى لواجهات برمجة التطبيقات الجديدة.
تغيير السلوك
تشتمل إصدارات المكتبة التالية على تغيير في سلوك التموج:
androidx.compose.material:material:1.7.0+
androidx.compose.material3:material3:1.3.0+
androidx.wear.compose:compose-material:1.4.0+
لم تعُد هذه الإصدارات من مكتبات المواد تستخدم السمة rememberRipple()
. بدلاً من ذلك،
فإنهم يستخدمون واجهات برمجة تطبيقات التموّج الجديدة. ونتيجةً لذلك، لا يتم الاستعلام عن LocalRippleTheme
.
لذلك، إذا ضبطت LocalRippleTheme
في تطبيقك، سيتم التعامل مع Material
لن تستخدم هذه القيم.
يصف القسم التالي كيفية الرجوع مؤقتًا إلى السلوك القديم.
بدون نقل البيانات إلا أننا ننصح بالنقل إلى واجهات برمجة التطبيقات الجديدة. بالنسبة
تعليمات النقل، يُرجى الاطّلاع على نقل البيانات من rememberRipple
إلى ripple
.
والأقسام اللاحقة.
ترقية إصدار "مكتبة المواد" بدون نقل البيانات
لإزالة حظر ترقية إصدارات المكتبة، يمكنك استخدام
واجهة برمجة تطبيقات LocalUseFallbackRippleImplementation CompositionLocal
المطلوب إعدادها
مكونات Material التي يتم استخدامها للعودة إلى السلوك القديم:
CompositionLocalProvider(LocalUseFallbackRippleImplementation provides true) { MaterialTheme { App() } }
احرص على ترك هذا خارج MaterialTheme
حتى تتمكن الأمواج القديمة
عبر LocalIndication
.
توضّح الأقسام التالية كيفية الانتقال إلى واجهات برمجة التطبيقات الجديدة.
نقل البيانات من rememberRipple
إلى ripple
استخدام مكتبة Material
في حال استخدام مكتبة Material، استبدِل rememberRipple()
مباشرةً بـ
إلى ripple()
من المكتبة المقابلة. واجهة برمجة التطبيقات هذه تنشئ موجة
باستخدام القيم المستمدة من واجهات برمجة تطبيقات مظهر Material. ثم مرر
إلى Modifier.clickable
و/أو مكوّنات أخرى.
على سبيل المثال، يستخدم المقتطف التالي واجهات برمجة التطبيقات المتوقّفة نهائيًا:
Box( Modifier.clickable( onClick = {}, interactionSource = remember { MutableInteractionSource() }, indication = rememberRipple() ) ) { // ... }
عليك تعديل المقتطف أعلاه إلى:
@Composable private fun RippleExample() { Box( Modifier.clickable( onClick = {}, interactionSource = remember { MutableInteractionSource() }, indication = ripple() ) ) { // ... } }
تجدر الإشارة إلى أنّ ripple()
لم تعُد دالة قابلة للإنشاء ولا حاجة إلى استخدامها
يتم تذكرها. كما يمكن إعادة استخدامها عبر مكونات متعددة، على غرار
لذا ننصحك باستخراج إنشاء التموج إلى قيمة عالية المستوى
لحفظ التخصيصات.
تنفيذ نظام التصميم المخصص
إذا كنت تقوم بتنفيذ نظام التصميم الخاص بك، وكنت تستخدم سابقًا
rememberRipple()
مع RippleTheme
مخصص لإعداد التموج،
يجب عليك بدلاً من ذلك توفير واجهة برمجة التطبيقات الخاصة بالموجات التي تفوّض العُقدة المتكررة
تم عرض واجهات برمجة التطبيقات في material-ripple
. بعد ذلك، يمكن للمكونات استخدام تمويك الخاص
تستهلك قيم السمة بشكل مباشر. لمزيد من المعلومات، يُرجى الاطّلاع على المقالة نقل البيانات.
من RippleTheme
.
نقل البيانات من RippleTheme
إيقاف تغيير السلوك مؤقتًا
تضم مكتبات المواد سمة CompositionLocal
مؤقتة،
LocalUseFallbackRippleImplementation
، الذي يمكنك استخدامه لإعداد جميع
مكونات Material التي يتم استخدامها مرة أخرى باستخدام rememberRipple
. بهذه الطريقة،
يستمر rememberRipple
في طلب البحث عن LocalRippleTheme
.
يوضح مقتطف الرمز التالي كيفية استخدام
واجهة برمجة تطبيقات LocalUseFallbackRippleImplementation CompositionLocal
:
CompositionLocalProvider(LocalUseFallbackRippleImplementation provides true) { MaterialTheme { App() } }
إذا كنت تستخدم مظهر تطبيق مخصصًا تم إنشاؤه بالاعتماد على Material، يمكنك يجب تقديم التركيبة المحلية بأمان كجزء من موضوع التطبيق:
@OptIn(ExperimentalMaterialApi::class) @Composable fun MyAppTheme(content: @Composable () -> Unit) { CompositionLocalProvider(LocalUseFallbackRippleImplementation provides true) { MaterialTheme(content = content) } }
للمزيد من المعلومات، يمكنك الاطّلاع على مقالة ترقية إصدار مكتبة المواد بدون نقل البيانات.
استخدام RippleTheme
لإيقاف التموج لمكون معيَّن
تعرض المكتبات material
وmaterial3
لـ RippleConfiguration
LocalRippleConfiguration
، التي تتيح لك ضبط مظهر
تمويجات ضمن شجرة فرعية. لاحظ أن RippleConfiguration
و
ميزة LocalRippleConfiguration
تجريبية، وهي مخصّصة فقط لكل مكوّن.
التخصيص. لا تتوافق التخصيصات على مستوى العالم أو المظهر مع هذه
واجهات برمجة التطبيقات راجع استخدام RippleTheme
لتغيير كل التموجات بشكل عام
app للحصول على مزيد من المعلومات حول حالة الاستخدام هذه.
على سبيل المثال، يستخدم المقتطف التالي واجهات برمجة التطبيقات المتوقّفة نهائيًا:
private object DisabledRippleTheme : RippleTheme { @Composable override fun defaultColor(): Color = Color.Transparent @Composable override fun rippleAlpha(): RippleAlpha = RippleAlpha(0f, 0f, 0f, 0f) } // ... CompositionLocalProvider(LocalRippleTheme provides DisabledRippleTheme) { Button { // ... } }
عليك تعديل المقتطف أعلاه إلى:
CompositionLocalProvider(LocalRippleConfiguration provides null) { Button { // ... } }
استخدام RippleTheme
لتغيير اللون/ألفا للتموّج لمكوِّن معيَّن
كما هو موضّح في القسم السابق، RippleConfiguration
LocalRippleConfiguration
هي واجهات برمجة تطبيقات تجريبية ومخصّصة فقط
التخصيص لكل مكون.
على سبيل المثال، يستخدم المقتطف التالي واجهات برمجة التطبيقات المتوقّفة نهائيًا:
private object DisabledRippleThemeColorAndAlpha : RippleTheme { @Composable override fun defaultColor(): Color = Color.Red @Composable override fun rippleAlpha(): RippleAlpha = MyRippleAlpha } // ... CompositionLocalProvider(LocalRippleTheme provides DisabledRippleThemeColorAndAlpha) { Button { // ... } }
عليك تعديل المقتطف أعلاه إلى:
@OptIn(ExperimentalMaterialApi::class) private val MyRippleConfiguration = RippleConfiguration(color = Color.Red, rippleAlpha = MyRippleAlpha) // ... CompositionLocalProvider(LocalRippleConfiguration provides MyRippleConfiguration) { Button { // ... } }
استخدام RippleTheme
لتغيير كل التموجات في أحد التطبيقات بشكل عام
في السابق، كان بإمكانك استخدام الدالة LocalRippleTheme
لتحديد سلوك التموج
على مستوى الموضوع. وقد كانت هذه نقطة تكامل بين التخصيص
تكوين نظام التصميم المحلي والتموّج. وبدلاً من عرض وصف عام
موضوع أساسي، تعرض material-ripple
الآن createRippleModifierNode()
الأخرى. تسمح هذه الدالة لمكتبات نظام التصميم بإنشاء
تنفيذ wrapper
، التي تستعلم عن قيم الموضوع ثم تفويض
تطبيق الموجات على العقدة التي تم إنشاؤها بواسطة هذه الدالة.
يسمح هذا لأنظمة التصميم بالاستعلام المباشر عما يحتاجون إليه، وكشف أي
طبقات موضوعة قابلة للتهيئة بواسطة المستخدم في الأعلى دون الحاجة إلى التوافق مع
ما يتم تقديمه في طبقة material-ripple
. هذا التغيير أيضًا يجعل
وتوضيح الموضوع/المواصفات التي تتوافق معها التموج، حيث
واجهة برمجة التطبيقات Ripple API نفسها التي تعرّف هذا العقد، بدلاً من أن تكون ضمنيًا
مستمدة من الموضوع.
للحصول على إرشادات، يمكنك الاطّلاع على تنفيذ واجهة برمجة التطبيقات ripple في Material. واستبدال استدعاءات تركيب المواد المحلية حسب الحاجة نظام التصميم الخاص بك.
نقل البيانات من Indication
إلى IndicationNodeFactory
مرور Indication
إذا كنت تنشئ Indication
للتلاعب، مثل إنشاء
التجديف لتمريرها إلى Modifier.clickable
أو Modifier.indication
، فلا
تحتاج إلى إجراء أي تغييرات. IndicationNodeFactory
مكتسب من Indication
،
لذلك سيستمر كل شيء في التجميع والعمل.
جارٍ إنشاء Indication
.
إذا كنت بصدد إنشاء عملية تنفيذ Indication
خاصة بك، من المفترض أن تبدأ عملية نقل البيانات.
بسيطة في معظم الحالات. على سبيل المثال، ننصحك باستخدام Indication
التي تطبّق
تأثير تغيير الحجم عند الضغط:
object ScaleIndication : Indication { @Composable override fun rememberUpdatedInstance(interactionSource: InteractionSource): IndicationInstance { // key the remember against interactionSource, so if it changes we create a new instance val instance = remember(interactionSource) { ScaleIndicationInstance() } LaunchedEffect(interactionSource) { interactionSource.interactions.collectLatest { interaction -> when (interaction) { is PressInteraction.Press -> instance.animateToPressed(interaction.pressPosition) is PressInteraction.Release -> instance.animateToResting() is PressInteraction.Cancel -> instance.animateToResting() } } } return instance } } private class ScaleIndicationInstance : IndicationInstance { var currentPressPosition: Offset = Offset.Zero val animatedScalePercent = Animatable(1f) suspend fun animateToPressed(pressPosition: Offset) { currentPressPosition = pressPosition animatedScalePercent.animateTo(0.9f, spring()) } suspend fun animateToResting() { animatedScalePercent.animateTo(1f, spring()) } override fun ContentDrawScope.drawIndication() { scale( scale = animatedScalePercent.value, pivot = currentPressPosition ) { this@drawIndication.drawContent() } } }
يمكنك نقل بيانات هذا المستودع من خلال خطوتَين:
نقل بيانات "
ScaleIndicationInstance
" لتصبحDrawModifierNode
مساحة عرض واجهة برمجة التطبيقات فيDrawModifierNode
يشبه إلى حد كبيرIndicationInstance
: يعرضContentDrawScope#draw()
المكافئة من الناحية الوظيفيةIndicationInstance#drawContent()
أنت بحاجة إلى تغيير هذه الدالة، ثم تطبيق منطقcollectLatest
داخل العقدة مباشرةً، بدلاً منIndication
على سبيل المثال، يستخدم المقتطف التالي واجهات برمجة التطبيقات المتوقّفة نهائيًا:
private class ScaleIndicationInstance : IndicationInstance { var currentPressPosition: Offset = Offset.Zero val animatedScalePercent = Animatable(1f) suspend fun animateToPressed(pressPosition: Offset) { currentPressPosition = pressPosition animatedScalePercent.animateTo(0.9f, spring()) } suspend fun animateToResting() { animatedScalePercent.animateTo(1f, spring()) } override fun ContentDrawScope.drawIndication() { scale( scale = animatedScalePercent.value, pivot = currentPressPosition ) { this@drawIndication.drawContent() } } }
عليك تعديل المقتطف أعلاه إلى:
private class ScaleIndicationNode( private val interactionSource: InteractionSource ) : Modifier.Node(), DrawModifierNode { var currentPressPosition: Offset = Offset.Zero val animatedScalePercent = Animatable(1f) private suspend fun animateToPressed(pressPosition: Offset) { currentPressPosition = pressPosition animatedScalePercent.animateTo(0.9f, spring()) } private suspend fun animateToResting() { animatedScalePercent.animateTo(1f, spring()) } override fun onAttach() { coroutineScope.launch { interactionSource.interactions.collectLatest { interaction -> when (interaction) { is PressInteraction.Press -> animateToPressed(interaction.pressPosition) is PressInteraction.Release -> animateToResting() is PressInteraction.Cancel -> animateToResting() } } } } override fun ContentDrawScope.draw() { scale( scale = animatedScalePercent.value, pivot = currentPressPosition ) { this@draw.drawContent() } } }
نقل
ScaleIndication
لتنفيذIndicationNodeFactory
. نظرًا لأن نقل منطق التجميع إلى العقدة، فهو مصنع كائنه المسؤول الوحيد عن إنشاء مثيل عقدة.على سبيل المثال، يستخدم المقتطف التالي واجهات برمجة التطبيقات المتوقّفة نهائيًا:
object ScaleIndication : Indication { @Composable override fun rememberUpdatedInstance(interactionSource: InteractionSource): IndicationInstance { // key the remember against interactionSource, so if it changes we create a new instance val instance = remember(interactionSource) { ScaleIndicationInstance() } LaunchedEffect(interactionSource) { interactionSource.interactions.collectLatest { interaction -> when (interaction) { is PressInteraction.Press -> instance.animateToPressed(interaction.pressPosition) is PressInteraction.Release -> instance.animateToResting() is PressInteraction.Cancel -> instance.animateToResting() } } } return instance } }
عليك تعديل المقتطف أعلاه إلى:
object ScaleIndicationNodeFactory : IndicationNodeFactory { override fun create(interactionSource: InteractionSource): DelegatableNode { return ScaleIndicationNode(interactionSource) } override fun hashCode(): Int = -1 override fun equals(other: Any?) = other === this }
جارٍ استخدام Indication
لإنشاء IndicationInstance
في معظم الحالات، عليك استخدام Modifier.indication
لعرض Indication
المكون. ومع ذلك، في حالة نادرة، تقوم بإنشاء حساب
IndicationInstance
باستخدام rememberUpdatedInstance
، يجب تحديث
للتحقق مما إذا كانت Indication
هي IndicationNodeFactory
ولذلك يجب
استخدام طريقة أسهل. على سبيل المثال، Modifier.indication
سوف
التفويض الداخلي إلى العقدة التي تم إنشاؤها إذا كانت IndicationNodeFactory
. في حال حذف
لن يستخدم Modifier.composed
للاتصال بـ rememberUpdatedInstance
.