نمای کلی پویانمایی ویژگی

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

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

سیستم پویانمایی ویژگی به شما امکان می‌دهد مشخصات زیر را برای پویانمایی تعریف کنید:

  • مدت: می‌توانید مدت پویانمایی را مشخص کنید. طول پیش‌فرض ۳۰۰ میلی‌ثانیه است.
  • درون‌یابی زمان: می‌توانید نحوه محاسبه مقادیر ویژگی را به‌عنوان تابعی از زمان سپری‌شده فعلی پویانمایی مشخص کنید.
  • تعداد تکرار و رفتار: می‌توانید مشخص کنید که آیا پویانمایی پس‌از رسیدن به پایان مدت تکرار شود یا نه و چند بار تکرار شود. همچنین می‌توانید مشخص کنید که می‌خواهید پویانمایی به‌صورت معکوس پخش شود یا نه. تنظیم آن روی «معکوس» پویانمایی را به‌طور مکرر به‌جلو و سپس به‌عقب پخش می‌کند تا زمانی که تعداد تکرارها به‌پایان برسد.
  • مجموعه‌های پویانما: می‌توانید پویانمایی‌ها را در مجموعه‌های منطقی گروه‌بندی کنید که باهم یا به‌صورت متوالی یا پس‌از تأخیرهای مشخص‌شده پخش می‌شوند.
  • تأخیر بازآوری قاب: می‌توانید مشخص کنید که قاب‌های پویانمایی شما هر چند وقت یک‌بار بازآوری شوند. به‌طور پیش‌فرض، بازآوری هر ۱۰ میلی‌ثانیه انجام می‌شود، اما سرعت بازآوری قاب‌ها در برنامه شما درنهایت به میزان مشغول بودن کلی سیستم و سرعت سیستم در ارائه خدمات به زمان‌سنج اصلی بستگی دارد.

برای دیدن نمونه کامل پویانمایی ویژگی، کلاس ChangeColor را در نمونه CustomTransition در GitHub ببینید.

نحوه عملکرد پویانمایی ویژگی

ابتدا، بیایید با یک مثال ساده نحوه عملکرد پویانمایی را بررسی کنیم. شکل ۱ شیء فرضی‌ای را نشان می‌دهد که با ویژگی x خود پویانمایی شده است، که نشان‌دهنده مکان افقی آن در صفحه‌نمایش است. مدت پویانمایی روی ۴۰ میلی‌ثانیه و فاصله حرکت روی ۴۰ پیکسل تنظیم شده است. هر ۱۰ میلی‌ثانیه، که نرخ بازآوری قاب پیش‌فرض است، شیء به‌صورت افقی ۱۰ پیکسل حرکت می‌کند. در پایان ۴۰ میلی‌ثانیه، پویانمایی متوقف می‌شود و شیء در موقعیت افقی ۴۰ قرار می‌گیرد. این نمونه‌ای از پویانمایی با درون‌یابی خطی است، یعنی شیء با سرعت ثابتی حرکت می‌کند.

شکل ۱. نمونه‌ای از پویانمایی خطی

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

شکل ۲. نمونه‌ای از پویانمایی غیرخطی

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

شکل ۳. نحوه محاسبه پویانمایی‌ها

شیء ValueAnimator زمان‌بندی پویانمایی شما را پیگیری می‌کند، مانند مدت‌زمانی که پویانمایی درحال اجرا بوده است و مقدار فعلی ویژگی‌ای که درحال پویانمایی است.

ValueAnimator یک TimeInterpolator را که درون‌یابی پویانمایی را تعریف می‌کند و یک TypeEvaluator را که نحوه محاسبه مقادیر برای ویژگی درحال پویانمایی را تعریف می‌کند، کپسوله‌سازی می‌کند. برای مثال، در شکل ۲، TimeInterpolator استفاده‌شده AccelerateDecelerateInterpolator و TypeEvaluator IntEvaluator خواهد بود.

برای شروع پویانمایی، یک ValueAnimator ایجاد کنید و مقادیر شروع و پایان را برای ویژگی‌ای که می‌خواهید پویانمایی کنید، همراه با مدت‌زمان پویانمایی به آن بدهید. وقتی start() را صدا می‌زنید، پویانمایی شروع می‌شود. درطول کل پویانمایی، ValueAnimator کسر سپری‌شده را بین ۰ و ۱ براساس مدت پویانمایی و مقدار زمان سپری‌شده محاسبه می‌کند. کسر سپری‌شده نشان‌دهنده درصد زمانی است که پویانمایی تکمیل شده است، ۰ به‌معنای ۰٪ و ۱ به‌معنای ۱۰۰٪ است. برای مثال، در شکل ۱، کسر سپری‌شده در t = 10 ms برابر با ‎ .25 خواهد بود زیرا مدت کل t = 40 ms است.

وقتی ValueAnimator محاسبه کسر سپری‌شده را تمام می‌کند، TimeInterpolator را که درحال‌حاضر تنظیم شده است فراخوانی می‌کند تا کسر درون‌یابی‌شده را محاسبه کند. کسر درون‌یابی‌شده کسر سپری‌شده را به کسر جدیدی نگاشت می‌کند که درون‌یابی زمانی تنظیم‌شده را درنظر می‌گیرد. برای مثال، در شکل ۲، چون پویانمایی به‌آرامی شتاب می‌گیرد، کسر درون‌یابی‌شده، حدود ۰٫۱۵، کمتر از کسر سپری‌شده، ۰٫۲۵، در t = ۱۰ میلی‌ثانیه است. در شکل ۱، کسر درون‌یابی‌شده همیشه با کسر سپری‌شده یکسان است.

وقتی کسر درون‌یابی‌شده محاسبه می‌شود، ValueAnimator TypeEvaluator مناسب را فراخوانی می‌کند تا مقدار ویژگی‌ای را که درحال پویانمایی آن هستید براساس کسر درون‌یابی‌شده، مقدار شروع، و مقدار پایان پویانمایی محاسبه کند. برای مثال، در شکل ۲، کسر میان‌یابی‌شده در t =‏ ۱۰ میلی‌ثانیه برابر با ۰٫۱۵ بود، بنابراین مقدار ویژگی در آن زمان برابر با ۰٫۱۵ × (۴۰ - ۰) یا ۶ خواهد بود.

تفاوت پویانمایی ویژگی با پویانمایی نما

