پویانمایی تغییرات چیدمان بااستفاده از گذر

امتحان کردن روش Compose
Jetpack Compose جعبه‌ابزار واسط کاربر توصیه‌شده برای Android است. با نحوه استفاده از «پویانمایی‌ها» در Compose آشنا شوید.

چارچوب انتقال Android به شما امکان می‌دهد با ارائه چیدمان‌های شروع و پایان، انواع حرکت‌ها را در واسط کاربر پویانمایی کنید. می‌توانید نوع پویانمایی موردنظرتان را انتخاب کنید—مثلاً محو کردن نماها به داخل یا خارج، یا تغییر اندازه نماها—و چارچوب گذر تعیین می‌کند چگونه از چیدمان شروع به چیدمان پایان پویانمایی شود.

چارچوب انتقال شامل ویژگی‌های زیر است:

  • پویانمایی‌های سطح گروه: جلوه‌های پویانمایی را بر همه نماها در سلسله‌مراتب نما اعمال می‌کند.
  • پویانمایی‌های داخلی: از پویانمایی‌های ازپیش تعریف‌شده برای جلوه‌های رایج مانند محو شدن یا حرکت استفاده کنید.
  • پشتیبانی از فایل منبع: سلسله‌مراتب نما و پویانمایی‌های داخلی را از فایل‌های منبع چیدمان بار کنید.
  • فراخوانی‌های چرخه حیات: فراخوانی‌هایی را دریافت کنید که کنترل فرایند تغییر سلسله‌مراتب و پویانمایی را فراهم می‌کنند.

فرایند اصلی برای پویانمایی بین دو چیدمان به‌صورت زیر است:

  1. شیء Scene برای چیدمان‌های شروع و پایان ایجاد کنید. بااین‌حال، صحنه چیدمان شروع اغلب به‌طور خودکار از چیدمان فعلی تعیین می‌شود.
  2. یک شیء Transition ایجاد کنید تا نوع پویانمایی موردنظرتان را تعریف کنید.
  3. TransitionManager.go() را فراخوانی کنید، و سیستم پویانمایی را برای جابه‌جایی طرح‌بندی‌ها اجرا می‌کند.

نمودار شکل ۱ رابطه بین چیدمان‌ها، صحنه‌ها، انتقال، و پویانمایی نهایی را نشان می‌دهد.

شکل ۱. تصویرسازی ساده‌ای از نحوه ایجاد پویانمایی توسط چارچوب انتقال.

ساختن صحنه

صحنه‌ها وضعیت سلسله‌مراتب نما را ذخیره می‌کنند، ازجمله همه نماها و مقادیر ویژگی‌های آن‌ها. چارچوب انتقال‌ها می‌تواند پویانمایی‌ها را بین صحنه شروع و پایان اجرا کند.

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

صحنه می‌تواند کنش‌های خودش را نیز تعریف کند که وقتی صحنه را تغییر می‌دهید اجرا می‌شوند. این ویژگی برای پاک کردن تنظیمات نما پس‌از انتقال به صحنه مفید است.

ایجاد صحنه از منبع چیدمان

می‌توانید نمونه Scene را مستقیماً از فایل منبع چیدمان ایجاد کنید. وقتی سلسله‌مراتب نما در فایل عمدتاً ایستا است، از این تکنیک استفاده کنید. صحنه حاصل نشان‌دهنده وضعیت سلسله‌مراتب نما در زمانی است که نمونه Scene را ایجاد کردید. اگر سلسله‌مراتب نما را تغییر دهید، صحنه را دوباره ایجاد کنید. چارچوب صحنه را از کل سلسله‌مراتب نمای موجود در فایل ایجاد می‌کند. نمی‌توانید از بخشی از فایل چیدمان صحنه ایجاد کنید.

برای ایجاد نمونه Scene از فایل منبع چیدمان، ریشه صحنه را از چیدمانتان به‌عنوان ViewGroup بازیابی کنید. سپس، تابع Scene.getSceneForLayout() را با ریشه صحنه و شناسه منبع فایل چیدمان که حاوی سلسله‌مراتب نمای صحنه است فراخوانی کنید.

تعریف کردن چیدمان برای صحنه‌ها

تکه‌کدهای بقیه این بخش نشان می‌دهند که چگونه دو صحنه متفاوت با یک عنصر ریشه صحنه ایجاد کنید. این قطعه کدها همچنین نشان می‌دهند که می‌توانید چندین شیء Scene نامرتبط را بدون اینکه نشان دهید به یکدیگر مرتبط هستند بار کنید.

