ساختن ترانزیشن های زیبا با حرکت مواد برای اندروید

1. مقدمه

متریال دیزاین سیستمی برای ساخت محصولات دیجیتال جسورانه و زیبا است. با متحد کردن سبک، نام تجاری، تعامل و حرکت تحت مجموعه‌ای از اصول و اجزای ثابت، تیم‌های محصول می‌توانند بزرگترین پتانسیل طراحی خود را محقق کنند.

logo_components_color_2x_web_96dp.png

Material Components (MDC) به توسعه دهندگان کمک می کند طراحی مواد را پیاده سازی کنند. MDC که توسط تیمی از مهندسان و طراحان UX در Google ایجاد شده است، دارای ده‌ها مؤلفه رابط کاربری زیبا و کاربردی است و برای Android، iOS، وب و Flutter.material.io/develop در دسترس است.

سیستم حرکتی Material برای اندروید چیست؟

سیستم حرکت مواد برای Android مجموعه‌ای از الگوهای انتقال در کتابخانه MDC-Android است که می‌تواند به کاربران کمک کند تا یک برنامه را بفهمند و آن را هدایت کنند، همانطور که در دستورالعمل‌های طراحی مواد توضیح داده شده است.

چهار الگوی اصلی انتقال مواد به شرح زیر است:

  • Container Transform: انتقال بین عناصر UI که شامل یک ظرف است. با تبدیل یکپارچه یک عنصر به عنصر دیگر، یک ارتباط قابل مشاهده بین دو عنصر UI مجزا ایجاد می کند.
  • محور مشترک: انتقال بین عناصر UI که یک رابطه فضایی یا ناوبری دارند. از یک تبدیل مشترک در محور x، y یا z برای تقویت رابطه بین عناصر استفاده می کند.
  • Fade Through: انتقال بین عناصر UI که رابطه قوی با یکدیگر ندارند. از محو شدن و محو شدن متوالی با مقیاس عنصر ورودی استفاده می کند.
  • محو شدن: برای عناصر رابط کاربری که در محدوده صفحه وارد یا خارج می شوند استفاده می شود.

کتابخانه MDC-Android کلاس‌های انتقالی را برای این الگوها ارائه می‌کند که بر روی کتابخانه AndroidX Transition ( androidx.transition ) و Android Transition Framework ( android.transition ) ساخته شده‌اند:

AndroidX

  • در بسته com.google.android.material.transition موجود است
  • از API Level 14+ پشتیبانی می کند
  • از Fragments و View ها پشتیبانی می کند، اما از Activities یا Windows پشتیبانی نمی کند
  • حاوی رفع اشکال پشتیبان‌شده و رفتار ثابت در سطوح API

چارچوب

  • در بسته com.google.android.material.transition.platform موجود است
  • از API Level 21+ پشتیبانی می کند
  • از Fragments، Views، Activities و Windows پشتیبانی می کند
  • رفع اشکال بکپورت نشده است و ممکن است رفتار متفاوتی در سطوح API داشته باشد

در این کد لبه شما از Transitions Material ساخته شده در بالای کتابخانه AndroidX استفاده می کنید، به این معنی که شما عمدتاً بر روی Fragments و View ها متمرکز خواهید شد.

چیزی که خواهی ساخت

این لبه کد شما را از طریق ساختن برخی از انتقال‌ها به یک برنامه ایمیل اندرویدی به نام Reply با استفاده از Kotlin راهنمایی می‌کند تا نشان دهد چگونه می‌توانید از انتقال‌های کتابخانه MDC-Android برای سفارشی کردن ظاهر و احساس برنامه خود استفاده کنید.

کد شروع برای برنامه Reply ارائه می‌شود، و شما جابجایی‌های Material زیر را در برنامه قرار می‌دهید، که می‌توانید در GIF کد لبه تکمیل‌شده زیر مشاهده کنید:

  • تبدیل کانتینر از لیست ایمیل به صفحه جزئیات ایمیل
  • تبدیل کانتینر از FAB به نوشتن صفحه ایمیل
  • انتقال مشترک Z-Axis از نماد جستجو به صفحه مشاهده جستجو
  • محو شدن از طریق انتقال بین صفحات صندوق پستی
  • تبدیل کانتینر از تراشه آدرس ایمیل به نمای کارت

