إنشاء تأثيرات انتقالية جميلة باستخدام ميزة Material Motion لنظام Android

1. مقدمة

التصميم المتعدد الأبعاد هو نظام لتصميم منتجات رقمية جريئة وجميلة. من خلال توحيد الأسلوب والعلامات التجارية والتفاعل والحركة في ظل مجموعة متسقة من المبادئ والمكونات، يمكن لفرق المنتجات تحقيق أكبر إمكانات التصميم.

logo_components_color_2x_web_96dp.png

تساعد المكونات المادية (MDC) المطورين على تنفيذ التصميم المتعدد الأبعاد. يضم مركز MDC، الذي أنشأه فريق من المهندسين ومصممي تجربة المستخدم في Google، عشرات من مكونات واجهة المستخدم الجميلة والعملية، وهو متاح لأجهزة Android وiOS والويب وFlutter.material.io/develop

ما هو نظام الحركة المتوافق مع Android؟

نظام Material Motion لنظام Android هو مجموعة من أنماط الانتقال داخل مكتبة MDC-Android التي يمكن أن تساعد المستخدمين في فهم التطبيق والتنقّل خلاله، كما هو موضَّح في إرشادات التصميم المتعدد الأبعاد.

في ما يلي أنماط انتقال المواد الأربعة الرئيسية:

  • تحويل الحاوية: الانتقالات بين عناصر واجهة المستخدم التي تحتوي على حاوية؛ إنشاء اتصال مرئي بين عنصرين متميزين لواجهة المستخدم عن طريق تحويل عنصر إلى آخر بسلاسة.
  • المحور المشترك: يشير إلى الانتقالات بين عناصر واجهة المستخدم التي تربطها علاقة مكانية أو تنقل. تستخدم التحويل المشترك على المحور س أو ص أو ع لتعزيز العلاقة بين العناصر.
  • التلاشي خلال: الانتقالات بين عناصر واجهة المستخدم التي لا تربطها علاقة قوية ببعضها تستخدم تلاشي متسلسل وتلاشي للداخل، بمقياس للعنصر الوارد.
  • التلاشي:يُستخدَم هذا النوع لعناصر واجهة المستخدم التي تدخل أو تخرج داخل حدود الشاشة.

توفّر مكتبة MDC-Android فئات انتقالية لهذه الأنماط تم تصميمها استنادًا إلى كل من مكتبة AndroidX Transition (androidx.transition) وإطار عمل انتقال Android (android.transition):

AndroidX

  • متوفّر في حزمة com.google.android.material.transition
  • يتوافق مع المستوى 14 من واجهة برمجة التطبيقات أو الإصدارات الأحدث
  • دعم الأجزاء وطرق العرض، ولكن لا يدعم الأنشطة أو Windows
  • تضم إصلاحات للأخطاء التي يتم نقلها إلى منصات أخرى بالإضافة إلى سلوك ثابت في مختلف مستويات واجهة برمجة التطبيقات.

إطار العمل

  • متوفّر في حزمة com.google.android.material.transition.platform
  • تتوافق مع المستوى 21 من واجهة برمجة التطبيقات أو الإصدارات الأحدث
  • إتاحة استخدام الأجزاء وطرق العرض والأنشطة وWindows
  • إصلاح الأخطاء التي لم يتم نقلها إلى الإصدار السابق وقد يختلف سلوكها في مختلف مستويات واجهة برمجة التطبيقات

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

ما الذي ستنشئه

سترشدك هذه الدروس التطبيقية حول الترميز خلال عملية إنشاء بعض عمليات النقل إلى نموذج تطبيق بريد إلكتروني Android باسم Reply (رد) باستخدام Kotlin، لتوضيح كيفية استخدام الانتقالات من مكتبة MDC-Android لتخصيص شكل ومظهر تطبيقك.