سیستم پویانمایی نما قابلیت پویانمایی کردن فقط اشیای View را ارائه می‌دهد، بنابراین اگر بخواهید اشیای غیرView را پویانمایی کنید، باید کد خودتان را برای انجام این کار پیاده‌سازی کنید. سیستم پویانمایی نما همچنین از این نظر محدود است که فقط چند جنبه از شیء View را برای پویانمایی کردن نشان می‌دهد، مثلاً مقیاس‌بندی و چرخش «نما» و نه رنگ پس‌زمینه.

Another disadvantage of the view animation system is that it only modified where the View was drawn, and not the actual View itself. برای مثال، اگر دکمه‌ای را برای حرکت در صفحه پویانمایی کنید، دکمه به‌درستی ترسیم می‌شود، اما مکان واقعی که می‌توانید روی دکمه کلیک کنید تغییر نمی‌کند، بنابراین باید منطق خود را برای مدیریت این موضوع پیاده‌سازی کنید.

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

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

نمای کلی میانای برنامه‌سازی کاربردی

می‌توانید اکثر میاناهای برنامه‌سازی کاربردی سیستم پویانمایی ویژگی را در android.animation پیدا کنید. چون سیستم پویانمایی نما ازقبل درون‌یاب‌های زیادی را در android.view.animation تعریف می‌کند، می‌توانید از آن درون‌یاب‌ها در سیستم پویانمایی ویژگی نیز استفاده کنید. جدول‌های زیر مؤلفه‌های اصلی سیستم پویانمایی ویژگی را شرح می‌دهند.

کلاس Animator ساختار اصلی را برای ایجاد پویانمایی‌ها فراهم می‌کند. معمولاً از این کلاس مستقیماً استفاده نمی‌کنید زیرا فقط حداقل عملکردی را ارائه می‌دهد که باید برای پشتیبانی کامل از مقادیر پویانمایی گسترش یابد. زیرکلاس‌های زیر Animator را گسترش می‌دهند:

جدول ۱. پویانمایی‌سازان

کلاس شرح
ValueAnimator موتور زمان‌بندی اصلی برای پویانمایی ویژگی که مقادیر ویژگی را نیز برای پویانمایی محاسبه می‌کند. این کلاس همه عملکردهای اصلی را که مقادیر پویانمایی را محاسبه می‌کنند دارد و حاوی جزئیات زمان‌بندی هر پویانمایی، اطلاعاتی درباره اینکه آیا پویانمایی تکرار می‌شود یا نه، شنوندگانی که رویدادهای به‌روزرسانی را دریافت می‌کنند، و توانایی تنظیم انواع سفارشی برای ارزیابی است. پویانمایی کردن ویژگی‌ها دو بخش دارد: محاسبه کردن مقادیر پویانمایی‌شده و تنظیم کردن آن مقادیر روی شیء و ویژگی‌ای که پویانمایی می‌شود. ValueAnimator بخش دوم را انجام نمی‌دهد، بنابراین باید برای به‌روزرسانی‌های مقادیر محاسبه‌شده توسط ValueAnimator گوش دهید و اشیایی را که می‌خواهید با منطق خودتان پویانمایی کنید اصلاح کنید. برای اطلاعات بیشتر، بخش مربوط به پویانمایی با ValueAnimator را ببینید.
ObjectAnimator زیرکلاسی از ValueAnimator که به شما امکان می‌دهد شیء هدف و ویژگی شیء را برای پویانمایی تنظیم کنید. این کلاس وقتی مقدار جدیدی برای پویانمایی محاسبه می‌کند، ویژگی را به‌طور متناسب به‌روز می‌کند. بیشتر اوقات بهتر است از ObjectAnimator استفاده کنید، چون فرایند پویانمایی مقادیر را در اشیاء هدف بسیار آسان‌تر می‌کند. بااین‌حال، گاهی اوقات می‌خواهید مستقیماً از ValueAnimator استفاده کنید زیرا ObjectAnimator چند محدودیت بیشتر دارد، مثلاً لازم است روش‌های دستیاب خاصی در شیء هدف وجود داشته باشد.
AnimatorSet سازوکاری برای گروه‌بندی پویانمایی‌ها با هم ارائه می‌دهد تا در ارتباط با یکدیگر اجرا شوند. می‌توانید پویانمایی‌ها را طوری تنظیم کنید که باهم، به‌صورت متوالی، یا پس‌از تأخیری مشخص پخش شوند. برای اطلاعات بیشتر، بخش مربوط به طراحی رقص چند پویانمایی با مجموعه‌های Animator را ببینید.

ارزیاب‌ها به سیستم پویانمایی ویژگی می‌گویند که چگونه مقادیر را برای یک ویژگی معین محاسبه کند. این ارزیاب‌ها داده‌های زمان‌بندی را که توسط کلاس Animator ارائه می‌شود، مقدار شروع و پایان پویانمایی را می‌گیرند و مقادیر پویانمایی‌شده ویژگی را براساس این داده‌ها محاسبه می‌کنند. سیستم پویانمایی ویژگی ارزیاب‌های زیر را ارائه می‌دهد:

جدول ۲. ارزیابی‌کنندگان

کلاس/میانا شرح
IntEvaluator ارزیاب پیش‌فرض برای محاسبه مقادیر ویژگی‌های int.
FloatEvaluator ارزیاب پیش‌فرض برای محاسبه مقادیر ویژگی‌های float.
ArgbEvaluator ارزیاب پیش‌فرض برای محاسبه مقادیر ویژگی‌های رنگ که به‌صورت مقادیر شانزده‌شانزدهی نشان داده می‌شوند.
TypeEvaluator میانایی که به شما امکان می‌دهد ارزیاب خودتان را ایجاد کنید. اگر درحال پویانمایی کردن ویژگی شیئی هستید که نه int، float، یا رنگ است، باید میانای TypeEvaluator را پیاده‌سازی کنید تا مشخص کنید چگونه مقادیر پویانمایی‌شده ویژگی شیء محاسبه شود. همچنین می‌توانید TypeEvaluator سفارشی برای int، float، و مقادیر رنگ مشخص کنید، اگر می‌خواهید این نوع‌ها را متفاوت از رفتار پیش‌فرض پردازش کنید. برای اطلاعات بیشتر درباره نحوه نوشتن ارزیاب سفارشی، بخش مربوط به استفاده از TypeEvaluator را ببینید.

