سیستم انیمیشن ویژگی، چارچوبی قوی است که به شما امکان میدهد تقریباً هر چیزی را متحرک کنید. میتوانید یک انیمیشن تعریف کنید تا هر ویژگی شیء را در طول زمان تغییر دهد، صرف نظر از اینکه روی صفحه نمایش داده شود یا خیر. یک انیمیشن ویژگی، مقدار یک ویژگی (یک فیلد در یک شیء) را در طول مدت زمان مشخصی تغییر میدهد. برای متحرکسازی چیزی، ویژگی شیء مورد نظر برای متحرکسازی را مشخص میکنید، مانند موقعیت شیء روی صفحه، مدت زمانی که میخواهید آن را متحرک کنید و مقادیری که میخواهید بین آنها متحرکسازی کنید.
سیستم انیمیشن ویژگی به شما امکان میدهد ویژگیهای زیر را برای یک انیمیشن تعریف کنید:
- مدت زمان: میتوانید مدت زمان یک انیمیشن را مشخص کنید. طول پیشفرض ۳۰۰ میلیثانیه است.
- درونیابی زمان: میتوانید مشخص کنید که مقادیر مربوط به ویژگی چگونه به عنوان تابعی از زمان سپریشدهی فعلی انیمیشن محاسبه شوند.
- تعداد تکرار و رفتار: میتوانید مشخص کنید که آیا یک انیمیشن وقتی به پایان مدت زمان خود میرسد تکرار شود یا خیر و چند بار تکرار شود. همچنین میتوانید مشخص کنید که آیا میخواهید انیمیشن به صورت معکوس پخش شود یا خیر. تنظیم آن روی معکوس، انیمیشن را به طور مکرر به جلو و سپس به عقب پخش میکند، تا زمانی که به تعداد تکرارها برسد.
- مجموعههای انیماتور: میتوانید انیمیشنها را در مجموعههای منطقی گروهبندی کنید که با هم یا به صورت متوالی یا پس از تأخیرهای مشخص پخش میشوند.
- تأخیر در بهروزرسانی فریم: میتوانید مشخص کنید که فریمهای انیمیشن شما هر چند وقت یکبار بهروزرسانی شوند. پیشفرض روی بهروزرسانی هر ۱۰ میلیثانیه تنظیم شده است، اما سرعت بهروزرسانی فریمها توسط برنامه شما در نهایت به میزان شلوغی کلی سیستم و سرعت سرویسدهی سیستم به تایمر مربوطه بستگی دارد.
برای دیدن یک مثال کامل از انیمیشن ویژگی، به کلاس 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 زیر را به روش زیر پخش میکند:
-
bounceAnimبازی میکند. -
squashAnim1،squashAnim2،stretchAnim1وstretchAnim2را همزمان اجرا میکند. -
bounceBackAnimرا پخش میکند. -
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.AnimatorUpdateListeneronAnimationUpdate()- در هر فریم از انیمیشن فراخوانی میشود. برای استفاده از مقادیر محاسبهشده تولید شده توسط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 زیر پشتیبانی میکنند:
-
ValueAnimator-<animator> -
ObjectAnimator-<objectAnimator> -
AnimatorSet-<set>
برای یافتن ویژگیهایی که میتوانید در اعلان 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 مراجعه کنید.