وسيتم توفير رمز التفعيل لتطبيق Reply، كما ستدمج انتقالات Material التالية في التطبيق، والتي يمكن الاطلاع عليها في ملف GIF للدرس التطبيقي حول الترميز الذي تم إكماله أدناه:

  • نقل تحويل الحاوية من قائمة عناوين البريد الإلكتروني إلى صفحة تفاصيل البريد الإلكتروني
  • نقل Container Transform من الإجراء إلى الإجراء الرئيسي (FAB) لإنشاء صفحة بريد إلكتروني.
  • نقل المحور ي المشترك من رمز البحث إلى صفحة عرض البحث
  • التلاشي خلال الانتقال بين صفحات صندوق البريد
  • نقل تحويل الحاوية من شريحة عنوان البريد الإلكتروني إلى طريقة عرض البطاقة

لم تتم إضافة نطاق إطار iframe المطلوب (youtu.be) إلى القائمة البيضاء.

المتطلبات

  • معرفة أساسية بتطوير Android وKotlin
  • استوديو Android (يمكنك تنزيله من هنا إذا لم يكن متوفّرًا لديك)
  • محاكي أو جهاز Android (متاح من خلال "استوديو Android")
  • نموذج الرمز (انظر الخطوة التالية)

ما هو تقييمك لمستوى خبرتك في إنشاء تطبيقات Android؟

حديث متوسط بارع

2. إعداد بيئة التطوير

بدء استخدام "استوديو Android"

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

الخيار 1: استنساخ تطبيق الدرس التطبيقي للمبتدئين من GitHub

لنسخ الدرس التطبيقي حول الترميز هذا من GitHub، شغِّل الأوامر التالية:

git clone https://github.com/material-components/material-components-android-motion-codelab.git
cd material-components-android-motion-codelab

الخيار 2: تنزيل ملف ZIP المتعلق بتطبيق "الدرس التطبيقي للمبتدئين"

يتوفّر تطبيق إجراء التفعيل ضمن دليل material-components-android-motion-codelab-develop.

تحميل رمز إجراء التفعيل في "استوديو Android"

  1. بعد انتهاء معالج الإعداد وظهور نافذة مرحبًا بك في استوديو Android، انقر على فتح مشروع استوديو Android حالي.

e3f200327a67a53.png

  1. انتقل إلى الدليل الذي قمت فيه بتثبيت نموذج التعليمات البرمجية وحدد نموذج الدليل لفتح المشروع.
  2. انتظِر قليلاً حتى ينشئ "استوديو Android" المشروع ويزامنه، كما هو موضّح من خلال مؤشرات النشاط أسفل نافذة "استوديو Android".
  1. في هذه المرحلة، قد يعرض "استوديو Android" بعض أخطاء الإصدار بسبب عدم توفُّر حزمة تطوير البرامج (SDK) لنظام التشغيل Android أو أدوات الإصدار، مثل الأداة الموضّحة أدناه. اتّبِع التعليمات الواردة في "استوديو Android" لتثبيت هذه العناصر أو تحديثها ومزامنة مشروعك. إذا كنت لا تزال تواجه مشاكل، يُرجى اتّباع الدليل حول تعديل أدواتك باستخدام "أداة إدارة حِزم تطوير البرامج (SDK)".

6e026ae171f5b1eb.png

التحقق من تبعيات المشروع

يجب أن يعتمد المشروع على مكتبة MDC-Android. من المفترض أن يحتوي نموذج الرمز البرمجي الذي نزّلته على هذه التبعية، ولكن لنلقي نظرة على الإعدادات للتأكّد من ذلك.

انتقِل إلى ملف build.gradle في وحدة app وتأكَّد من أنّ الجزء dependencies يتضمن تبعية على MDC-Android:

implementation 'com.google.android.material:material:1.2.0'

تشغيل تطبيق إجراء التفعيل

  1. تأكَّد من أنّ إعدادات الإصدار على يمين خيار الجهاز هي app.
  2. اضغط على الزر الأخضر تشغيل / تشغيل لإنشاء التطبيق وتشغيله.