این نمونه شامل تعاریف چیدمان زیر است:

  • چیدمان اصلی فعالیت با برچسب نوشتاری و فرزند FrameLayout.
  • ConstraintLayout برای صحنه اول با دو فیلد نوشتاری.
  • یک ConstraintLayout برای صحنه دوم با همان دو فیلد نوشتاری با ترتیبی متفاوت.

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

چیدمان اصلی برای فعالیت به‌صورت زیر تعریف می‌شود:

res/layout/activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/master_layout">
    <TextView
        android:id="@+id/title"
        ...
        android:text="Title"/>
    <FrameLayout
        android:id="@+id/scene_root">
        <include layout="@layout/a_scene" />
    </FrameLayout>
</LinearLayout>

این تعریف چیدمان حاوی فیلد نوشتاری و FrameLayout فرزند برای ریشه صحنه است. چیدمان صحنه اول در فایل چیدمان اصلی گنجانده شده است. این کار به برنامه اجازه می‌دهد آن را به‌عنوان بخشی از میانای کاربر اولیه نمایش دهد و همچنین آن را در صحنه بار کند، زیرا چارچوب فقط می‌تواند کل فایل چیدمان را در صحنه بار کند.

چیدمان صحنه اول به‌صورت زیر تعریف می‌شود:

res/layout/a_scene.xml

<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/scene_container"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
    <TextView
        android:id="@+id/text_view1"
        android:layout_height="wrap_content"
        android:layout_width="wrap_content"
        android:text="Text Line 1"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"/>
    <TextView
        android:id="@+id/text_view2"
        android:layout_height="wrap_content"
        android:layout_width="wrap_content"
        android:text="Text Line 2"
        app:layout_constraintTop_toBottomOf="@id/text_view1"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

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

res/layout/another_scene.xml

<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/scene_container"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
    <TextView
        android:id="@+id/text_view2"
        android:layout_height="wrap_content"
        android:layout_width="wrap_content"
        android:text="Text Line 2"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent" />
    <TextView
        android:id="@+id/text_view1"
        android:layout_height="wrap_content"
        android:layout_width="wrap_content"
        android:text="Text Line 1"
        app:layout_constraintTop_toBottomOf="@id/text_view2"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>

تولید کردن صحنه از چیدمان‌ها

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

تکه‌کد زیر نحوه دریافت مرجع برای ریشه صحنه و ایجاد دو شیء Scene از فایل‌های چیدمان را نشان می‌دهد:

کاتلین

val sceneRoot: ViewGroup = findViewById(R.id.scene_root)
val aScene: Scene = Scene.getSceneForLayout(sceneRoot, R.layout.a_scene, this)
val anotherScene: Scene = Scene.getSceneForLayout(sceneRoot, R.layout.another_scene, this)

جاوا

Scene aScene;
Scene anotherScene;

// Create the scene root for the scenes in this app.
sceneRoot = (ViewGroup) findViewById(R.id.scene_root);

// Create the scenes.
aScene = Scene.getSceneForLayout(sceneRoot, R.layout.a_scene, this);
anotherScene =
    Scene.getSceneForLayout(sceneRoot, R.layout.another_scene, this);

اکنون در برنامه، دو شیء Scene براساس سلسله‌مراتب نما وجود دارد. هر دو صحنه از ریشه صحنه تعریف‌شده توسط عنصر FrameLayout در res/layout/activity_main.xml استفاده می‌کنند.

ایجاد صحنه در کد

همچنین می‌توانید نمونه Scene را در کدتان از شیء ViewGroup ایجاد کنید. وقتی سلسله‌مراتب نما را مستقیماً در کدتان اصلاح می‌کنید یا وقتی آن‌ها را به‌صورت پویا تولید می‌کنید، از این تکنیک استفاده کنید.

برای ایجاد صحنه از سلسله‌مراتب نما در کدتان، از سازنده Scene(sceneRoot, viewHierarchy) استفاده کنید. فراخوانی این سازنده معادل فراخوانی تابع Scene.getSceneForLayout() است وقتی‌که قبلاً فایل چیدمان را گسترش داده باشید.

تکه‌کد زیر نشان می‌دهد که چگونه می‌توان یک نمونه Scene از عنصر ریشه صحنه و سلسله‌مراتب نمای صحنه در کد خود ایجاد کرد:

