نمای کلی انیمیشن خواص

روش نوشتن را امتحان کنید
Jetpack Compose ابزار رابط کاربری پیشنهادی برای اندروید است. یاد بگیرید که چگونه از انیمیشن‌ها در Compose استفاده کنید.

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

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

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

برای دیدن یک مثال کامل از انیمیشن ویژگی، به کلاس ChangeColor در نمونه CustomTransition در GitHub مراجعه کنید.

انیمیشن املاک چگونه کار می‌کند؟

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

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

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

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

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

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

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

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

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

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

وقتی کسر درون‌یابی‌شده محاسبه می‌شود، ValueAnimator ، TypeEvaluator مناسب را فراخوانی می‌کند تا مقدار ویژگی‌ای که شما در حال انیمیشن‌سازی هستید را بر اساس کسر درون‌یابی‌شده، مقدار شروع و مقدار پایان انیمیشن محاسبه کند. برای مثال، در شکل 2، کسر درون‌یابی‌شده در زمان t = 10 میلی‌ثانیه 0.15 بود، بنابراین مقدار ویژگی در آن زمان 0.15 × (40 - 0) یا 6 خواهد بود.

تفاوت انیمیشن ویژگی‌ها با انیمیشن نما

سیستم انیمیشن نما (view animation system) قابلیت متحرک‌سازی فقط اشیاء View objects) را فراهم می‌کند، بنابراین اگر می‌خواهید اشیاء غیرنما (non- View objects) را متحرک‌سازی کنید، باید کد خودتان را برای این کار پیاده‌سازی کنید. سیستم انیمیشن نما همچنین محدود به این واقعیت است که فقط چند جنبه از یک شیء View object) را برای متحرک‌سازی نمایش می‌دهد، مانند مقیاس‌بندی و چرخش یک نما (View)، اما نه رنگ پس‌زمینه (background color).

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

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

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

مرور کلی API

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

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

جدول ۱. انیماتورها

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

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

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

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

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

جدول 3. میان‌یاب‌ها

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

متحرک‌سازی با استفاده از ValueAnimator

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

کاتلین

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 با استفاده از منطق ارائه شده توسط MyTypeEvaluator ، به مدت ۱۰۰۰ میلی‌ثانیه، هنگام اجرای متد start() ، شروع به محاسبه مقادیر انیمیشن، بین startPropertyValue و endPropertyValue می‌کند.

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

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

طراحی رقص چندین انیمیشن با استفاده از AnimatorSet

در بسیاری از موارد، شما می‌خواهید انیمیشنی را پخش کنید که به زمان شروع یا پایان انیمیشن دیگری بستگی دارد. سیستم اندروید به شما امکان می‌دهد انیمیشن‌ها را در یک 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() - وقتی انیمیشن تکرار می‌شود، فراخوانی می‌شود.
    • onAnimationCancel() - زمانی فراخوانی می‌شود که انیمیشن لغو شود. یک انیمیشن لغو شده نیز صرف نظر از نحوه پایان یافتن، onAnimationEnd() را فراخوانی می‌کند.
  • ValueAnimator.AnimatorUpdateListener
    • onAnimationUpdate() - در هر فریم از انیمیشن فراخوانی می‌شود. برای استفاده از مقادیر محاسبه‌شده تولید شده توسط ValueAnimator در طول یک انیمیشن، به این رویداد گوش دهید. برای استفاده از مقدار، شیء ValueAnimator که به رویداد ارسال شده است را جستجو کنید تا مقدار انیمیشن فعلی را با استفاده از متد getAnimatedValue() دریافت کنید. پیاده‌سازی این شنونده در صورت استفاده ValueAnimator الزامی است.

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

اگر نمی‌خواهید تمام متدهای رابط AnimatorListenerAdapter را پیاده‌سازی کنید، می‌توانید به جای پیاده‌سازی رابط Animator.AnimatorListener ، کلاس Animator.AnimatorListener را ارث‌بری کنید. کلاس 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 را فراهم می‌کند.

شما می‌توانید تغییرات طرح‌بندی (layout) را در یک ViewGroup با کلاس LayoutTransition متحرک‌سازی کنید. نماهای (views) درون یک 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 ، یک انیمیشن قابل ترسیم را بین تغییرات حالت اجرا کنید. برخی از ویجت‌های سیستم در اندروید ۵.۰ به طور پیش‌فرض از این انیمیشن‌ها استفاده می‌کنند. مثال زیر نحوه تعریف 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

اگر می‌خواهید نوعی را که برای سیستم اندروید ناشناخته است، متحرک‌سازی کنید، می‌توانید با پیاده‌سازی رابط TypeEvaluator ، ارزیاب خودتان را ایجاد کنید. انواعی که توسط سیستم اندروید شناخته می‌شوند عبارتند از 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 دریافت می‌کند، بنابراین لازم نیست هنگام محاسبه مقادیر انیمیشن، میان‌یابی‌کننده را در نظر بگیرید.

استفاده از میان‌یاب‌ها

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

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

به عنوان مثال، نحوه محاسبه کسرهای درون‌یابی شده توسط میان‌یاب پیش‌فرض AccelerateDecelerateInterpolator و LinearInterpolator در زیر مقایسه شده است. LinearInterpolator هیچ تاثیری بر کسر سپری شده ندارد. 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;
}

میان‌یاب خطی

کاتلین

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

جاوا

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

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

میلی‌ثانیه سپری شده است کسر سپری‌شده/کسر درون‌یابی‌شده (خطی) کسر درون‌یابی شده (شتاب‌گیری/کاهش سرعت)
0 0 0
۲۰۰ .2 .1
۴۰۰ .4 .۳۴۵
۶۰۰ .6 .654
۸۰۰ .8 .9
۱۰۰۰ ۱ ۱

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

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

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

برای نمونه‌سازی یک شیء Keyframe ، باید از یکی از متدهای factory، ofInt() ، ofFloat() یا ofObject() برای به دست آوردن نوع مناسب Keyframe استفاده کنید. سپس متد factory 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 انجام می‌شد، زیرا خود View هیچ ویژگی برای دستکاری نداشت. این امر منجر به انیمیشن شدن View می‌شد، اما هیچ تغییری در خود شیء View ایجاد نمی‌کرد. این امر منجر به رفتاری مانند وجود یک شیء در مکان اصلی خود می‌شد، حتی اگر در مکان دیگری روی صفحه نمایش ترسیم شده باشد. در اندروید ۳.۰، ویژگی‌های جدید و متدهای getter و setter مربوطه برای رفع این نقص اضافه شدند.

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

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

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

کاتلین

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

جاوا

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

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

متحرک‌سازی با استفاده از ViewPropertyAnimator

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

چندین شیء 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();

یک انیماتور شیء

کاتلین

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();

انیمیشن ساز ViewProperty

کاتلین

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

جاوا

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

برای اطلاعات بیشتر در مورد ViewPropertyAnimator ، به پست وبلاگ مربوطه در Android Developers مراجعه کنید.

اعلان انیمیشن‌ها در XML

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

برای تشخیص فایل‌های انیمیشنی که از APIهای انیمیشن ویژگی جدید استفاده می‌کنند از آن‌هایی که از چارچوب انیمیشن نمای قدیمی استفاده می‌کنند، از اندروید ۳.۱ به بعد، باید فایل‌های 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 قبلی در کد خود، باید شیء را inflate کنید، یک 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 برای تعریف انیمیشن‌های ویژگی، به منابع انیمیشن مراجعه کنید.

تأثیرات بالقوه بر عملکرد رابط کاربری

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

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