24218d0a6ae25803.png

  1. في نافذة اختيار هدف النشر، إذا كان لديك جهاز Android مُدرَج في أجهزتك المتاحة، انتقِل إلى الخطوة 8. بخلاف ذلك، انقر على إنشاء جهاز افتراضي جديد.
  2. في شاشة اختيار الأجهزة، اختَر جهاز هاتف، مثل Pixel 3، ثم انقر على التالي.
  3. في شاشة صورة النظام، اختَر إصدارًا حديثًا من Android، ويُفضَّل أن يكون أعلى مستوى لواجهة برمجة التطبيقات. إذا لم يكن مثبتًا، انقر على رابط التنزيل الذي يظهر وأكمل عملية التنزيل.
  4. انقر على التالي.
  5. على شاشة جهاز Android الافتراضي (AVD)، اترُك الإعدادات كما هي وانقر على إنهاء.
  6. اختر جهاز Android من مربّع حوار هدف النشر.
  7. انقر على حسنًا.
  8. يعمل "استوديو Android" على إنشاء التطبيق ونشره وفتحه تلقائيًا على الجهاز الهدف.

اكتمال عملية النقل بنجاح يجب أن يكون رمز إجراء التفعيل للصفحة الرئيسية للرد قيد التشغيل في المحاكي. من المفترض أن يظهر لك البريد الوارد الذي يحتوي على قائمة بالرسائل الإلكترونية.

cc73eb0d0f779035.png

اختياري: إبطاء الصور المتحركة على الجهاز

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

الطريقة 1: أوامر ADB Shell

لإبطاء الصور المتحركة على الجهاز بعامل 10x، يمكنك تشغيل الأوامر التالية من سطر الأوامر:

adb shell settings put global window_animation_scale 10
adb shell settings put global transition_animation_scale 10
adb shell settings put global animator_duration_scale 10

لإعادة ضبط سرعة الصور المتحركة في الجهاز إلى الوضع العادي، شغِّل الطلبات التالية:

adb shell settings put global window_animation_scale 1
adb shell settings put global transition_animation_scale 1
adb shell settings put global animator_duration_scale 1

الطريقة 2: مربّع الإعدادات السريعة

بدلاً من ذلك، لإعداد مربّع الإعدادات السريعة، فعِّل أولاً "إعدادات المطوّرين" على جهازك إذا لم يسبق لك إجراء ذلك:

  1. افتح "إعدادات" الجهاز. تطبيق واحد
  2. انتقِل إلى أسفل الصفحة وانقر على "لمحة عن الجهاز في وضع المحاكاة"
  3. انتقِل إلى أسفل الصفحة وانقر سريعًا على "رقم الإصدار". إلى أن يتم تفعيل إعدادات المطوّر

بعد ذلك، اتّبِع الخطوات التالية ضمن "الإعدادات" في الجهاز لتفعيل مربّع الإعدادات السريعة:

  1. النقر على رمز البحث أو شريط البحث في أعلى الشاشة
  2. اكتب "المربّعات". في حقل البحث
  3. انقر على "مربّعات مطوّري الإعدادات السريعة". صف واحد
  4. انقر على "مقياس رسم نافذة النافذة" المبدل (Switch)

أخيرًا، خلال الدرس التطبيقي حول الترميز، اسحب مركز إشعارات النظام من أعلى الشاشة واستخدِم رمز c7e3f98200023f6a.png للتبديل بين الصور المتحركة بالسرعة البطيئة والعادية.

3- التعرّف على نموذج رمز التطبيق

لنلقِ نظرة على الرمز. لقد وفّرنا تطبيقًا يستخدم مكتبة مكوِّن التنقل في Jetpack للتنقل بين بعض الأجزاء المختلفة، وكل ذلك ضمن نشاط واحد، وهو MainActivity:

  • HomeFragment: لعرض قائمة بالرسائل الإلكترونية
  • EmailFragment: يعرض رسالة إلكترونية واحدة كاملة
  • ComposeFragment: يتيح إنشاء رسالة إلكترونية جديدة.
  • SearchFragment: يعرض طريقة عرض بحث