درون‌یاب زمان نحوه محاسبه مقادیر خاص در پویانمایی را به‌عنوان تابعی از زمان تعریف می‌کند. برای مثال، می‌توانید مشخص کنید که پویانمایی‌ها به‌صورت خطی در کل پویانمایی اتفاق بیفتند، یعنی پویانمایی در کل زمان به‌طور یکنواخت حرکت کند، یا می‌توانید مشخص کنید که پویانمایی‌ها از زمان غیرخطی استفاده کنند، برای مثال، در شروع پویانمایی شتاب بگیرند و در پایان پویانمایی سرعتشان کاهش یابد. جدول ۳ درون‌یاب‌های موجود در android.view.animation را شرح می‌دهد. اگر هیچ‌کدام از میان‌یاب‌های ارائه‌شده برای نیازهای شما مناسب نیست، میانای TimeInterpolator را پیاده‌سازی کنید و میان‌یاب خودتان را بسازید. برای اطلاعات بیشتر درباره نحوه نوشتن میان‌یاب سفارشی، استفاده از میان‌یاب‌ها را ببینید.

جدول ۳. درون‌یاب‌ها

کلاس/میانا شرح
AccelerateDecelerateInterpolator درون‌یابی که نرخ تغییر آن به‌آرامی شروع و پایان می‌یابد اما در وسط شتاب می‌گیرد.
AccelerateInterpolator درون‌یابی که نرخ تغییر آن به‌آرامی شروع می‌شود و سپس شتاب می‌گیرد.
AnticipateInterpolator درون‌یابی که تغییر آن از عقب شروع می‌شود و سپس به جلو پرتاب می‌شود.
AnticipateOvershootInterpolator درون‌یابی که تغییر آن از عقب شروع می‌شود، به جلو پرتاب می‌شود و از مقدار هدف فراتر می‌رود، سپس درنهایت به مقدار نهایی برمی‌گردد.
BounceInterpolator درون‌یابی که تغییر آن در پایان جهش می‌کند.
CycleInterpolator درون‌یابی که پویانمایی آن برای تعداد مشخصی از چرخه‌ها تکرار می‌شود.
DecelerateInterpolator درون‌یابی که نرخ تغییر آن به‌سرعت شروع می‌شود و سپس کاهش می‌یابد.
LinearInterpolator درون‌یابی که نرخ تغییر آن ثابت است.
OvershootInterpolator درون‌یابی که تغییر آن به جلو پرتاب می‌شود و از آخرین مقدار فراتر می‌رود و سپس برمی‌گردد.
TimeInterpolator میانایی که به شما امکان می‌دهد درون‌یاب خودتان را پیاده‌سازی کنید.

پویانمایی بااستفاده از ValueAnimator

کلاس ValueAnimator به شما امکان می‌دهد مقادیر برخی‌از انواع را برای مدت پویانمایی با مشخص کردن مجموعه‌ای از مقادیر int، float، یا رنگ برای پویانمایی کردن ازطریق آن‌ها پویانمایی کنید. با فراخوانی یکی از روش‌های کارخانه‌ای ValueAnimator، می‌توانید آن را دریافت کنید: ofInt()، ofFloat()، یا ofObject(). برای مثال:

کاتلین

ValueAnimator.ofFloat(0f, 100f).apply {
    duration = 1000
    start()
}

جاوا

ValueAnimator animation = ValueAnimator.ofFloat(0f, 100f);
animation.setDuration(1000);
animation.start();

در این کد، ValueAnimator محاسبه مقادیر پویانمایی را بین ۰ و ۱۰۰ برای مدت ۱۰۰۰ میلی‌ثانیه، هنگام اجرای روش start()، شروع می‌کند.

همچنین می‌توانید با انجام دادن کارهای زیر، نوع سفارشی را برای پویانمایی مشخص کنید:

کاتلین

ValueAnimator.ofObject(MyTypeEvaluator(), startPropertyValue, endPropertyValue).apply {
    duration = 1000
    start()
}

جاوا

ValueAnimator animation = ValueAnimator.ofObject(new MyTypeEvaluator(), startPropertyValue, endPropertyValue);
animation.setDuration(1000);
animation.start();

در این کد، ValueAnimator محاسبه مقادیر پویانمایی را بین startPropertyValue و endPropertyValue بااستفاده از منطق ارائه‌شده توسط MyTypeEvaluator برای مدت ۱۰۰۰ میلی‌ثانیه، هنگام اجرای روش start() شروع می‌کند.

می‌توانید با افزودن AnimatorUpdateListener به شیء ValueAnimator، از مقادیر پویانمایی استفاده کنید، همان‌طور که در کد زیر نشان داده شده است:

کاتلین

ValueAnimator.ofObject(...).apply {
    ...
    addUpdateListener { updatedAnimation ->
        // You can use the animated value in a property that uses the
        // same type as the animation. In this case, you can use the
        // float value in the translationX property.
        textView.translationX = updatedAnimation.animatedValue as Float
    }
    ...
}

جاوا

animation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator updatedAnimation) {
        // You can use the animated value in a property that uses the
        // same type as the animation. In this case, you can use the
        // float value in the translationX property.
        float animatedValue = (float)updatedAnimation.getAnimatedValue();
        textView.setTranslationX(animatedValue);
    }
});

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

پویانمایی بااستفاده از ObjectAnimator

‫ObjectAnimator زیرکلاسی از ValueAnimator (که در بخش قبلی بحث شد) است و موتور زمان‌بندی و محاسبه مقدار ValueAnimator را با توانایی پویانمایی کردن ویژگی نام‌گذاری‌شده شیء هدف ترکیب می‌کند. این کار پویانمایی هر شیء را بسیار آسان‌تر می‌کند، زیرا دیگر نیازی به پیاده‌سازی ValueAnimator.AnimatorUpdateListener ندارید، چراکه ویژگی پویانمایی‌شده به‌طور خودکار به‌روز می‌شود.

نمونه‌سازی ObjectAnimator شبیه به ValueAnimator است، اما شما همچنین شیء و نام ویژگی آن شیء (به‌عنوان رشته) را همراه با مقادیر برای پویانمایی بین آن‌ها مشخص می‌کنید:

کاتلین

ObjectAnimator.ofFloat(textView, "translationX", 100f).apply {
    duration = 1000
    start()
}

جاوا

ObjectAnimator animation = ObjectAnimator.ofFloat(textView, "translationX", 100f);
animation.setDuration(1000);
animation.start();

