عرض التحديثات الديناميكية في المربّعات

بدءًا من الإصدار 1.2 من "المربّعات"، يمكنك بثّ آخر بيانات النظام الأساسي باستخدام تعابير ديناميكية. يمكنك بعد ذلك ربط هذه التحديثات بالصور المتحركة في مربّعاتك. يتلقّى تطبيقك تحديثات لهذه القيمة كل ثانية.

باستخدام التعابير الديناميكية، لن تحتاج إلى إعادة تحميل المربّع بالكامل عند تغيير محتواه. لإنشاء تجربة أكثر جاذبية في مربّعاتك، يمكنك تحريك هذه الكائنات الديناميكية.

ربط التعابير الديناميكية بمصادر البيانات

تحتوي مساحتا الاسمَين androidx.wear.protolayout وandroidx.wear.protolayout.material على العديد من الفئات التي تقبل حقولها تعابير ديناميكية. في ما يلي بعض الأمثلة:

لاستخدام تعبير ديناميكي كقيمة محتمَلة لعنصر في مربّعك، استخدِم نوع السمة الديناميكية *Prop المقابلة للعنصر وأدخِل مصدر البيانات إلى طريقة setDynamicValue() لفئة أداة إنشاء نوع السمة الديناميكية.

تتيح "المربّعات" أنواع السمات الديناميكية التالية:

  • بالنسبة إلى الأبعاد الخطية، التي يتم قياسها بوحدات بكسل مستقلة عن كثافة العرض، استخدِم DimensionBuilders.DpProp.
  • بالنسبة إلى الأبعاد الزاوية، التي يتم قياسها بالدرجات، استخدِم DimensionBuilders.DegreesProp.
  • بالنسبة إلى قيم السلسلة، استخدِم TypeBuilders.StringProp.
  • بالنسبة إلى قيم الألوان، استخدِم ColorBuilders.ColorProp.
  • بالنسبة إلى القيم ذات الفاصلة العائمة، استخدِم TypeBuilders.FloatProp.

عند استخدام تعبير ديناميكي يؤثر في الأبعاد المادية (أي قيمة في المربّع باستثناء اللون)، عليك أيضًا تحديد مجموعة من القيود ذات الصلة، مثل تنسيق سلسلة. تسمح هذه القيود لأداة العرض في النظام بتحديد الحد الأقصى للمساحة التي يمكن أن تشغلها القيمة داخل مربّعك. عادةً ما تحدّد هذه القيود على مستوى العنصر، وليس على مستوى التعبير الديناميكي، من خلال استدعاء طريقة تبدأ بـ setLayoutConstraintsForDynamic*.

يعرض مقتطف الرمز التالي كيفية عرض تحديثات معدّل نبضات القلب باستخدام 3 أرقام، مع قيمة احتياطية هي --:

override fun onTileRequest(requestParams: RequestBuilders.TileRequest) =
    Futures.immediateFuture(
        Tile.Builder()
            .setResourcesVersion(RESOURCES_VERSION)
            .setFreshnessIntervalMillis(60 * 60 * 1000) // 60 minutes
            .setTileTimeline(
                Timeline.fromLayoutElement(
                    Text.Builder(
                        this,
                        TypeBuilders.StringProp.Builder("--")
                            .setDynamicValue(
                                PlatformHealthSources.heartRateBpm()
                                    .format()
                                    .concat(DynamicBuilders.DynamicString.constant(" bpm"))
                            )
                            .build(),
                        TypeBuilders.StringLayoutConstraint.Builder("000").build(),
                    )
                        .build()
                )
            )
            .build()
    )

استخدام عدد صغير من التعابير ضمن مربّع واحد

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

دمج البيانات الديناميكية في كائن حالة

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

لاستخدام معلومات الحالة في مربّعاتك، أكمل الخطوات التالية:

  1. أنشئ مجموعة من المفاتيح التي تمثّل القيم المختلفة لحالة مربّعك. ينشئ هذا المثال مفاتيح لكمية المياه التي تم تناولها وملاحظة qqq:

    companion object {
        val KEY_WATER_INTAKE = intAppDataKey("key_water_intake")
        val KEY_NOTE = stringAppDataKey("key_note")
    }

  2. في عملية تنفيذ onTileRequest()، استدعِ setState() وأنشئ عمليات الربط الأولية من كل مفتاح إلى قيمة بيانات ديناميكية معيّنة:

    override fun onTileRequest(
        requestParams: RequestBuilders.TileRequest
    ): ListenableFuture<Tile?> {
        // If the tile hasn't had any state set yet, use the default values
        val state =
            if (requestParams.currentState.keyToValueMapping.isNotEmpty())
                requestParams.currentState
            else
                StateBuilders.State.Builder()
                    .setStateMap(
                        dynamicDataMapOf(
                            KEY_WATER_INTAKE mapTo 200,
                            KEY_NOTE mapTo "Good"
                        )
                    )
                    .build()
    
        return Futures.immediateFuture(
            Tile.Builder()
                // Set resources, timeline, and other tile properties.
                .setState(state)
                .build()
        )
    }

  3. عند إنشاء التنسيق، استخدِم كائنًا من نوع Dynamic* في المكان الذي تريد عرض هذه البيانات من الحالة فيه. يمكنك أيضًا استدعاء animate() لعرض صورة متحركة من القيمة السابقة إلى القيمة الحالية:

    val waterIntakeValue =
        DynamicBuilders.DynamicInt32.from(KEY_WATER_INTAKE)

  4. عند الحاجة، يمكنك أيضًا تعديل الحالة باستخدام قيم جديدة. يمكن أن يكون ذلك جزءًا من LoadAction للمربّع.

    في هذا المثال، يتم تعديل قيمة كمية المياه التي تم تناولها إلى 400:

    val loadAction =
        loadAction(
            dynamicDataMapOf(
                KEY_WATER_INTAKE mapTo 400,
                KEY_NOTE mapTo "Outstanding"
            )
        )