أولاً، لفهم طريقة إعداد الرسم البياني للتنقّل في التطبيق، افتح navigation_graph.xml في دليل app -> src -> main -> res -> navigation:

<navigation xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:app="http://schemas.android.com/apk/res-auto"
   android:id="@+id/navigation_graph"
   app:startDestination="@id/homeFragment">

   <fragment
       android:id="@+id/homeFragment"
       android:name="com.materialstudies.reply.ui.home.HomeFragment"
       android:label="HomeFragment">
       <argument...>
       <action
           android:id="@+id/action_homeFragment_to_emailFragment"
           app:destination="@id/emailFragment" />
   </fragment>
   <fragment
       android:id="@+id/emailFragment"
       android:name="com.materialstudies.reply.ui.email.EmailFragment"
       android:label="EmailFragment">
       <argument...>
   </fragment>
   <fragment
       android:id="@+id/composeFragment"
       android:name="com.materialstudies.reply.ui.compose.ComposeFragment"
       android:label="ComposeFragment">
       <argument...>
   </fragment>
   <fragment
       android:id="@+id/searchFragment"
       android:name="com.materialstudies.reply.ui.search.SearchFragment"
       android:label="SearchFragment" />
   <action
       android:id="@+id/action_global_homeFragment"
       app:destination="@+id/homeFragment"
       app:launchSingleTop="true"
       app:popUpTo="@+id/navigation_graph"
       app:popUpToInclusive="true"/>
   <action
       android:id="@+id/action_global_composeFragment"
       app:destination="@+id/composeFragment" />
   <action
       android:id="@+id/action_global_searchFragment"
       app:destination="@+id/searchFragment" />
</navigation>

لاحظ كيفية توفُّر جميع الأجزاء المذكورة أعلاه، من خلال ضبط جزء التشغيل التلقائي على HomeFragment من خلال app:startDestination="@id/homeFragment". يوفر تعريف XML هذا للرسم البياني لوجهة الأجزاء، بالإضافة إلى الإجراءات، رمز تنقل Kotlin الذي تم إنشاؤه والذي ستواجهه عند ربط عمليات الانتقال.

activity_main.xml

بعد ذلك، ألقِ نظرة على تنسيق activity_main.xml في الدليل app -> src -> main -> res -> layout. سيظهر لك NavHostFragment الذي تم إعداده مع الرسم البياني للتنقل أعلاه:

<fragment
   android:id="@+id/nav_host_fragment"
   android:name="androidx.navigation.fragment.NavHostFragment"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   app:defaultNavHost="true"
   app:navGraph="@navigation/navigation_graph"/>

يملأ NavHostFragment الشاشة ويعالج جميع تغييرات التنقّل في أجزاء ملء الشاشة في التطبيق. يتم وضع BottomAppBar وFloatingActionButton المرتبط بها أيضًا باللغة activity_main.xml أعلى الجزء الحالي الذي يعرضه NavHostFragment، وبالتالي سيتم إظهارهما أو إخفاءهما بناءً على وجهة الجزء من خلال نموذج رمز التطبيق المقدَّم.

بالإضافة إلى ذلك، إنّ "BottomNavDrawerFragment" في "activity_main.xml" هو درج سفلي يحتوي على قائمة للتنقّل بين صناديق البريد الإلكتروني المختلفة، ويتم عرضها بشكل مشروط من خلال زر "شعار الرد على BottomAppBar".

MainActivity.kt

وأخيرًا، للاطّلاع على مثال على إجراء تنقُّل قيد الاستخدام، افتح MainActivity.kt في الدليل app -> src -> main -> java -> com.materialstudies.reply.ui. حدِّد موقع الدالة navigateToSearch()، التي يُفترض أن تظهر على النحو التالي:

private fun navigateToSearch() {
   val directions = SearchFragmentDirections.actionGlobalSearchFragment()
   findNavController(R.id.nav_host_fragment).navigate(directions)
}