The domain of the requested iframe (youtu.be) has not been whitelisted.

آنچه شما نیاز دارید

  • دانش اولیه توسعه اندروید و Kotlin
  • Android Studio (اگر قبلاً آن را ندارید آن را از اینجا دانلود کنید)
  • شبیه ساز یا دستگاه اندروید (در دسترس از طریق Android Studio)
  • کد نمونه (مرحله بعدی را ببینید)

سطح تجربه خود را در ساخت برنامه های اندروید چگونه ارزیابی می کنید؟

تازه کار متوسط مسلط

2. محیط توسعه خود را تنظیم کنید

اندروید استودیو را راه اندازی کنید

هنگامی که Android Studio را باز می کنید، باید پنجره ای با عنوان "Welcome to Android Studio" نمایش داده شود. با این حال، اگر این اولین بار است که Android Studio را راه اندازی می کنید، مراحل Android Studio Setup Wizard را با مقادیر پیش فرض انجام دهید. این مرحله برای دانلود و نصب فایل‌های لازم می‌تواند چند دقیقه طول بکشد، بنابراین هنگام انجام بخش بعدی، راحت آن را در پس‌زمینه رها کنید.

گزینه 1: برنامه codelab starter را از GitHub کلون کنید

برای شبیه سازی این کد لبه از GitHub، دستورات زیر را اجرا کنید:

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

گزینه 2: فایل فشرده برنامه codelab starter را دانلود کنید

برنامه شروع در دایرکتوری material-components-android-motion-codelab-develop قرار دارد.

کد شروع را در Android Studio بارگیری کنید

  1. هنگامی که جادوگر راه اندازی به پایان رسید و پنجره خوش آمدید به Android Studio نشان داده شد، روی باز کردن پروژه موجود Android Studio کلیک کنید.

e3f200327a67a53.png

  1. به دایرکتوری که کد نمونه را در آن نصب کرده بودید بروید و دایرکتوری نمونه را برای باز کردن پروژه انتخاب کنید.
  2. همانطور که توسط نشانگرهای فعالیت در پایین پنجره Android Studio نشان داده شده است، کمی صبر کنید تا Android Studio پروژه را بسازد و همگام کند.
  1. در این مرحله، Android Studio ممکن است برخی از خطاهای ساخت را ایجاد کند زیرا شما Android SDK یا ابزارهای ساخت را از دست داده اید، مانند آنچه در زیر نشان داده شده است. دستورالعمل‌های موجود در Android Studio را برای نصب/به‌روزرسانی و همگام‌سازی پروژه خود دنبال کنید. اگر همچنان با مشکل مواجه هستید، راهنمای به‌روزرسانی ابزارهای خود را با مدیر SDK دنبال کنید.

6e026ae171f5b1eb.png

وابستگی های پروژه را تأیید کنید

پروژه نیاز به وابستگی به کتابخانه MDC-Android دارد. کد نمونه ای که دانلود کردید باید قبلاً این وابستگی را در لیست داشته باشد، اما برای اطمینان، اجازه دهید نگاهی به پیکربندی بیندازیم.

به فایل build.gradle ماژول app بروید و مطمئن شوید که بلوک dependencies دارای وابستگی به MDC-Android است:

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

برنامه استارتر را اجرا کنید

  1. مطمئن شوید که پیکربندی ساخت در سمت چپ دستگاه انتخابی app است.
  2. برای ساخت و اجرای برنامه ، دکمه سبز Run / Play را فشار دهید.