برای اینکه ObjectAnimator ویژگی‌های به‌روزرسانی را به‌درستی داشته باشد، باید کارهای زیر را انجام دهید:

  • ویژگی شیء که درحال پویانمایی آن هستید باید تابع تنظیم‌کننده (به‌صورت نگارش شتری) در قالب set<PropertyName>() داشته باشد. ازآنجایی‌که ObjectAnimator به‌طور خودکار ویژگی را درطول پویانمایی به‌روز می‌کند، باید بتواند با این روش تنظیم‌کننده به ویژگی دسترسی پیدا کند. برای مثال، اگر نام دارایی foo است، باید روش setFoo() داشته باشید. اگر این روش تنظیم‌کننده وجود ندارد، سه گزینه دارید:
    • اگر حقوق لازم را دارید، روش تنظیم‌کننده را به کلاس اضافه کنید.
    • از کلاس پوششی استفاده کنید که حق تغییر آن را دارید و آن پوشش را طوری تنظیم کنید که مقدار را با روش تنظیم‌کننده معتبر دریافت کند و آن را به شیء اصلی ارسال کند.
    • درعوض از ValueAnimator استفاده کنید.
  • اگر فقط یک مقدار برای پارامتر values... در یکی از روش‌های کارخانه ObjectAnimator مشخص کنید، فرض می‌شود که مقدار پایانی پویانمایی است. بنابراین، ویژگی شیء که درحال پویانمایی آن هستید باید تابع گیرنده‌ای داشته باشد که برای به‌دست آوردن مقدار شروع پویانمایی استفاده می‌شود. تابع گیرنده باید به‌صورت get<PropertyName>() باشد. برای مثال، اگر نام دارایی foo باشد، باید روش getFoo() داشته باشید.
  • روش‌های گیرنده (درصورت نیاز) و تنظیم‌کننده ویژگی‌ای که پویانمایی می‌کنید باید روی همان نوع مقادیر شروع و پایانی که برای ObjectAnimator مشخص می‌کنید عمل کنند. برای مثال، اگر ObjectAnimator زیر را بسازید، باید targetObject.setPropName(float) و targetObject.getPropName() را داشته باشید:
    ObjectAnimator.ofFloat(targetObject, "propName", 1f)
  • بسته به اینکه کدام ویژگی یا شیء را پویانمایی می‌کنید، ممکن است لازم باشد متد invalidate() را در View فراخوانی کنید تا صفحه مجبور شود خودش را با مقادیر پویانمایی‌شده به‌روزشده دوباره ترسیم کند. این کار را در onAnimationUpdate() فراخوانی برگشتی انجام می‌دهید. برای مثال، پویانمایی ویژگی رنگ یک شیء Drawable فقط زمانی باعث به‌روزرسانی صفحه می‌شود که آن شیء خودش را دوباره ترسیم کند. همه تنظیم‌کننده‌های ویژگی در View، مانند setAlpha() و setTranslationX() View را به‌درستی باطل می‌کنند، بنابراین نیازی نیست هنگام فراخوانی این روش‌ها با مقادیر جدید، View را باطل کنید. برای اطلاعات بیشتر درباره شنوندگان، به بخش مربوط به شنوندگان پویانمایی مراجعه کنید.

Choreograph multiple animations using an AnimatorSet

در بسیاری‌از موارد، می‌خواهید پویانمایی‌ای را پخش کنید که به زمان شروع یا پایان پویانمایی دیگری بستگی دارد. سیستم Android به شما امکان می‌دهد پویانمایی‌ها را در یک AnimatorSet دسته‌بندی کنید تا بتوانید مشخص کنید که پویانمایی‌ها به‌صورت هم‌زمان، متوالی، یا پس‌از تأخیری مشخص شروع شوند. همچنین می‌توانید اشیاء AnimatorSet را در یکدیگر آشیانه کنید.

تکه‌کد زیر، Animator شیء زیر را به روش زیر پخش می‌کند:

  1. ‫bounceAnim را پخش می‌کند.
  2. squashAnim1، squashAnim2، stretchAnim1، و stretchAnim2 را هم‌زمان پخش می‌کند.
  3. ‫bounceBackAnim را پخش می‌کند.
  4. ‫fadeAnim را پخش می‌کند.

کاتلین

val bouncer = AnimatorSet().apply {
    play(bounceAnim).before(squashAnim1)
    play(squashAnim1).with(squashAnim2)
    play(squashAnim1).with(stretchAnim1)
    play(squashAnim1).with(stretchAnim2)
    play(bounceBackAnim).after(stretchAnim2)
}
val fadeAnim = ObjectAnimator.ofFloat(newBall, "alpha", 1f, 0f).apply {
    duration = 250
}
AnimatorSet().apply {
    play(bouncer).before(fadeAnim)
    start()
}

جاوا

AnimatorSet bouncer = new AnimatorSet();
bouncer.play(bounceAnim).before(squashAnim1);
bouncer.play(squashAnim1).with(squashAnim2);
bouncer.play(squashAnim1).with(stretchAnim1);
bouncer.play(squashAnim1).with(stretchAnim2);
bouncer.play(bounceBackAnim).after(stretchAnim2);
ValueAnimator fadeAnim = ObjectAnimator.ofFloat(newBall, "alpha", 1f, 0f);
fadeAnim.setDuration(250);
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.play(bouncer).before(fadeAnim);
animatorSet.start();

شنوندگان پویانمایی