يوضّح هذا كيفية الانتقال إلى صفحة عرض البحث، بدون أيّ انتقال مخصّص. خلال هذا الدرس التطبيقي حول الترميز، ستتعمق في قسم MainActivity في Reply وأربعة أجزاء رئيسية لإعداد انتقالات Material التي تعمل جنبًا إلى جنب مع إجراءات التنقل المختلفة في جميع أنحاء التطبيق.

والآن بعد أن تعرفت على رمز إجراء التفعيل، لنبدأ في تنفيذ أول عملية انتقال.

4. إضافة نقل الحاوية من قائمة عناوين البريد الإلكتروني إلى صفحة تفاصيل البريد الإلكتروني

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

قبل إضافة أي رمز، حاول تشغيل تطبيق Reply والنقر على رسالة إلكترونية. يجب أن يتم الانتقال سريعًا، أي يتم استبدال الشاشة بدون انتقال:

f0e8a92eb2216bce.gif

ابدأ بإضافة سمة transitionName على MaterialCardView في email_item_layout.xml كما هو موضّح في المقتطف التالي:

email_item_layout.xml

android:transitionName="@{@string/email_card_transition_name(email.id)}"

يوجد اسم الانتقال في مورد سلسلة مع معلمة. يجب استخدام معرّف كل عنوان بريد إلكتروني لضمان أن تكون كل transitionName في EmailFragment فريدة.

الآن بعد أن تم تعيين اسم انتقال عنصر قائمة عناوين البريد الإلكتروني، لنفعل الشيء نفسه في تنسيق تفاصيل البريد الإلكتروني. في fragment_email.xml، اضبط transitionName من MaterialCardView على مورد السلسلة التالي:

fragment_email.xml

android:transitionName="@string/email_card_detail_transition_name"

في HomeFragment.kt، استبدِل الرمز في onEmailClicked بالمقتطف أدناه لإنشاء عملية الربط من عرض البدء (عنصر قائمة عناوين البريد الإلكتروني) وعرض النهاية (شاشة تفاصيل البريد الإلكتروني):

HomeFragment.kt

val emailCardDetailTransitionName = getString(R.string.email_card_detail_transition_name)
val extras = FragmentNavigatorExtras(cardView to emailCardDetailTransitionName)
val directions = HomeFragmentDirections.actionHomeFragmentToEmailFragment(email.id)
findNavController().navigate(directions, extras)

الآن بعد أن قمت بتهيئة السباكة، يمكنك إنشاء تحويل الحاوية. في طريقة onCreate EmailFragment، اضبط sharedElementEnterTransition على مثيل جديد من MaterialContainerTransform (استيراد إصدار com.google.android.material.transition بدلاً من إصدار com.google.android.material.transition.platform) من خلال إضافة المقتطف التالي:

EmailFragment.kt

sharedElementEnterTransition = MaterialContainerTransform().apply {
   drawingViewId = R.id.nav_host_fragment
   duration = resources.getInteger(R.integer.reply_motion_duration_large).toLong()
   scrimColor = Color.TRANSPARENT
   setAllContainerColors(requireContext().themeColor(R.attr.colorSurface))
}

يمكنك الآن إعادة تشغيل التطبيق.

ed62cedec31da268.gif

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

لإصلاح انتقال الإرجاع، أضِف السطرين التاليين إلى طريقة onViewCreated في HomeFragment.kt:

HomeFragment.kt

postponeEnterTransition()
view.doOnPreDraw { startPostponedEnterTransition() }

جرِّب إعادة تشغيل التطبيق. وسيؤدي الضغط على زر الرجوع بعد فتح رسالة إلكترونية إلى تصغير الرسالة الإلكترونية إلى القائمة مرة أخرى. أحسنت. لنواصل تحسين الرسوم المتحركة.

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