کاتلین

val sceneRoot = someLayoutElement as ViewGroup
val viewHierarchy = someOtherLayoutElement as ViewGroup
val scene: Scene = Scene(sceneRoot, viewHierarchy)

جاوا

Scene mScene;

// Obtain the scene root element.
sceneRoot = (ViewGroup) someLayoutElement;

// Obtain the view hierarchy to add as a child of
// the scene root when this scene is entered.
viewHierarchy = (ViewGroup) someOtherLayoutElement;

// Create a scene.
mScene = new Scene(sceneRoot, mViewHierarchy);

کنش‌های ایجاد صحنه

این چارچوب به شما امکان می‌دهد کنش‌های سفارشی صحنه را تعریف کنید تا سیستم هنگام ورود یا خروج از صحنه آن‌ها را اجرا کند. در بسیاری از موارد، تعریف کنش‌های صحنه سفارشی غیرضروری است، زیرا چارچوب تغییر بین صحنه‌ها را به‌طور خودکار پویانمایی می‌کند.

کنش‌های صحنه برای رسیدگی به این موارد مفید هستند:

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

برای ارائه کنش‌های صحنه سفارشی، کنش‌هایتان را به‌عنوان اشیای Runnable تعریف کنید و آن‌ها را به توابع Scene.setExitAction() یا Scene.setEnterAction() ارسال کنید. چارچوب، تابع setExitAction() را در صحنه شروع قبل‌از اجرای پویانمایی گذار و تابع setEnterAction() را در صحنه پایان پس‌از اجرای پویانمایی گذار فراخوانی می‌کند.

اعمال کردن انتقال

چارچوب گذار نشان‌دهنده سبک پویانمایی بین صحنه‌ها با شیء Transition است. می‌توانید بااستفاده از زیرکلاس‌های داخلی، مانند AutoTransition و Fade، یک Transition را نمونه‌سازی کنید یا گذار خودتان را تعریف کنید. سپس می‌توانید با ارسال Scene پایانی و Transition به TransitionManager.go()، پویانمایی را بین صحنه‌ها اجرا کنید.

چرخه حیات گذر شبیه چرخه حیات فعالیت است و نشان‌دهنده حالت‌های گذری است که چارچوب بین شروع و تکمیل پویانمایی پایش می‌کند. در وضعیت‌های مهم چرخه حیات، چارچوب توابع بازخوانی را فرامی‌خواند که می‌توانید آن‌ها را برای تنظیم میانای کاربر در فازهای مختلف انتقال پیاده‌سازی کنید.

ایجاد انتقال

بخش قبلی نشان می‌دهد که چگونه صحنه‌هایی ایجاد کنید که نشان‌دهنده وضعیت سلسله‌مراتب‌های مختلف نما باشد. وقتی صحنه‌های شروع و پایان را که می‌خواهید بین آن‌ها تغییر دهید تعریف کردید، شیء Transition را که پویانمایی را تعریف می‌کند ایجاد کنید. این چارچوب به شما امکان می‌دهد که یا یک انتقال داخلی را در یک فایل منبع مشخص کنید و آن را در کد خود گسترش دهید یا یک نمونه از انتقال داخلی را مستقیماً در کد خود ایجاد کنید.

جدول ۱. انواع گذار داخلی.

کلاس برچسب جلوه
AutoTransition <autoTransition/> انتقال پیش‌فرض. به‌ترتیب، نماها را محو می‌کند، جابه‌جا می‌کند، تغییر اندازه می‌دهد، و ظاهر می‌کند.
ChangeBounds <changeBounds/> نماها را جابه‌جا می‌کند و اندازه آن‌ها را تغییر می‌دهد.
ChangeClipBounds <changeClipBounds/> View.getClipBounds() را قبل و بعداز تغییر صحنه ضبط می‌کند و آن تغییرات را درطول گذر پویانمایی می‌کند.
ChangeImageTransform <changeImageTransform/> ماتریس ImageView را قبل و بعداز تغییر صحنه ضبط می‌کند و آن را درطول گذر پویانمایی می‌کند.
ChangeScroll <changeScroll/> ویژگی‌های پیمایش هدف‌ها را قبل و بعداز تغییر صحنه ضبط می‌کند و هرگونه تغییری را پویانمایی می‌کند.
ChangeTransform <changeTransform/> مقیاس و چرخش نماها را قبل و بعداز تغییر صحنه ضبط می‌کند و این تغییرات را درطول گذر پویانمایی می‌کند.
Explode <explode/> تغییرات در نمایان بودن نماهای هدف را در صحنه‌های شروع و پایان ردیابی می‌کند و نماها را از لبه‌های صحنه به داخل یا خارج منتقل می‌کند.
Fade <fade/> fade_in در بازدیدها محو می‌شود.
fade_out نماها را محو می‌کند.
fade_in_out (پیش‌فرض) fade_out را انجام می‌دهد و سپس fade_in را انجام می‌دهد.
Slide <slide/> تغییرات در رؤیت‌پذیری نماهای هدف را در صحنه‌های شروع و پایان ردیابی می‌کند و نماها را از یکی از لبه‌های صحنه به داخل یا خارج منتقل می‌کند.