می‌توانید با شنوندگان شرح‌داده‌شده در زیر، رویدادهای مهم را درطول مدت پویانمایی بشنوید.

  • Animator.AnimatorListener
    • onAnimationStart() - وقتی پویانمایی شروع می‌شود، فراخوانی می‌شود.
    • onAnimationEnd() - وقتی پویانمایی تمام می‌شود، فراخوانی می‌شود.
    • onAnimationRepeat() - Called when the animation repeats itself.
    • onAnimationCancel() - وقتی پویانمایی لغو می‌شود، فراخوانی می‌شود. پویانمایی لغوشده onAnimationEnd() را نیز فراخوانی می‌کند، صرف‌نظر از اینکه چگونه پایان یافته است.
  • ValueAnimator.AnimatorUpdateListener
    • ‫onAnimationUpdate() - در هر قاب پویانمایی فراخوانی می‌شود. به این رویداد گوش دهید تا از مقادیر محاسبه‌شده تولیدشده توسط ValueAnimator درطول پویانمایی استفاده کنید. برای استفاده از مقدار، شیء ValueAnimator را که به رویداد ارسال شده است پُرسمان کنید تا مقدار پویانمایی‌شده فعلی را با روش getAnimatedValue() دریافت کنید. اگر از ValueAnimator استفاده می‌کنید، پیاده‌سازی این شنونده الزامی است.

      بسته به اینکه کدام دارایی یا شیء را پویانمایی می‌کنید، ممکن است لازم باشد invalidate() را در View فراخوانی کنید تا آن ناحیه از صفحه مجبور شود خودش را با مقادیر پویانمایی‌شده جدید بازترسیم کند. برای مثال، پویانمایی کردن ویژگی رنگ شیء Drawable فقط زمانی باعث به‌روزرسانی صفحه‌نمایش می‌شود که آن شیء خودش را دوباره ترسیم کند. همه تنظیم‌کننده‌های ویژگی در View، مثل setAlpha() و setTranslationX()، View را به‌درستی باطل می‌کنند، بنابراین هنگام فراخوانی این روش‌ها با مقادیر جدید، نیازی به باطل کردن View ندارید.

اگر نمی‌خواهید همه روش‌های میانای Animator.AnimatorListener را پیاده‌سازی کنید، می‌توانید به‌جای پیاده‌سازی میانای Animator.AnimatorListener، کلاس AnimatorListenerAdapter را گسترش دهید. کلاس AnimatorListenerAdapter پیاده‌سازی‌های خالی از روش‌هایی را ارائه می‌دهد که می‌توانید برای لغو انتخاب کنید.

برای مثال، تکه‌کد زیر یک AnimatorListenerAdapter فقط برای فراخوانی برگشتی onAnimationEnd() ایجاد می‌کند:

کاتلین

ObjectAnimator.ofFloat(newBall, "alpha", 1f, 0f).apply {
    duration = 250
    addListener(object : AnimatorListenerAdapter() {
        override fun onAnimationEnd(animation: Animator) {
            balls.remove((animation as ObjectAnimator).target)
        }
    })
}

جاوا