أضِف المقتطف أدناه إلى طريقة HomeFragment onEmailClicked لتوسيع قائمة الرسائل الإلكترونية بشكلٍ دقيق عند الخروج والعودة مرة أخرى عند إعادة الدخول:

HomeFragment.kt

exitTransition = MaterialElevationScale(false).apply {
   duration = resources.getInteger(R.integer.reply_motion_duration_large).toLong()
}
reenterTransition = MaterialElevationScale(true).apply {
   duration = resources.getInteger(R.integer.reply_motion_duration_large).toLong()
}

بعد ذلك، لضمان تطبيق الانتقال MaterialElevationScale على الشاشة الرئيسية ككل، بدلاً من وضع علامة على كل طريقة عرض فردية في التسلسل الهرمي، ضَع علامة على RecyclerView في fragment_home.xml كمجموعة انتقالية.

fragment_home.xml

android:transitionGroup="true"

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

9df2b39d5a150418.gif

5- إضافة نقل Container Transform من زر الإجراء الرئيسي (FAB) لإنشاء صفحة بريد إلكتروني

لنواصل تحويل الحاوية وإضافة تأثير انتقال من زر الإجراء العائم إلى ComposeFragment، ما يؤدي إلى توسيع زر الإجراء الرئيسي (FAB) إلى رسالة إلكترونية جديدة ليكتبها المستخدم. أولاً، أعد تشغيل التطبيق وانقر على زر الإجراء الرئيسي (FAB) للتأكد من عدم وجود انتقال عند تشغيل شاشة إنشاء الرسالة الإلكترونية.

d242c9708abd382c.gif

أثناء استخدام فئة النقل نفسها، ستختلف طريقة ضبط هذا المثيل لأنّ زر الإجراء الرئيسي (FAB) متوفّر في MainActivity ويتم وضع ComposeFragment داخل حاوية مضيف التنقّل MainActivity.

في ComposeFragment.kt، أضِف المقتطف التالي إلى طريقة onViewCreated، مع الحرص على استيراد إصدار androidx.transition من Slide.

ComposeFragment.kt

enterTransition = MaterialContainerTransform().apply {
   startView = requireActivity().findViewById(R.id.fab)
   endView = emailCardView
   duration = resources.getInteger(R.integer.reply_motion_duration_large).toLong()
   scrimColor = Color.TRANSPARENT
   containerColor = requireContext().themeColor(R.attr.colorSurface)
   startContainerColor = requireContext().themeColor(R.attr.colorSecondary)
   endContainerColor = requireContext().themeColor(R.attr.colorSurface)
}
returnTransition = Slide().apply {
   duration = resources.getInteger(R.integer.reply_motion_duration_medium).toLong()
   addTarget(R.id.email_card_view)
}

بالإضافة إلى المَعلمات المستخدَمة في عملية تحويل الحاوية السابقة، يتم ضبط startView وendView يدويًا هنا. بدلاً من استخدام سمات transitionName للسماح لنظام Android Transition بمعرفة طرق العرض التي يجب تحويلها، يمكنك تحديد طرق العرض هذه يدويًا عند الضرورة.

الآن، أعد تشغيل التطبيق. يُفترض أن يظهر زر الإجراء الرئيسي وهو يتحول إلى شاشة الإنشاء (انظر ملف GIF في نهاية هذه الخطوة).

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

انسخ المقتطف أدناه في طريقة navigateToCompose في MainActivity قبل استدعاء NavController navigate.

MainActivity.kt

currentNavigationFragment?.apply {
   exitTransition = MaterialElevationScale(false).apply {
       duration = resources.getInteger(R.integer.reply_motion_duration_large).toLong()
   }
   reenterTransition = MaterialElevationScale(true).apply {
       duration = resources.getInteger(R.integer.reply_motion_duration_large).toLong()
   }
}

هذا كل شيء في هذه الخطوة! يُفترض أن يكون لديك انتقال من FAB لإنشاء شاشة تشبه ما يلي:

81b68391ac4b0a9.gif

6- إضافة تأثير محور ي مشترَك من رمز البحث إلى صفحة عرض البحث

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

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

