الصور المتحركة لمربّعات

يمكنك إضافة تأثيرات حركية إلى المربّعات بعدة طرق مختلفة، بما في ذلك ما يلي:

إظهار انتقال ساحق

لعرض مسح سلس من قيمة إلى أخرى، يمكنك تفعيل الصور المتحركة في البداية لأحد العناصر، كما هو موضّح في مقتطف الرمز التالي:

Kotlin

private val defaultValue = 0f
private var startValue = 15f
private var endValue = 105f
private val animationDurationInMillis = 2000f // 2 seconds

override fun onTileRequest(requestParams: TileRequest) =
    Futures.immediateFuture(
        // Add timeline and layout containers. CircularProgressIndicator is an
        // inner element of those containers.
        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()
        // Finish building all elements that contain CircularProgressIndicator.
    )

Java

private float defaultValue = 0f;
private float startValue = 15f;
private float endValue = 105f;
private float animationDurationInMillis = 2000f; // 2 seconds

@Override
protected ListenableFuture<Tile> onTileRequest(
       @NonNull TileRequest requestParams
) {
    return Futures.immediateFuture(
        // Add timeline and layout containers. CircularProgressIndicator is an
        // inner element of those containers.
        new CircularProgressIndicator.Builder()
            .setProgress(
                new 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,
                            new AnimationSpec.Builder()
                                .setAnimationParameters(
                                    new AnimationParameters.Builder()
                                        .setDurationMillis(animationDurationInMillis)
                                        .build()
                                ).build()
                        )
                    ).build()
            ).build()
        // Finish building all elements that contain CircularProgressIndicator.
    );
}

ضبط اتجاه القوس

إذا كان مربّعك يحتوي على قوس، قد لا تريد أن ينمو خط القوس أو النص دائمًا في الاتجاه التلقائي للنص للغة التي اختارها المستخدم. لتحديد اتجاه نمو القوس، استخدِم واجهات برمجة تطبيقات ArcDirection:

Kotlin

@OptIn(ProtoLayoutExperimental::class)
public override fun onTileRequest(
        requestParams: RequestBuilders.TileRequest
): ListenableFuture<Tile> {
    return Futures.immediateFuture(Tile.Builder()
        .setResourcesVersion(RESOURCES_VERSION)
        .setTileTimeline(Timeline.fromLayoutElement(
            EdgeContentLayout.Builder(deviceParameters)
                .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()
    )
}

Java

@OptIn(markerClass = ProtoLayoutExperimental.class)
@NonNull
@Override
protected ListenableFuture<Tile> onTileRequest(
        @NonNull RequestBuilders.TileRequest requestParams
) {
    return Futures.immediateFuture(new Tile.Builder()
        .setResourcesVersion(RESOURCES_VERSION)
        .setTileTimeline(Timeline.fromLayoutElement(
            new EdgeContentLayout.Builder(deviceParameters)
                .setEdgeContent(
                    new Arc.Builder()
                        // Arc should always grow clockwise.
                        .setArcDirection(LayoutElementBuilders.ARC_DIRECTION_CLOCKWISE)
                        .addContent(
                            new 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() على التوالي في طريقتَي إعداد الانتقال.

Kotlin

@OptIn(ProtoLayoutExperimental::class)
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(
                    ModifiersBuilders.Modifiers.Builder()
                        .setContentUpdateAnimation(AnimatedVisibility.Builder()
                            .setEnterTransition(
                                    DefaultContentTransitions.fadeIn())
                            .setExitTransition(
                                    DefaultContentTransitions.fadeOut()
                            ).build())
                ).build())
        ).build()
    )
}

Java

@OptIn(markerClass = ProtoLayoutExperimental.class)
@NonNull
@Override
protected ListenableFuture<Tile> onTileRequest(
        @NonNull RequestBuilders.TileRequest requestParams
) {
    // Assumes that you've defined a custom helper method called
    // getTileTextToShow().
    String tileText = getTileTextToShow();

    return Futures.immediateFuture(new Tile.Builder()
        .setResourcesVersion(RESOURCES_VERSION)
        .setTileTimeline(Timeline.fromLayoutElement(
            new Text.Builder(this, tileText)
                .setModifiers(
                    new ModifiersBuilders.Modifiers.Builder()
                        .setContentUpdateAnimation(new AnimatedVisibility.Builder()
                            .setEnterTransition(
                                    DefaultContentTransitions.fadeIn())
                            .setExitTransition(
                                    DefaultContentTransitions.fadeOut())
                            .build())
                .build()))
        .build()
    );
}

انتقالات الشرائح

يوضح مقتطف الرمز الآخر هذا كيفية إجراء انتقالات من خلال الانتقال إلى تسلسل هرمي باستخدام طرق المساعدة من DefaultContentTransitions. يمكنك أيضًا تحديد كائنين SlideInTransition وSlideOutTransition مخصّصين من خلال استدعاء setSlideIn() وsetSlideOut()، على التوالي، في طريقتَي "ضبط الانتقال".

Kotlin

@OptIn(ProtoLayoutExperimental::class)
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(
                                    SLIDE_DIRECTION_LEFT_TO_RIGHT)
                            ).setExitTransition(
                                DefaultContentTransitions.slideOut(
                                    SLIDE_DIRECTION_LEFT_TO_RIGHT)
                            ).build()
                        ).build()
                ).build()
        )).build()
    )
}