24218d0a6ae25803.png

  1. در پنجره Select Deployment Target ، اگر قبلاً یک دستگاه Android در لیست دستگاه های موجود خود دارید، به مرحله 8 بروید. در غیر این صورت، روی Create New Virtual Device کلیک کنید.
  2. در صفحه انتخاب سخت افزار ، یک دستگاه تلفن مانند Pixel 3 را انتخاب کنید و سپس روی Next کلیک کنید.
  3. در صفحه تصویر سیستم ، یک نسخه جدید Android را انتخاب کنید، ترجیحاً بالاترین سطح API را انتخاب کنید. اگر نصب نیست، روی لینک دانلودی که نشان داده شده است کلیک کنید و دانلود را کامل کنید.
  4. روی Next کلیک کنید.
  5. در صفحه دستگاه مجازی Android (AVD) ، تنظیمات را همانطور که هستند رها کنید و روی Finish کلیک کنید.
  6. یک دستگاه Android را از گفتگوی هدف استقرار انتخاب کنید.
  7. Ok را کلیک کنید.
  8. Android Studio برنامه را می سازد، آن را مستقر می کند و به طور خودکار آن را در دستگاه مورد نظر باز می کند.

موفقیت! کد شروع صفحه اصلی Reply باید در شبیه ساز شما اجرا شود. باید صندوق ورودی حاوی لیستی از ایمیل ها را ببینید.

cc73eb0d0f779035.png

اختیاری: انیمیشن های دستگاه را کاهش دهید

از آنجایی که این آزمایشگاه کد شامل انتقال‌های سریع و در عین حال صیقلی می‌شود، می‌تواند برای کاهش سرعت انیمیشن‌های دستگاه به منظور مشاهده برخی از جزئیات ریز انتقال‌ها در حین پیاده‌سازی مفید باشد. این را می توان با دستورات پوسته adb یا کاشی تنظیمات سریع انجام داد. توجه داشته باشید که این روش‌های کاهش سرعت انیمیشن‌های دستگاه روی انیمیشن‌های دستگاه خارج از برنامه Reply نیز تأثیر می‌گذارند.

روش 1: دستورات پوسته ADB

برای کاهش سرعت انیمیشن های دستگاه به میزان 10 برابر، می توانید دستورات زیر را از خط فرمان اجرا کنید:

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. در قسمت جستجو عبارت "tiles" را تایپ کنید
  3. روی ردیف «تنظیمات سریع کاشی‌های توسعه‌دهنده» کلیک کنید
  4. روی سوئیچ «مقیاس انیمیشن پنجره» کلیک کنید

در نهایت، در سراسر صفحه کد، سایه اعلان سیستم را از بالای صفحه پایین بکشید و از آن استفاده کنید c7e3f98200023f6a.png نمادی برای جابه‌جایی بین انیمیشن‌های با سرعت کم و معمولی.

3. با نمونه کد برنامه آشنا شوید

بیایید نگاهی به کد بیندازیم. ما برنامه‌ای ارائه کرده‌ایم که از کتابخانه اجزای Jetpack Navigation برای پیمایش بین چند بخش مختلف، همه در یک Activity، 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 Reply نشان داده می‌شود.

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

این نشان می‌دهد که چگونه می‌توانید بدون هیچ گونه انتقال سفارشی، به صفحه نمای جستجو بروید. در طول این کد، شما به Reply's MainActivity و چهار قطعه اصلی شیرجه می‌زنید تا انتقالات Material را تنظیم کنید که همزمان با اقدامات ناوبری مختلف در سراسر برنامه کار می‌کنند.

اکنون که با کد شروع آشنا شدید، اجازه دهید اولین انتقال خود را پیاده سازی کنیم.

4. انتقال Container Transform را از لیست ایمیل به صفحه جزئیات ایمیل اضافه کنید

برای شروع، هنگام کلیک کردن بر روی ایمیل، یک انتقال اضافه خواهید کرد. برای این تغییر مسیریابی، الگوی تبدیل کانتینر به خوبی مناسب است، زیرا برای انتقال بین عناصر UI که شامل یک ظرف است، طراحی شده است. این الگو یک ارتباط قابل مشاهده بین دو عنصر UI ایجاد می کند.