499e1a677b4216bb.gif

للبدء، ابحث عن طريقة navigateToSearch في MainActivity، وأضِف مقتطف الرمز التالي قبل استدعاء طريقة navigate NavController لإعداد خروج الجزء الحالي وإعادة إدخال MaterialSharedAxis انتقالات المحور Z.

MainActivity.kt

currentNavigationFragment?.apply {
   exitTransition = MaterialSharedAxis(MaterialSharedAxis.Z, true).apply {
       duration = resources.getInteger(R.integer.reply_motion_duration_large).toLong()
   }
   reenterTransition = MaterialSharedAxis(MaterialSharedAxis.Z, false).apply {
       duration = resources.getInteger(R.integer.reply_motion_duration_large).toLong()
   }
}

بعد ذلك، أضِف مقتطف الرمز التالي إلى الطريقة onCreate في SearchFragment، والتي تضبط انتقالات الإدخال وتعرض MaterialSharedAxis.

SearchFragment.kt

enterTransition = MaterialSharedAxis(MaterialSharedAxis.Z, true).apply {
   duration = resources.getInteger(R.integer.reply_motion_duration_large).toLong()
}
returnTransition = MaterialSharedAxis(MaterialSharedAxis.Z, false).apply {
   duration = resources.getInteger(R.integer.reply_motion_duration_large).toLong()
}

أخيرًا، لضمان تطبيق انتقال MaterialSharedAxis على شاشة البحث ككل، بدلاً من وضع علامة على LinearLayout في fragment_search.xml كمجموعة انتقالية، بدلاً من كل طريقة عرض فردية في التسلسل الهرمي.

fragment_search.xml

android:transitionGroup="true"

هذا كل شيء! حاول الآن إعادة تشغيل التطبيق والنقر على أيقونة البحث. يجب أن تتلاشى شاشتا عرض الصفحة الرئيسية والبحث في وقت واحد وتتغيران على طول المحور Z بعمق، مما يخلق تأثيرًا سلسًا بين الشاشتين.

e5c0b0a130e807db.gif

7. إضافة تأثير التلاشي خلال الانتقال بين صفحات صندوق البريد

في هذه الخطوة، سنضيف إمكانية الانتقال بين صناديق البريد المختلفة. ونظرًا لأننا لا نريد التأكيد على علاقة مكانية أو هرمية، سنستخدم ميزة التلاشي لإجراء "تبديل" بسيط بين قوائم رسائل البريد الإلكتروني.

قبل إضافة أي رمز إضافي، جرّب تشغيل التطبيق والنقر على شعار "رد" في شريط التطبيق السفلي، وتبديل صناديق البريد. يجب أن تتغير قائمة عناوين البريد الإلكتروني بدون أي عمليات انتقال.

2c874c0a4588e8fb.gif

للبدء، ابحث عن طريقة navigateToHome في MainActivity، وأضِف مقتطف الرمز التالي قبل استدعاء طريقة navigate NavController لإعداد انتقال الخروج MaterialFadeThrough من الجزء الحالي.

MainActivity.kt

currentNavigationFragment?.apply {
   exitTransition = MaterialFadeThrough().apply {
       duration = resources.getInteger(R.integer.reply_motion_duration_large).toLong()
   }
}

بعد ذلك، افتح HomeFragment. في onCreate، اضبط السمة enterTransition للجزء على مثيل جديد من MaterialFadeThrough.

HomeFragment.kt

enterTransition = MaterialFadeThrough().apply {
   duration = resources.getInteger(R.integer.reply_motion_duration_large).toLong()
}

إعادة تشغيل التطبيق عند فتح درج التنقل السفلي وتغيير صناديق البريد، من المفترض أن تتلاشى القائمة الحالية للرسائل الإلكترونية وتتسع بينما تتلاشى القائمة الجديدة وتصبح كبيرة. أحسنت.

f61dfd58ea7bd3fd.gif