Java

@OptIn(markerClass = ProtoLayoutExperimental.class)
@NonNull
@Override
protected ListenableFuture<Tile> onTileRequest(
        @NonNull RequestBuilders.TileRequest requestParams
) {
    // Assumes that you've defined a custom helper method called
    // getTileTextToShow().
    String tileText = getTileTextToShow();
    return Futures.immediateFuture(Tile.Builder()
        .setResourcesVersion(RESOURCES_VERSION)
        .setTileTimeline(Timeline.fromLayoutElement(
            new Text.Builder(this, tileText)
                .setModifiers(
                    new Modifiers.Builder()
                        .setContentUpdateAnimation(
                            new AnimatedVisibility.Builder()
                                .setEnterTransition(
                                    DefaultContentTransitions.slideIn(
                                        SLIDE_DIRECTION_LEFT_TO_RIGHT))
                                .setExitTransition(
                                    DefaultContentTransitions.slideOut(
                                        SLIDE_DIRECTION_LEFT_TO_RIGHT))
                                .build())
                        .build())
                .build()))
        .build()
    );
}

عرض تحويل

للفت الانتباه إلى عنصر أو منطقة معيّنة في مربّع، يمكنك تطبيق عدة أنواع من عمليات التحويل عليه، بما في ذلك: التدوير والتحجيم والترجمة.

تقبل العديد من قيم النقاط العائمة المرتبطة بعمليات التحويل التعبيرات الديناميكية، ما يتيح لك إضافة تأثيرات حركية إلى هذه عمليات التحويل.

تدوير

لإجراء دوران في اتجاه عقارب الساعة حول نقطة محورية قابلة للتخصيص، استخدِم رمزًا برمجيًا مشابهًا لما يلي:

Kotlin

// Last line in your onTileRequest() method implementation.
return Futures.immediateFuture(Tile.Builder()
    .setResourcesVersion(RESOURCES_VERSION)
    .setTileTimeline(Timeline.fromLayoutElement(
        Text.Builder(this, someTileText)
            .setModifiers(
                    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(50))
                        .setPivotY(dp(100))
                        // Rotate the element 45 degrees clockwise.
                        .setRotation(
                            degrees(45f)
                        ).build()
            ).build())
    ).build()
)

Java

// Last line in your onTileRequest() method implementation.
return Futres.immediateFuture(new Tile.Builder()
    .setResourcesVersion(RESOURCES_VERSION)
    .setTileTimeline(Timeline.fromLayoutElement(
        new Text.Builder(this, someTileText)
            .setModifiers(
                    new 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(50))
                        .setPivotY(dp(100))
                        // Rotate the element 45 degrees clockwise.
                        .setRotation(
                            degrees(45f))
                        .build())
            .build()))
    .build()
);