ایجاد نمونه انتقال از فایل منبع

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

برای مشخص کردن انتقال داخلی در فایل منبع، این مراحل را دنبال کنید:

  • دایرکتوری res/transition/ را به پروژه‌تان اضافه کنید.
  • فایل منبع XML جدیدی در این دایرکتوری ایجاد کنید.
  • یک گره XML برای یکی از انتقال‌های توکار اضافه کنید.

برای مثال، فایل منبع زیر انتقال Fade را مشخص می‌کند:

res/transition/fade_transition.xml

<fade xmlns:android="http://schemas.android.com/apk/res/android" />

تکه‌کد زیر نشان می‌دهد که چگونه یک نمونه Transition را در فعالیت خود از یک فایل منبع باز کنید:

کاتلین

var fadeTransition: Transition =
    TransitionInflater.from(this)
                      .inflateTransition(R.transition.fade_transition)

جاوا

Transition fadeTransition =
        TransitionInflater.from(this).
        inflateTransition(R.transition.fade_transition);

ایجاد نمونه انتقال در کد

این تکنیک برای ایجاد پویای اشیای انتقال مفید است اگر میانای کاربر را در کد خود اصلاح کنید و نمونه‌های انتقال داخلی ساده با پارامترهای کم یا بدون پارامتر ایجاد کنید.

برای ایجاد نمونه‌ای از انتقال داخلی، یکی از سازنده‌های عمومی را در زیرکلاس‌های کلاس Transition فراخوانی کنید. برای مثال، تکه‌کد زیر نمونه‌ای از انتقال Fade را ایجاد می‌کند:

کاتلین

var fadeTransition: Transition = Fade()

جاوا

Transition fadeTransition = new Fade();

اعمال کردن انتقال

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

برای تغییر صحنه هنگام اعمال انتقال در پاسخ به رویدادی در فعالیتتان، تابع کلاس TransitionManager.go() را با صحنه پایانی و نمونه انتقال برای استفاده در پویانمایی فراخوانی کنید، همان‌طور که در قطعه کد زیر نشان داده شده است:

کاتلین

TransitionManager.go(endingScene, fadeTransition)

جاوا

TransitionManager.go(endingScene, fadeTransition);

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

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

انتخاب نماهای هدف خاص

چارچوب به‌طور پیش‌فرض انتقال‌ها را بر همه نماها در صحنه‌های شروع و پایان اعمال می‌کند. در برخی موارد، ممکن است بخواهید پویانمایی را فقط روی زیرمجموعه‌ای از نماها در صحنه اعمال کنید. این چارچوب به شما امکان می‌دهد نماهای خاصی را که می‌خواهید پویانمایی کنید انتخاب کنید. برای مثال، این چارچوب از پویانمایی تغییرات در اشیاء ListView پشتیبانی نمی‌کند، بنابراین سعی نکنید آن‌ها را درطول انتقال پویانمایی کنید.

هر نمایی که انتقال آن را پویانمایی می‌کند هدف نامیده می‌شود. فقط می‌توانید هدف‌هایی را انتخاب کنید که بخشی از سلسله‌مراتب نمای مرتبط با صحنه باشند.

برای برداشتن یک یا چند نما از فهرست هدف‌ها، removeTarget() را قبل‌از شروع انتقال فراخوانی کنید. برای افزودن فقط نماهایی که مشخص می‌کنید به فهرست هدف‌ها، تابع addTarget() را فراخوانی کنید. برای اطلاعات بیشتر، به مرجع میانای برنامه‌سازی کاربردی برای کلاس Transition مراجعه کنید.