8. إضافة نقل Container Transform (تحويل الحاوية) من شريحة عنوان البريد الإلكتروني إلى طريقة عرض البطاقة

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

قبل إضافة أي رمز، شغِّل تطبيق Reply (رد)، وانقر على رسالة إلكترونية، ثم انقر على "الرد" FAB، ثم جرِّب النقر على شريحة جهة اتصال المستلم. من المفترَض أن تختفي الشريحة على الفور، ويجب أن تظهر بطاقة تحتوي على عناوين بريد إلكتروني لجهة الاتصال هذه بدون أي رسوم متحركة.

6200c682da2382d5.gif

وستعمل باللغة ComposeFragment في هذه الخطوة. سبق أن تمت إضافة شرائح مستلِمين (مرئية تلقائيًا) وبطاقة مستلم (غير مرئية تلقائيًا) في التنسيق ComposeFragment. شريحة المستلِم وهذه البطاقة هما طريقتا العرض الذي سيتم تحويل حاوية بينهما.

للبدء، افتح ComposeFragment وابحث عن الطريقة expandChip. يتم استدعاء هذه الطريقة عند النقر على chip المُقدّم. أضِف مقتطف الرمز التالي فوق السطور التي تبدِّل مستوى الرؤية recipientCardView وchip، ما سيؤدي إلى تشغيل عملية تحويل الحاوية المسجَّلة عبر beginDelayedTransition.

ComposeFragment.kt

val transform = MaterialContainerTransform().apply {
   startView = chip
   endView = binding.recipientCardView
   scrimColor = Color.TRANSPARENT
   endElevation = requireContext().resources.getDimension(
       R.dimen.email_recipient_card_popup_elevation_compat
   )
   addTarget(binding.recipientCardView)
}

TransitionManager.beginDelayedTransition(binding.composeConstraintLayout, transform)

في حال تشغيل التطبيق الآن، يُفترض أن تتحول الشريحة إلى بطاقة عناوين بريد إلكتروني للمستلِم. بعد ذلك، لنضبط انتقال الإرجاع لتصغير البطاقة إلى الشريحة مرة أخرى.

في طريقة collapseChip في ComposeFragment، أضِف مقتطف الرمز أدناه لتصغير البطاقة إلى الشريحة مرة أخرى.

ComposeFragment.kt

val transform = MaterialContainerTransform().apply {
   startView = binding.recipientCardView
   endView = chip
   scrimColor = Color.TRANSPARENT
   startElevation = requireContext().resources.getDimension(
       R.dimen.email_recipient_card_popup_elevation_compat
   )
   addTarget(chip)
}

TransitionManager.beginDelayedTransition(binding.composeConstraintLayout, transform)

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

e823b28e2890e05d.gif

9. تم

باستخدام أقل من 100 سطر من رموز Kotlin وبعض ترميز XML الأساسي، ساعدتك مكتبة MDC-Android في إنشاء انتقالات رائعة ضمن تطبيق حالي يتوافق مع إرشادات التصميم المتعدد الأبعاد، كما يتوافق مع جميع أجهزة Android ويتوافق مع مظهرها وسلوكها.

454a47ba96017a25.gif

الخطوات التالية

للحصول على مزيد من المعلومات حول نظام Material Motion، احرص على الاطلاع على المواصفات ومستندات المطوِّرين الكاملة، وحاول إضافة بعض أشكال الانتقال إلى Materials إلى تطبيقك.

نشكرك على تجربة Material motion. نأمل أن تكون قد استفدت من هذا الدرس التطبيقي حول الترميز.

تمكنتُ من إكمال هذا الدرس التطبيقي حول الترميز بقدرٍ معقول من الوقت والجهد

أوافق بشدة أوافق ليست دقيقة ولا غير دقيقة لا أوافق لا أوافق أبدًا

أود مواصلة استخدام نظام Material motion في المستقبل

أوافق بشدة أوافق ليست دقيقة ولا غير دقيقة لا أوافق لا أوافق أبدًا