قبل از افزودن هر کدی، برنامه 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)

اکنون که لوله کشی را پیکربندی کرده اید، می توانید یک تبدیل ظرف ایجاد کنید. در روش EmailFragment onCreate ، 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 بداند کدام نماها باید تغییر داده شوند، می‌توانید در صورت لزوم این ویژگی‌ها را به صورت دستی مشخص کنید.

اکنون، برنامه را دوباره اجرا کنید. باید مشاهده کنید که FAB به صفحه نوشتن تبدیل می شود (به GIF در انتهای این مرحله مراجعه کنید).

مشابه مرحله قبل، باید یک انتقال به HomeFragment اضافه کنید تا پس از حذف و جایگزینی ComposeFragment از بین نرود.

قبل از فراخوانی NavController navigate قطعه زیر را در متد navigateToCompose در MainActivity کپی کنید.

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-Axis را از نماد جستجو به صفحه مشاهده جستجو اضافه کنید

در این مرحله، یک انتقال از نماد جستجو به نمای جستجوی تمام صفحه اضافه می کنیم. از آنجایی که هیچ محفظه دائمی در این تغییر ناوبری وجود ندارد، می‌توانیم از انتقال مشترک Z-Axis برای تقویت رابطه فضایی بین دو صفحه و نشان دادن حرکت یک سطح به سمت بالا در سلسله مراتب برنامه استفاده کنیم.

قبل از افزودن هر کد اضافی، برنامه را اجرا کنید و روی نماد جستجو در گوشه سمت راست پایین صفحه ضربه بزنید. این باید صفحه نمایش جستجو را بدون انتقال ظاهر کند.

499e1a677b4216bb.gif

برای شروع، متد navigateToSearch را در MainActivity بیابید، و قطعه کد زیر را قبل از فراخوانی متد navigate NavController اضافه کنید تا خروجی قطعه فعلی را راه‌اندازی کنید و مجدداً انتقالات MaterialSharedAxis Z-Axis را وارد کنید.

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 اضافه کنید، که ترانزیشن های Enter و بازگشت 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. انتقال Fade Through بین صفحات صندوق پست را اضافه کنید

در این مرحله، یک انتقال بین صندوق های پستی مختلف اضافه می کنیم. از آنجایی که نمی‌خواهیم بر یک رابطه فضایی یا سلسله مراتبی تأکید کنیم، از fade through برای انجام یک «تبادل» ساده بین فهرست‌های ایمیل استفاده می‌کنیم.

قبل از افزودن کد اضافی، برنامه را اجرا کنید، روی نشان‌واره Reply در نوار برنامه پایین ضربه بزنید و صندوق‌های پستی را تغییر دهید. لیست ایمیل ها باید بدون انتقال تغییر کند.

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. همه چیز انجام شد

کتابخانه MDC-Android با استفاده از کمتر از 100 خط کد Kotlin و برخی نشانه‌گذاری اولیه XML، به شما کمک کرده است که انتقال‌های زیبایی را در یک برنامه موجود ایجاد کنید که با دستورالعمل‌های طراحی متریال مطابقت دارد، و همچنین در همه دستگاه‌های اندرویدی به‌طور ثابت ظاهر و رفتار می‌کند.

454a47ba96017a25.gif

مراحل بعدی

برای اطلاعات بیشتر در مورد سیستم حرکت مواد، حتما مشخصات و مستندات کامل توسعه دهنده را بررسی کنید و سعی کنید چند انتقال مواد را به برنامه خود اضافه کنید!

از اینکه حرکت Material را امتحان کردید متشکریم. امیدواریم از این کد لبه لذت برده باشید!

من توانستم با صرف زمان و تلاش معقول این کد لبه را تکمیل کنم

کاملا موافقم موافقم خنثی مخالفت کنید به شدت مخالفم

من می خواهم در آینده از سیستم حرکت مواد استفاده کنم

کاملا موافقم موافقم خنثی مخالفت کنید به شدت مخالفم