مشخص کردن چند گذر

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

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

برای تعریف مجموعه انتقال از مجموعه‌ای از انتقال‌ها در XML، فایل منبعی در دایرکتوری res/transitions/ ایجاد کنید و انتقال‌ها را در زیر عنصر TransitionSet فهرست کنید. برای مثال، تکه‌کد زیر نشان می‌دهد که چگونه مجموعه گذاری را مشخص کنید که رفتاری مشابه با کلاس AutoTransition دارد:

<transitionSet xmlns:android="http://schemas.android.com/apk/res/android"
    android:transitionOrdering="sequential">
    <fade android:fadingMode="fade_out" />
    <changeBounds />
    <fade android:fadingMode="fade_in" />
</transitionSet>

برای گسترش دادن مجموعه انتقال به شیء TransitionSet در کدتان، تابع TransitionInflater.from() را در فعالیتتان فراخوانی کنید. کلاس TransitionSet از کلاس Transition گسترش می‌یابد، بنابراین می‌توانید از آن با مدیر انتقال درست مانند هر نمونه Transition دیگری استفاده کنید.

اعمال انتقال بدون صحنه

تغییر سلسله‌مراتب نما تنها راه اصلاح میانای کاربر نیست. همچنین می‌توانید با افزودن، اصلاح، و برداشتن نماهای فرزند در سلسله‌مراتب فعلی، تغییراتی ایجاد کنید.

برای مثال، می‌توانید تعامل جستجو را با یک چیدمان پیاده‌سازی کنید. با طرح‌بندی‌ای شروع کنید که فیلد ورودی جستجو و نماد جستجو را نشان می‌دهد. برای تغییر میانای کاربر برای نمایش نتایج، دکمه جستجو را بردارید وقتی کاربر با فراخوانی ViewGroup.removeView() روی آن تک‌ضرب می‌زند و نتایج جستجو را با فراخوانی ViewGroup.addView() اضافه کنید.

اگر جایگزین این باشد که دو سلسله‌مراتب داشته باشید که تقریباً یکسان هستند، می‌توانید از این رویکرد استفاده کنید. به‌جای ایجاد و نگهداری دو فایل چیدمان جداگانه برای تفاوت جزئی در میانای کاربر، می‌توانید یک فایل چیدمان داشته باشید که حاوی سلسله‌مراتب نمایی باشد که در کد اصلاح می‌کنید.

اگر تغییرات را در سلسله‌مراتب نمای فعلی به این روش انجام دهید، نیازی به ایجاد صحنه ندارید. درعوض، می‌توانید بااستفاده از انتقال تأخیری، انتقالی بین دو حالت سلسله‌مراتب نما ایجاد و اعمال کنید. این ویژگی چارچوب انتقال‌ها با وضعیت سلسله‌مراتب نمای فعلی شروع می‌شود، تغییراتی را که در نماهای آن ایجاد می‌کنید ثبت می‌کند، و انتقالی را اعمال می‌کند که تغییرات را هنگام بازترسیم میانای کاربر توسط سیستم پویانمایی می‌کند.

برای ایجاد انتقال تأخیری در سلسله‌مراتب نمای تکی، این مراحل را دنبال کنید:

  1. وقتی رویدادی که انتقال را راه‌اندازی می‌کند اتفاق می‌افتد، تابع TransitionManager.beginDelayedTransition() را فراخوانی کنید و نمای والد همه نماهایی را که می‌خواهید تغییر دهید و انتقال موردنظر برای استفاده را ارائه دهید. چارچوب، وضعیت فعلی نماهای فرزند و مقادیر ویژگی آن‌ها را ذخیره می‌کند.
  2. تغییرات لازم را در نماهای فرزند مطابق با مورد استفاده‌تان اعمال کنید. چارچوب تغییراتی را که در نماهای فرزند و ویژگی‌های آن‌ها ایجاد می‌کنید ثبت می‌کند.
  3. وقتی سیستم میانای کاربر را براساس تغییرات شما بازترسیم می‌کند، چارچوب تغییرات بین وضعیت اصلی و وضعیت جدید را پویانمایی می‌کند.

مثال زیر نشان می‌دهد که چگونه می‌توان افزودن نمای نوشتاری به سلسله‌مراتب نما را بااستفاده از انتقال تأخیری پویانمایی کرد. اولین قطعه کد فایل تعریف چیدمان را نشان می‌دهد:

res/layout/activity_main.xml

<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/mainLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
    <EditText
        android:id="@+id/inputText"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent" />
    ...
</androidx.constraintlayout.widget.ConstraintLayout>

تکه‌کد بعدی کدی را نشان می‌دهد که افزودن نمای نوشتار را پویانمایی می‌کند:

MainActivity

کاتلین

setContentView(R.layout.activity_main)
val labelText = TextView(this).apply {
    text = "Label"
    id = R.id.text
}
val rootView: ViewGroup = findViewById(R.id.mainLayout)
val mFade: Fade = Fade(Fade.IN)
TransitionManager.beginDelayedTransition(rootView, mFade)
rootView.addView(labelText)

جاوا

private TextView labelText;
private Fade mFade;
private ViewGroup rootView;
...
// Load the layout.
setContentView(R.layout.activity_main);
...
// Create a new TextView and set some View properties.
labelText = new TextView(this);
labelText.setText("Label");
labelText.setId(R.id.text);

// Get the root view and create a transition.
rootView = (ViewGroup) findViewById(R.id.mainLayout);
mFade = new Fade(Fade.IN);

// Start recording changes to the view hierarchy.
TransitionManager.beginDelayedTransition(rootView, mFade);

// Add the new TextView to the view hierarchy.
rootView.addView(labelText);

// When the system redraws the screen to show this update,
// the framework animates the addition as a fade in.

تعریف فراخوانی‌های چرخه حیات انتقال

چرخه حیات انتقال مشابه چرخه حیات فعالیت است. این کلاس نشان‌دهنده حالت‌های گذاری است که چارچوب در طول دوره بین فراخوانی تابع TransitionManager.go() و تکمیل پویانمایی نظارت می‌کند. در حالت‌های مهم چرخه حیات، چارچوب فراخوانی‌های برگشتی تعریف‌شده توسط میانای TransitionListener را فراخوانی می‌کند.

فراخوانی‌های برگشتی چرخه حیات گذار مفید هستند، برای مثال، برای کپی کردن مقدار ویژگی نما از سلسله‌مراتب نمای شروع به سلسله‌مراتب نمای پایان درطول تغییر صحنه. نمی‌توانید به‌سادگی مقدار را از نمای شروع آن به نمای موجود در سلسله‌مراتب نمای پایان کپی کنید، زیرا سلسله‌مراتب نمای پایان تا زمانی که انتقال کامل نشود افزایش نمی‌یابد. درعوض، باید مقدار را در متغیری ذخیره کنید و سپس وقتی چارچوب گذر را به‌پایان رساند، آن را در سلسله‌مراتب نمای پایانی کپی کنید. برای اینکه وقتی انتقال تکمیل شد مطلع شوید، تابع TransitionListener.onTransitionEnd() را در فعالیتتان پیاده‌سازی کنید.

برای اطلاعات بیشتر، مرجع میانای برنامه‌سازی کاربردی را برای کلاس TransitionListener ببینید.

محدودیت‌ها

این بخش برخی‌از محدودیت‌های شناخته‌شده چارچوب انتقال‌ها را فهرست می‌کند:

  • پویانمایی‌های اعمال‌شده روی SurfaceView ممکن است به‌درستی نمایش داده نشود. SurfaceView نمونه از رشته غیرمیانای کاربر به‌روزرسانی شده‌اند، بنابراین به‌روزرسانی‌ها ممکن است با پویانمایی‌های نماهای دیگر همگام‌سازی نشده باشند.
  • برخی‌از انواع خاص گذار ممکن است هنگام اعمال شدن روی TextureView، جلوه پویانمایی موردنظر را ایجاد نکنند.
  • کلاس‌هایی که AdapterView را گسترش می‌دهند، مانند ListView، نماهای فرزند خود را به‌گونه‌ای مدیریت می‌کنند که با چارچوب انتقال‌ها ناسازگار است. اگر بخواهید نمایی را براساس AdapterView پویانمایی کنید، ممکن است نمایشگر دستگاه دیگر پاسخ ندهد.
  • اگر بخواهید اندازه TextView را با پویانمایی تغییر دهید، نوشتار قبل‌از اینکه اندازه شیء کاملاً تغییر کند به مکان جدیدی می‌پرد. برای جلوگیری از این مشکل، تغییر اندازه نماهای حاوی نوشتار را پویانمایی نکنید.