التوسعة

لزيادة حجم عنصر أو تقليصه من خلال عوامل التحجيم الأفقية والرأسية، استخدِم تعليمات برمجية مشابهة لما يلي:

Kotlin

// Last line in your onTileRequest() method implementation.
return Futures.immediateFuture(Tile.Builder()
    .setResourcesVersion(RESOURCES_VERSION)
    .setTileTimeline(Timeline.fromLayoutElement(
        Text.Builder(this, someTileText)
            .setModifiers(
                    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(50))
                        .setPivotY(dp(100))
                        // Shrink the element by a scale factor
                        // of 0.5 horizontally and 0.75 vertically.
                        .setScaleX(TypeBuilders.FloatProp.Builder(0.5f)
                                .build())
                        .setScaleY(TypeBuilders.FloatProp.Builder(0.75f)
                                .build()
                        ).build()
            ).build())
    ).build()
)

Java

// Last line in your onTileRequest() method implementation.
return Futres.immediateFuture(new Tile.Builder()
    .setResourcesVersion(RESOURCES_VERSION)
    .setTileTimeline(Timeline.fromLayoutElement(
        new Text.Builder(this, someTileText)
            .setModifiers(
                    new 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(50))
                        .setPivotY(dp(100))
                        // Shrink the element by a scale factor
                        // of 0.5 horizontally and 0.75 vertically.
                        .setScaleX(new TypeBuilders.FloatProp.Builder(0.5f)
                                .build())
                        .setScaleY(new TypeBuilders.FloatProp.Builder(0.75f)
                                .build())
                        .build())
            .build()))
    .build()
);

ترجمة الأشكال الهندسية

لنقل عنصر بعدد معيّن من وحدات بكسل الكثافة (dp) على الشاشة أفقيًا أو عموديًا، استخدِم رمزًا برمجيًا مشابهًا لما يلي:

Kotlin

// Last line in your onTileRequest() method implementation.
return Futures.immediateFuture(Tile.Builder()
    .setResourcesVersion(RESOURCES_VERSION)
    .setTileTimeline(Timeline.fromLayoutElement(
        Text.Builder(this, someTileText)
            .setModifiers(
                    ModifiersBuilders.Transformation.Builder()
                        // Translate (move) the element 60 dp to the right
                        // and 80 dp down.
                        .setTranslationX(dp(60))
                        .setTranslationY(dp(80))
                        ).build()
            ).build())
    ).build()
)

Java

// Last line in your onTileRequest() method implementation.
return Futres.immediateFuture(new Tile.Builder()
    .setResourcesVersion(RESOURCES_VERSION)
    .setTileTimeline(Timeline.fromLayoutElement(
        new Text.Builder(this, someTileText)
            .setModifiers(
                    new ModifiersBuilders.Transformation.Builder()
                        // Translate (move) the element 60 dp to the right
                        // and 80 dp down.
                        .setTranslationX(dp(60))
                        .setTranslationY(dp(80))
                        .build())
            .build()))
    .build()
);

عدم عرض المعلومات المهمة في منتصف الصورة المتحركة

هناك العديد من الحالات التي يتم فيها إيقاف الصور المتحركة:

  • قد يؤدّي عرض مربّع النظام إلى إيقاف الصور المتحركة في جميع المربّعات.
  • يمكن للمربّع تحريك 4 عناصر فقط في كل مرة. إذا حاولت رسم أكثر من 4 عناصر في نفس الوقت، فلن تعرض جميعها رسومًا متحركة.

في حالة إيقاف الرسوم المتحركة، تكون العناصر ثابتة وتعرض القيمة النهائية للصورة المتحركة. لهذا السبب، لا تعتمد على سلوك الرسوم المتحركة، مثل مدتها، لعرض معلومات مهمة.