تتيح المربّعات عدة طرق مختلفة للرسوم المتحركة، بما في ذلك ما يلي:
- انتقالات المسح باستخدام الرسوم المتحركة بينية
- حركات التلاشي والانزلاق السلس للدخول إلى المربّع والخروج منه
- صور Lottie المتحركة
عرض انتقال سريع
لعرض انتقال سلس من قيمة إلى أخرى، يمكنك تفعيل الرسوم المتحركة بين القيمتين لعنصر، كما هو موضّح في مقتطف الرمز التالي:
private var startValue = 15f private var endValue = 105f private val animationDurationInMillis = 2000L // 2 seconds override fun onTileRequest(requestParams: RequestBuilders.TileRequest): ListenableFuture<Tile> { val circularProgressIndicator = CircularProgressIndicator.Builder() .setProgress( FloatProp.Builder(/* static value */ 0.25f) .setDynamicValue( // Or you can use some other dynamic object, for example // from the platform and then at the end of expression // add animate(). DynamicFloat.animate( startValue, endValue, AnimationSpec.Builder() .setAnimationParameters( AnimationParameters.Builder() .setDurationMillis(animationDurationInMillis) .build() ) .build(), ) ) .build() ) .build() return Futures.immediateFuture( Tile.Builder() .setResourcesVersion(RESOURCES_VERSION) .setTileTimeline(Timeline.fromLayoutElement(circularProgressIndicator)) .build() ) }
ضبط اتجاه القوس
إذا كان المربّع يتضمّن قوسًا، قد لا تريد أن يزداد حجم خط القوس أو النص دائمًا في اتجاه النص التلقائي للغة التي اختارها المستخدم. لتحديد اتجاه نمو القوس، استخدِم واجهات برمجة التطبيقات ArcDirection
:
public override fun onTileRequest( requestParams: RequestBuilders.TileRequest ): ListenableFuture<Tile> { return Futures.immediateFuture( Tile.Builder() .setResourcesVersion(RESOURCES_VERSION) .setTileTimeline( Timeline.fromLayoutElement( EdgeContentLayout.Builder(deviceParameters) .setResponsiveContentInsetEnabled(true) .setEdgeContent( Arc.Builder() // Arc should always grow clockwise. .setArcDirection(LayoutElementBuilders.ARC_DIRECTION_CLOCKWISE) .addContent( ArcLine.Builder() // Set color, length, thickness, and more. // Arc should always grow clockwise. .setArcDirection( LayoutElementBuilders.ARC_DIRECTION_CLOCKWISE ) .build() ) .build() ) .build() ) ) .build() ) }
عرض انتقال سلس أو تمرير
للإشارة بشكل أكثر وضوحًا إلى أنّ عنصرًا يظهر أو يختفي في مربّع، أو لعرض تغيير تدريجي في قيمة المربّع بشكل أكثر دقة، استخدِم تأثيرات التلاشي والانزلاق في الرسوم المتحركة للمربّع.
إذا كان تصميم المربّعات يتضمّن عنصرًا تتغيّر قيمته، يعرض المربّع حركة الخروج الخاصة بالعنصر، ثم يعدّل التصميم ويعرض حركة الدخول الخاصة بالعنصر.
الانتقالات بين المشاهد باستخدام تأثير التلاشي
يوضّح مقتطف الرمز البرمجي التالي كيفية تنفيذ انتقالات التلاشي والظهور
باستخدام طرق المساعد من DefaultContentTransitions
. لتحديد الكائنَين المخصّصَين FadeInTransition
وFadeOutTransition
، استدعِ الدالتَين setFadeIn()
وsetFadeOut()
على التوالي في دوال الضبط الخاصة بالانتقال.
public override fun onTileRequest( requestParams: RequestBuilders.TileRequest ): ListenableFuture<Tile> { // Assumes that you've defined a custom helper method called // getTileTextToShow(). val tileText = getTileTextToShow() return Futures.immediateFuture( Tile.Builder() .setResourcesVersion(RESOURCES_VERSION) .setTileTimeline( Timeline.fromLayoutElement( Text.Builder(this, tileText) .setModifiers( Modifiers.Builder() .setContentUpdateAnimation( AnimatedVisibility.Builder() .setEnterTransition(DefaultContentTransitions.fadeIn()) .setExitTransition(DefaultContentTransitions.fadeOut()) .build() ) .build() ) .build() ) ) .build() ) }
انتقالات الشرائح
يوضّح مقتطف الرمز الآخر هذا كيفية تنفيذ عمليات الانتقال من نوعَي "التمرير للداخل" و"التمرير للخارج" باستخدام طرق المساعد من DefaultContentTransitions
. يمكنك أيضًا تحديد عناصر SlideInTransition
وSlideOutTransition
مخصّصة من خلال استدعاء setSlideIn()
وsetSlideOut()
على التوالي في طرق ضبط الانتقال.
public override fun onTileRequest( requestParams: RequestBuilders.TileRequest ): ListenableFuture<Tile> { // Assumes that you've defined a custom helper method called // getTileTextToShow(). val tileText = getTileTextToShow() return Futures.immediateFuture( Tile.Builder() .setResourcesVersion(RESOURCES_VERSION) .setTileTimeline( Timeline.fromLayoutElement( Text.Builder(this, tileText) .setModifiers( Modifiers.Builder() .setContentUpdateAnimation( AnimatedVisibility.Builder() .setEnterTransition( DefaultContentTransitions.slideIn( ModifiersBuilders.SLIDE_DIRECTION_LEFT_TO_RIGHT ) ) .setExitTransition( DefaultContentTransitions.slideOut( ModifiersBuilders.SLIDE_DIRECTION_LEFT_TO_RIGHT ) ) .build() ) .build() ) .build() ) ) .build() ) }
عرض عملية تحويل
للفت الانتباه إلى عنصر أو مساحة معيّنة في لوحة، يمكنك تطبيق عدة أنواع من عمليات التحويل عليها، بما في ذلك التدوير والتوسيع والترجمة.
تقبل العديد من قيم الفاصلة العائمة المرتبطة بالتحويلات تعبيرات ديناميكية، ما يتيح لك تحريك هذه التحويلات.
الدوران
لتنفيذ دوران في اتجاه عقارب الساعة حول نقطة محورية قابلة للتخصيص، استخدِم رمزًا مشابهًا لما يلي:
return Futures.immediateFuture( Tile.Builder() .setResourcesVersion(RESOURCES_VERSION) .setTileTimeline( Timeline.fromLayoutElement( Text.Builder(this, someTileText) .setModifiers( Modifiers.Builder() .setTransformation( ModifiersBuilders.Transformation.Builder() // Set the pivot point 50 dp from the left edge // and 100 dp from the top edge of the screen. .setPivotX(dp(50f)) .setPivotY(dp(100f)) // Rotate the element 45 degrees clockwise. .setRotation(degrees(45f)) .build() ) .build() ) .build() ) ) .build() )
التوسّع
لتكبير عنصر أو تصغيره باستخدام عوامل القياس الأفقية والعمودية، استخدِم رمزًا مشابهًا لما يلي:
return Futures.immediateFuture( Tile.Builder() .setResourcesVersion(RESOURCES_VERSION) .setTileTimeline( Timeline.fromLayoutElement( Text.Builder(this, someTileText) .setModifiers( Modifiers.Builder() .setTransformation( ModifiersBuilders.Transformation.Builder() // Set the pivot point 50 dp from the left edge // and 100 dp from the top edge of the screen. .setPivotX(dp(50f)) .setPivotY(dp(100f)) // Shrink the element by a scale factor // of 0.5 horizontally and 0.75 vertically. .setScaleX(FloatProp.Builder(0.5f).build()) .setScaleY(FloatProp.Builder(0.75f).build()) .build() ) .build() ) .build() ) ) .build() )
الترجمة الهندسية
لنقل عنصر بعدد محدّد من وحدات البكسل الكثيفة (dp) على الشاشة أفقيًا أو عموديًا، استخدِم رمزًا مشابهًا لما يلي:
return Futures.immediateFuture( Tile.Builder() .setResourcesVersion(RESOURCES_VERSION) .setTileTimeline( Timeline.fromLayoutElement( Text.Builder(this, someTileText) .setModifiers( Modifiers.Builder() .setTransformation( ModifiersBuilders.Transformation.Builder() // Translate (move) the element 60 dp to the right // and 80 dp down. .setTranslationX(dp(60f)) .setTranslationY(dp(80f)) .build() ) .build() ) .build() ) ) .build() )
صور Lottie المتحركة
تتيح المربّعات تشغيل صور متحركة بتنسيق Lottie باستخدام بنية مشابهة لبنية الصور:
class LottieAnimation : TileService() { val lottieResourceId = "lottie_animation" override fun onTileRequest(requestParams: RequestBuilders.TileRequest): ListenableFuture<Tile> { val layout = LayoutElementBuilders.Image.Builder() .setWidth(dp(150f)) .setHeight(dp(150f)) .setResourceId(lottieResourceId) .build() return Futures.immediateFuture( Tile.Builder() .setResourcesVersion(RESOURCES_VERSION) .setTileTimeline(Timeline.fromLayoutElement(layout)) .build() ) } override fun onTileResourcesRequest( requestParams: ResourcesRequest ): ListenableFuture<Resources> { val lottieImage = ResourceBuilders.ImageResource.Builder() .setAndroidLottieResourceByResId( ResourceBuilders.AndroidLottieResourceByResId.Builder(R.raw.lottie) .setStartTrigger(createOnVisibleTrigger()) .build() ) .build() return Futures.immediateFuture( Resources.Builder() .setVersion(requestParams.version) .addIdToImageMapping(lottieResourceId, lottieImage) .build() ) } }
في ما يلي بعض النقاط التي يجب أخذها في الاعتبار:
- لا تتوافق سوى مجموعة فرعية من ملفات Lottie. يمكنك التحقّق من التوافق باستخدام إحدى أدوات التحقّق التالية:
- أداة التحقّق من الصحة على الإنترنت: https://skottie.skia.org/ في قسم "تقرير التوافق"، يجب أن يجتاز الملف اختبارات "أخطاء المواصفات" و"تحذيرات المواصفات" (مع تجاهل "السمات الشائعة") و"أخطاء ملف الطاقة المنخفضة".
- مكتبة للتحقّق من صحة Rust: https://github.com/google/lottie-tools
- تتوافق أداة عرض اللوحات مع تشغيل ملفات Lottie إذا كان الإصدار الرئيسي
1
أو أحدث والإصدار الثانوي500
أو أحدث. إذا لم تكن الحركة المتوفرة متوافقة، لن تظهر الحركة، ولكن سيتم عرض بقية المربّع على النحو المتوقّع. إذا لزم الأمر، يمكنك توفير خيار احتياطي، مثل صورة ثابتة.
عدم عرض المعلومات المهمة في منتصف صورة متحركة
هناك عدة حالات يتم فيها إيقاف الصور المتحركة:
- قد يؤدي عرض مربّعات النظام إلى إيقاف الصور المتحركة لجميع المربّعات.
- يمكن أن تحرّك اللوحة 4 عناصر فقط في كل مرة. إذا حاولت تحريك أكثر من 4 عناصر في الوقت نفسه، لن تظهر حركة لبعضها.
في حال إيقاف رسم متحرك، تكون العناصر ثابتة وتعرض قيمة نهاية الرسم المتحرك. لهذا السبب، لا تعتمد على سلوك الرسوم المتحركة، مثل مدتها، لعرض معلومات مهمة.