ValueAnimator fadeAnim = ObjectAnimator.ofFloat(newBall, "alpha", 1f, 0f);
fadeAnim.setDuration(250);
fadeAnim.addListener(new AnimatorListenerAdapter() {
public void onAnimationEnd(Animator animation) {
    balls.remove(((ObjectAnimator)animation).getTarget());
}

پویانمایی تغییرات چیدمان در اشیای ViewGroup

سیستم پویانمایی ویژگی امکان پویانمایی تغییرات در اشیای ViewGroup را فراهم می‌کند و همچنین روشی آسان برای پویانمایی خود اشیای View ارائه می‌دهد.

می‌توانید تغییرات چیدمان را در ViewGroup با کلاس LayoutTransition پویانمایی کنید. نماهای داخل ViewGroup می‌توانند هنگام افزودن یا حذف آن‌ها از ViewGroup یا هنگام فراخوانی روش setVisibility() یک View با VISIBLE، INVISIBLE، یا GONE، از یک پویانمایی ظاهر شدن و ناپدید شدن عبور کنند. وقتی «نماها» را اضافه یا حذف می‌کنید، «نماهای» باقی‌مانده در ViewGroup نیز می‌توانند به موقعیت‌های جدیدشان پویانمایی شوند. می‌توانید پویانمایی‌های زیر را در شیء LayoutTransition با فراخوانی setAnimator() و ارسال شیء Animator با یکی از ثابت‌های LayoutTransition زیر تعریف کنید:

  • APPEARING - پرچمی که پویانمایی اجراشده روی مواردی را که در محفظه ظاهر می‌شوند نشان می‌دهد.
  • CHANGE_APPEARING - پرچمی که پویانمایی اجراشده روی مواردی را نشان می‌دهد که به‌دلیل ظاهر شدن موردی جدید در محفظه درحال تغییر هستند.
  • DISAPPEARING - پرچمی که پویانمایی اجراشده روی مواردی را نشان می‌دهد که درحال ناپدید شدن از محفظه هستند.
  • CHANGE_DISAPPEARING - پرچمی که پویانمایی اجراشده روی مواردی را نشان می‌دهد که به‌دلیل ناپدید شدن موردی از ظرف درحال تغییر هستند.

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

برای تنظیم مشخصه android:animateLayoutchanges روی true برای ViewGroup، کارهای زیر را انجام دهید:

<LinearLayout
    android:orientation="vertical"
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    android:id="@+id/verticalContainer"
    android:animateLayoutChanges="true" />

تنظیم این مشخصه روی true به‌طور خودکار «نماهایی» را که به ViewGroup اضافه یا از آن برداشته شده‌اند، و همچنین «نماهای» باقی‌مانده در ViewGroup را پویانمایی می‌کند.

پویانمایی تغییرات وضعیت نما بااستفاده از StateListAnimator

کلاس StateListAnimator به شما امکان می‌دهد پویانماهایی را تعریف کنید که هنگام تغییر وضعیت نما اجرا می‌شوند. این شیء به‌عنوان پوششی برای شیء Animator عمل می‌کند و هرگاه وضعیت نمای مشخص‌شده (مانند «فشرده‌شده» یا «متمرکزشده») تغییر کند، آن پویانمایی را فراخوانی می‌کند.

StateListAnimator را می‌توان در منبع XML با عنصر ریشه <selector> و عناصر فرزند <item> تعریف کرد که هرکدام حالت نمای متفاوتی را که توسط کلاس StateListAnimator تعریف شده است مشخص می‌کنند. هر <item> حاوی تعریف مجموعه پویانمایی ویژگی است.

برای مثال، فایل زیر یک پویانمای فهرست وضعیت ایجاد می‌کند که مقیاس x و y نما را هنگام فشار دادن آن تغییر می‌دهد:

res/xml/animate_scale.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- the pressed state; increase x and y size to 150% -->
    <item android:state_pressed="true">
        <set>
            <objectAnimator android:propertyName="scaleX"
                android:duration="@android:integer/config_shortAnimTime"
                android:valueTo="1.5"
                android:valueType="floatType"/>
            <objectAnimator android:propertyName="scaleY"
                android:duration="@android:integer/config_shortAnimTime"
                android:valueTo="1.5"
                android:valueType="floatType"/>
        </set>
    </item>
    <!-- the default, non-pressed state; set x and y size to 100% -->
    <item android:state_pressed="false">
        <set>
            <objectAnimator android:propertyName="scaleX"
                android:duration="@android:integer/config_shortAnimTime"
                android:valueTo="1"
                android:valueType="floatType"/>
            <objectAnimator android:propertyName="scaleY"
                android:duration="@android:integer/config_shortAnimTime"
                android:valueTo="1"
                android:valueType="floatType"/>
        </set>
    </item>
</selector>

برای پیوست کردن پویانمای فهرست وضعیت به نما، مشخصه android:stateListAnimator را به‌صورت زیر اضافه کنید:

<Button android:stateListAnimator="@xml/animate_scale"
        ... />

اکنون پویانمایی‌های تعریف‌شده در animate_scale.xml هنگام تغییر وضعیت این دکمه استفاده می‌شوند.

یا برای اینکه به‌جای آن، پویانمایی فهرست وضعیت را به نمایی در کدتان اختصاص دهید، از روش AnimatorInflater.loadStateListAnimator() استفاده کنید و پویانمایی را با روش View.setStateListAnimator() به نمایتان اختصاص دهید.

یا به‌جای پویانمایی کردن ویژگی‌های نما، می‌توانید بااستفاده از AnimatedStateListDrawable، پویانمایی قابل‌ترسیمی را بین تغییرات وضعیت پخش کنید. برخی‌از ابزاره‌های سیستم در Android 5.0 به‌طور پیش‌فرض از این پویانمایی‌ها استفاده می‌کنند. مثال زیر نشان می‌دهد که چگونه AnimatedStateListDrawable را به‌عنوان منبع XML تعریف کنید:

<!-- res/drawable/myanimstatedrawable.xml -->
<animated-selector
    xmlns:android="http://schemas.android.com/apk/res/android">

    <!-- provide a different drawable for each state-->
    <item android:id="@+id/pressed" android:drawable="@drawable/drawableP"
        android:state_pressed="true"/>
    <item android:id="@+id/focused" android:drawable="@drawable/drawableF"
        android:state_focused="true"/>
    <item android:id="@id/default"
        android:drawable="@drawable/drawableD"/>

    <!-- specify a transition -->
    <transition android:fromId="@+id/default" android:toId="@+id/pressed">
        <animation-list>
            <item android:duration="15" android:drawable="@drawable/dt1"/>
            <item android:duration="15" android:drawable="@drawable/dt2"/>
            ...
        </animation-list>
    </transition>
    ...
</animated-selector>

از TypeEvaluator استفاده کنید

اگر می‌خواهید نوعی را که برای سیستم Android ناشناخته است پویانمایی کنید، می‌توانید با پیاده‌سازی میانای TypeEvaluator، ارزیاب خودتان را ایجاد کنید. انواعی که سیستم Android می‌شناسد عبارت‌اند از int، float، یا رنگ، که ارزیاب‌های نوع IntEvaluator، FloatEvaluator، و ArgbEvaluator از آن‌ها پشتیبانی می‌کنند.

فقط یک روش برای پیاده‌سازی در میانای TypeEvaluator وجود دارد، روش evaluate(). این کار به پویانماگری که استفاده می‌کنید اجازه می‌دهد مقدار مناسبی را برای ویژگی پویانمایی‌شده شما در نقطه فعلی پویانمایی برگرداند. کلاس FloatEvaluator نحوه انجام این کار را نشان می‌دهد:

کاتلین

private class FloatEvaluator : TypeEvaluator<Any> {

    override fun evaluate(fraction: Float, startValue: Any, endValue: Any): Any {
        return (startValue as Number).toFloat().let { startFloat ->
            startFloat + fraction * ((endValue as Number).toFloat() - startFloat)
        }
    }

}

جاوا

public class FloatEvaluator implements TypeEvaluator {

    public Object evaluate(float fraction, Object startValue, Object endValue) {
        float startFloat = ((Number) startValue).floatValue();
        return startFloat + fraction * (((Number) endValue).floatValue() - startFloat);
    }
}

توجه: وقتی ValueAnimator (یا ObjectAnimator) اجرا می‌شود، کسر سپری‌شده فعلی پویانمایی (مقداری بین ۰ و ۱) را محاسبه می‌کند و سپس نسخه درون‌یابی‌شده آن را بسته به درون‌یابی که استفاده می‌کنید محاسبه می‌کند. کسر درون‌یابی‌شده چیزی است که TypeEvaluator شما ازطریق پارامتر fraction دریافت می‌کند، بنابراین هنگام محاسبه مقادیر پویانمایی‌شده نیازی به درنظر گرفتن درون‌یاب ندارید.

استفاده از درون‌یاب‌ها

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

درون‌یاب‌ها در سیستم پویانمایی کسری از «پویانماها» دریافت می‌کنند که نشان‌دهنده زمان سپری‌شده پویانمایی است. درون‌یاب‌ها این کسر را تغییر می‌دهند تا با نوع پویانمایی‌ای که هدفش ارائه آن است مطابقت داشته باشد. سیستم Android مجموعه‌ای از میان‌یاب‌های رایج را در android.view.animation package ارائه می‌دهد. اگر هیچ‌کدام از این‌ها مناسب نیازهایتان نیست، می‌توانید میانای TimeInterpolator را پیاده‌سازی کنید و میانای خودتان را ایجاد کنید.

به‌عنوان مثال، نحوه محاسبه کسر میان‌یابی‌شده توسط میان‌یاب پیش‌فرض AccelerateDecelerateInterpolator و LinearInterpolator در زیر مقایسه شده است. ‫LinearInterpolator تأثیری بر کسر سپری‌شده ندارد. AccelerateDecelerateInterpolator در پویانمایی شتاب می‌گیرد و در خارج از آن سرعتش کاهش می‌یابد. روش‌های زیر منطق این میان‌یاب‌ها را تعریف می‌کنند:

AccelerateDecelerateInterpolator

کاتلین

override fun getInterpolation(input: Float): Float =
        (Math.cos((input + 1) * Math.PI) / 2.0f).toFloat() + 0.5f

جاوا

@Override
public float getInterpolation(float input) {
    return (float)(Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f;
}

LinearInterpolator

کاتلین

override fun getInterpolation(input: Float): Float = input

جاوا

@Override
public float getInterpolation(float input) {
    return input;
}

جدول زیر مقادیر تقریبی را نشان می‌دهد که توسط این درون‌یاب‌ها برای پویانمایی‌ای که ۱۰۰۰ میلی‌ثانیه طول می‌کشد محاسبه شده است:

میلی‌ثانیه سپری‌شده کسر سپری‌شده/کسر درون‌یابی‌شده (خطی) کسر درون‌یابی‌شده (شتاب‌دهی/کاهش سرعت)
0 0 0
۲۰۰ ‫۲- .1
۴۰۰ ‫۰٫۴ .345
600 .6 ‫.۶۵۴
۸۰۰ ‫۰٫۸ ‫۰٫۹
1000 1 1

همان‌طور که جدول نشان می‌دهد، LinearInterpolator مقادیر را با سرعت یکسان تغییر می‌دهد، یعنی ۰٫۲ برای هر ۲۰۰ میلی‌ثانیه‌ای که می‌گذرد. ‫AccelerateDecelerateInterpolator مقادیر را سریع‌تر از LinearInterpolator بین ۲۰۰ میلی‌ثانیه و ۶۰۰ میلی‌ثانیه و کندتر بین ۶۰۰ میلی‌ثانیه و ۱۰۰۰ میلی‌ثانیه تغییر می‌دهد.

مشخص کردن قاب‌های کلیدی

یک شیء Keyframe شامل یک جفت زمان/مقدار است که به شما امکان می‌دهد یک حالت خاص را در یک زمان خاص از یک پویانمایی تعریف کنید. هر قاب کلیدی می‌تواند میان‌یاب خودش را نیز داشته باشد تا رفتار پویانمایی را در فاصله زمانی بین زمان قاب کلیدی قبلی و زمان این قاب کلیدی کنترل کند.

برای نمونه‌سازی شیء Keyframe، باید از یکی از روش‌های کارخانه‌ای ofInt()، ofFloat()، یا ofObject() استفاده کنید تا نوع مناسب Keyframe را به‌دست آورید. سپس روش کارخانه ofKeyframe() را فراخوانی می‌کنید تا شیء PropertyValuesHolder را دریافت کنید. وقتی شیء را دارید، می‌توانید با ارسال شیء PropertyValuesHolder و شیء موردنظر برای پویانمایی، یک پویانما دریافت کنید. تکه‌کد زیر نحوه انجام این کار را نشان می‌دهد:

کاتلین

val kf0 = Keyframe.ofFloat(0f, 0f)
val kf1 = Keyframe.ofFloat(.5f, 360f)
val kf2 = Keyframe.ofFloat(1f, 0f)
val pvhRotation = PropertyValuesHolder.ofKeyframe("rotation", kf0, kf1, kf2)
ObjectAnimator.ofPropertyValuesHolder(target, pvhRotation).apply {
    duration = 5000
}

جاوا

Keyframe kf0 = Keyframe.ofFloat(0f, 0f);
Keyframe kf1 = Keyframe.ofFloat(.5f, 360f);
Keyframe kf2 = Keyframe.ofFloat(1f, 0f);
PropertyValuesHolder pvhRotation = PropertyValuesHolder.ofKeyframe("rotation", kf0, kf1, kf2);
ObjectAnimator rotationAnim = ObjectAnimator.ofPropertyValuesHolder(target, pvhRotation);
rotationAnim.setDuration(5000);

پویانمایی کردن نماها

سیستم پویانمایی ویژگی امکان پویانمایی ساده‌شده اشیاء View را فراهم می‌کند و چند مزیت نسبت‌به سیستم پویانمایی نما ارائه می‌دهد. سیستم پویانمایی نما، اشیای «نما» را با تغییر دادن نحوه ترسیم آن‌ها تبدیل می‌کرد. این کار در محفظه هر View انجام می‌شد، زیرا خود View هیچ ویژگی‌ای برای دستکاری نداشت. این کار باعث پویانمایی View شد، اما تغییری در خود شیء View ایجاد نکرد. این امر منجر به رفتاری مانند وجود داشتن شیء در مکان اصلی خود می‌شد، حتی اگر در مکان دیگری در صفحه کشیده شده بود. در Android 3.0، ویژگی‌های جدید و روش‌های گیرنده و تنظیم‌کننده مربوطه برای رفع این اشکال اضافه شدند.

سیستم پویانمایی ویژگی می‌تواند با تغییر ویژگی‌های واقعی در اشیاء «نما»، «نماها» را در صفحه پویانمایی کند. علاوه‌براین، «نماها» به‌طور خودکار روش invalidate() را نیز فراخوانی می‌کنند تا هرگاه ویژگی‌های آن تغییر کرد، صفحه‌نمایش را بازآوری کنند. مشخصه‌های جدید در کلاس View که پویانمایی‌های مشخصه را تسهیل می‌کنند عبارت‌اند از:

  • translationX و translationY: این ویژگی‌ها کنترل می‌کنند که «نما» در کجا به‌عنوان دلتا از مختصات چپ و بالای آن که توسط محفظه چیدمان آن تنظیم شده است قرار دارد.
  • rotation،‏ rotationX، و rotationY: این ویژگی‌ها چرخش را در حالت دوبعدی (ویژگی rotation) و سه‌بعدی حول نقطه محوری کنترل می‌کنند.
  • scaleX و scaleY: این ویژگی‌ها مقیاس‌بندی دوبعدی «نما» را در اطراف نقطه محوری آن کنترل می‌کنند.
  • pivotX و pivotY: این ویژگی‌ها مکان نقطه محوری را کنترل می‌کنند که تبدیل‌های چرخش و مقیاس‌بندی حول آن اتفاق می‌افتد. به‌طور پیش‌فرض، نقطه محوری در مرکز شیء قرار دارد.
  • x و y: این‌ها ویژگی‌های کمکی ساده‌ای برای توصیف مکان نهایی «نما» در ظرف آن هستند، به‌عنوان مجموع مقادیر چپ و بالا و مقادیر translationX و translationY.
  • alpha: شفافیت آلفا را در «نما» نشان می‌دهد. این مقدار به‌طور پیش‌فرض ۱ (مات) است و مقدار ۰ نشان‌دهنده شفافیت کامل (نامرئی) است.

برای پویانمایی ویژگی یک شیء View، مانند رنگ یا مقدار چرخش آن، تنها کاری که باید انجام دهید این است که یک پویانمایی ویژگی ایجاد کنید و ویژگی View را که می‌خواهید پویانمایی کنید مشخص کنید. برای مثال:

کاتلین

ObjectAnimator.ofFloat(myView, "rotation", 0f, 360f)

جاوا

ObjectAnimator.ofFloat(myView, "rotation", 0f, 360f);

برای کسب اطلاعات بیشتر درباره ایجاد پویانما، بخش‌های مربوط به پویانمایی با ValueAnimator و ObjectAnimator را ببینید.

پویانمایی بااستفاده از ViewPropertyAnimator

ViewPropertyAnimator روشی ساده برای پویانمایی کردن چندین ویژگی View به‌صورت موازی بااستفاده از یک شیء Animator زیربنایی ارائه می‌دهد. رفتار آن بسیار شبیه به ObjectAnimator است، زیرا مقادیر واقعی ویژگی‌های نما را تغییر می‌دهد، اما هنگام پویانمایی هم‌زمان بسیاری از ویژگی‌ها کارآمدتر است. علاوه‌براین، کد استفاده از ViewPropertyAnimator بسیار مختصرتر و خواندن آن آسان‌تر است. تکه‌کدهای زیر تفاوت‌های استفاده از چند شیء ObjectAnimator، یک ObjectAnimator، و ViewPropertyAnimator را هنگام پویانمایی هم‌زمان ویژگی x و y یک نما نشان می‌دهند.

چندین شیء ObjectAnimator

کاتلین

val animX = ObjectAnimator.ofFloat(myView, "x", 50f)
val animY = ObjectAnimator.ofFloat(myView, "y", 100f)
AnimatorSet().apply {
    playTogether(animX, animY)
    start()
}

جاوا

ObjectAnimator animX = ObjectAnimator.ofFloat(myView, "x", 50f);
ObjectAnimator animY = ObjectAnimator.ofFloat(myView, "y", 100f);
AnimatorSet animSetXY = new AnimatorSet();
animSetXY.playTogether(animX, animY);
animSetXY.start();

One ObjectAnimator

کاتلین

val pvhX = PropertyValuesHolder.ofFloat("x", 50f)
val pvhY = PropertyValuesHolder.ofFloat("y", 100f)
ObjectAnimator.ofPropertyValuesHolder(myView, pvhX, pvhY).start()

جاوا

PropertyValuesHolder pvhX = PropertyValuesHolder.ofFloat("x", 50f);
PropertyValuesHolder pvhY = PropertyValuesHolder.ofFloat("y", 100f);
ObjectAnimator.ofPropertyValuesHolder(myView, pvhX, pvhY).start();

ViewPropertyAnimator

کاتلین

myView.animate().x(50f).y(100f)

جاوا

myView.animate().x(50f).y(100f);

برای اطلاعات دقیق‌تر درباره ViewPropertyAnimator، به پست وبلاگ مربوطه در «توسعه‌دهندگان Android» مراجعه کنید.

اعلام پویانمایی‌ها در XML

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

برای متمایز کردن فایل‌های پویانمایی که از میاناهای برنامه‌سازی کاربردی پویانمایی ویژگی جدید استفاده می‌کنند از فایل‌هایی که از چارچوب قدیمی پویانمایی نما استفاده می‌کنند، از Android 3.1 به‌بعد، باید فایل‌های XML مربوط به پویانمایی‌های ویژگی را در دایرکتوری res/animator/ ذخیره کنید.

کلاس‌های پویانمایی ویژگی زیر از تعریف XML با برچسب‌های XML زیر پشتیبانی می‌کنند:

برای پیدا کردن مشخصه‌هایی که می‌توانید در اعلان XML استفاده کنید، به منابع پویانمایی مراجعه کنید. مثال زیر دو مجموعه پویانمایی شیء را به‌صورت متوالی پخش می‌کند، به‌طوری‌که اولین مجموعه تودرتو دو پویانمایی شیء را باهم پخش می‌کند:

<set android:ordering="sequentially">
    <set>
        <objectAnimator
            android:propertyName="x"
            android:duration="500"
            android:valueTo="400"
            android:valueType="intType"/>
        <objectAnimator
            android:propertyName="y"
            android:duration="500"
            android:valueTo="300"
            android:valueType="intType"/>
    </set>
    <objectAnimator
        android:propertyName="alpha"
        android:duration="500"
        android:valueTo="1f"/>
</set>

برای اجرای این پویانمایی، باید منابع XML را در کد خود به یک شیء AnimatorSet تبدیل کنید و سپس اشیاء هدف را برای همه پویانمایی‌ها قبل‌از شروع مجموعه پویانمایی تنظیم کنید. فراخوانی setTarget() یک شیء هدف واحد را برای همه فرزندان AnimatorSet به‌عنوان یک راحتی تنظیم می‌کند. کد زیر نحوه انجام این کار را نشان می‌دهد:

کاتلین

(AnimatorInflater.loadAnimator(myContext, R.animator.property_animator) as AnimatorSet).apply {
    setTarget(myObject)
    start()
}

جاوا

AnimatorSet set = (AnimatorSet) AnimatorInflater.loadAnimator(myContext,
    R.animator.property_animator);
set.setTarget(myObject);
set.start();

همچنین می‌توانید ValueAnimator را در XML اعلام کنید، همان‌طور که در مثال زیر نشان داده شده است:

<animator xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1000"
    android:valueType="floatType"
    android:valueFrom="0f"
    android:valueTo="-100f" />

برای استفاده از ValueAnimator قبلی در کدتان، باید شیء را باد کنید، AnimatorUpdateListener اضافه کنید، مقدار پویانمایی به‌روزشده را دریافت کنید، و از آن در ویژگی یکی از نماهایتان استفاده کنید، همان‌طور که در کد زیر نشان داده شده است:

کاتلین

(AnimatorInflater.loadAnimator(this, R.animator.animator) as ValueAnimator).apply {
    addUpdateListener { updatedAnimation ->
        textView.translationX = updatedAnimation.animatedValue as Float
    }

    start()
}

جاوا

ValueAnimator xmlAnimator = (ValueAnimator) AnimatorInflater.loadAnimator(this,
        R.animator.animator);
xmlAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator updatedAnimation) {
        float animatedValue = (float)updatedAnimation.getAnimatedValue();
        textView.setTranslationX(animatedValue);
    }
});

xmlAnimator.start();

برای اطلاعات درباره نحو XML برای تعریف پویانمایی‌های ویژگی، به منابع پویانمایی مراجعه کنید.

تأثیرات احتمالی بر عملکرد واسط کاربر

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

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