توفير تنسيقات مرنة للتطبيقات المصغّرة

تجربة طريقة Compose
‫Jetpack Compose هي مجموعة أدوات واجهة المستخدِم المقترَحة لنظام Android. تعرَّف على كيفية إنشاء التطبيقات المصغّرة باستخدام واجهات برمجة التطبيقات بنمط Compose.

تصف هذه الصفحة التحسينات التي تم إدخالها على تغيير حجم التطبيقات المصغّرة والمرونة الأكبر التي تم توفيرها في Android 12 (المستوى 31 من واجهة برمجة التطبيقات). وتوضّح أيضًا كيفية تحديد حجم التطبيق المصغّر .

استخدام واجهات برمجة التطبيقات المحسّنة لأحجام التطبيقات المصغّرة وتنسيقاتها

بدءًا من Android 12 (المستوى 31 من واجهة برمجة التطبيقات)، يمكنك توفير سمات حجم أكثر دقة وتنسيقات مرنة من خلال تنفيذ ما يلي، كما هو موضّح في الأقسام التالية:

  1. تحديد قيود إضافية لتغيير حجم التطبيق المصغّر

  2. توفير تنسيقات سريعة الاستجابة أو تنسيقات دقيقة.

في الإصدارات السابقة من Android، من الممكن الحصول على نطاقات حجم التطبيق المصغّر باستخدام الإضافات OPTION_APPWIDGET_MIN_WIDTH وOPTION_APPWIDGET_MIN_HEIGHT وOPTION_APPWIDGET_MAX_WIDTH وOPTION_APPWIDGET_MAX_HEIGHT ثم تقدير حجم التطبيق المصغّر، ولكن هذه الطريقة لا تعمل في جميع الحالات. بالنسبة إلى التطبيقات المصغّرة التي تستهدف Android 12 أو الإصدارات الأحدث، ننصح بتوفير تنسيقات سريعة الاستجابة أو دقيقة.

تحديد قيود إضافية لتغيير حجم التطبيق المصغّر

يضيف Android 12 واجهات برمجة تطبيقات تتيح لك ضمان تغيير حجم التطبيق المصغّر بشكل أكثر موثوقية على الأجهزة المختلفة التي تتضمّن أحجام شاشة متفاوتة.

بالإضافة إلى سمات minWidth و minHeight و minResizeWidth و وminResizeHeight الحالية، استخدِم سمات appwidget-provider الجديدة التالية:

  • targetCellWidth وtargetCellHeight: تحدّدان الحجم المستهدَف للتطبيق المصغّر من حيث خلايا شبكة مشغّل التطبيقات. إذا تم تحديد هاتَين السمتَين، يتم استخدامهما بدلاً من minWidth أو minHeight.

  • maxResizeWidth وmaxResizeHeight: تحدّدان الحد الأقصى للحجم الذي يسمح مشغّل التطبيقات للمستخدم بتغيير حجم التطبيق المصغّر إليه.

يوضّح ملف XML التالي كيفية استخدام سمات تغيير الحجم.

<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
  android:targetCellWidth="3"
  android:targetCellHeight="2"
  android:maxResizeWidth="250dp"
  android:maxResizeHeight="110dp">
</appwidget-provider>

توفير تنسيقات سريعة الاستجابة

إذا كان التنسيق بحاجة إلى التغيير استنادًا إلى حجم التطبيق المصغّر، ننصحك بإنشاء مجموعة صغيرة من التنسيقات، يكون كل منها صالحًا لنطاق من الأحجام. إذا لم يكن ذلك ممكنًا، هناك خيار آخر وهو توفير تنسيقات استنادًا إلى الحجم الدقيق للتطبيق المصغّر في وقت التشغيل، كما هو موضّح في هذه الصفحة.

تتيح هذه الميزة تغيير الحجم بسلاسة وتحسين حالة النظام بشكل عام، لأنّه ليس على النظام تنبيه التطبيق في كل مرة يعرض فيها التطبيق المصغّر بحجم مختلف.

يوضّح مثال الرمز البرمجي التالي كيفية توفير قائمة بالتنسيقات.

override fun onUpdate(
    /* ... */
) {
    val smallView = RemoteViews(
        /* ... */
    )
    val tallView = RemoteViews(
        /* ... */
    )
    val wideView = RemoteViews(
        /* ... */
    )

    val viewMapping: Map<SizeF, RemoteViews> = mapOf(
        SizeF(150f, 100f) to smallView,
        SizeF(150f, 200f) to tallView,
        SizeF(215f, 100f) to wideView
    )
    val remoteViews = RemoteViews(viewMapping)

    appWidgetManager.updateAppWidget(id, remoteViews)
}

لنفترض أنّ التطبيق المصغّر يتضمّن السمات التالية:

<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
    android:minResizeWidth="160dp"
    android:minResizeHeight="110dp"
    android:maxResizeWidth="250dp"
    android:maxResizeHeight="200dp">
</appwidget-provider>

يعني مقتطف الرمز البرمجي السابق ما يلي:

  • تتراوح أحجام smallView بين ‎160dp (minResizeWidth) × ‎110dp (minResizeHeight) و‎160dp × ‎199dp (نقطة القطع التالية - ‎1dp).
  • تتراوح أحجام tallView بين ‎160dp × ‎200dp و‎214dp (نقطة القطع التالية - ‎1) × ‎200dp.
  • تتراوح أحجام wideView بين ‎215dp × ‎110dp (minResizeHeight) و‎250dp (maxResizeWidth) × ‎200dp (maxResizeHeight).

يجب أن يتوافق التطبيق المصغّر مع نطاق الحجم من minResizeWidth × minResizeHeight إلى maxResizeWidth × maxResizeHeight. ضمن هذا النطاق، يمكنك تحديد نقطة القطع للتبديل بين التنسيقات.

مثال على التنسيق المتجاوب
الشكل 1. مثال على تنسيق سريع الاستجابة

توفير تنسيقات دقيقة

إذا لم يكن من الممكن توفير مجموعة صغيرة من التنسيقات السريعة الاستجابة، يمكنك بدلاً من ذلك توفير تنسيقات مختلفة مصمّمة خصيصًا للأحجام التي يتم عرض التطبيق المصغّر بها. عادةً ما يكون هناك حجمان للهواتف (الوضع العمودي والوضع الأفقي) وأربعة أحجام للهواتف القابلة للطي.

لتنفيذ هذا الحل، على تطبيقك اتّباع الخطوات التالية:

  1. تجاوز AppWidgetProvider.onAppWidgetOptionsChanged()، الذي يتم استدعاؤه عند تغيير مجموعة الأحجام.

  2. استدعِ AppWidgetManager.getAppWidgetOptions()، الذي يعرض Bundle يحتوي على الأحجام.

  3. يمكنك الوصول إلى المفتاح AppWidgetManager.OPTION_APPWIDGET_SIZES من Bundle.

يوضّح مثال الرمز البرمجي التالي كيفية توفير تنسيقات دقيقة.

override fun onAppWidgetOptionsChanged(
    context: Context,
    appWidgetManager: AppWidgetManager,
    id: Int,
    newOptions: Bundle?
) {
    super.onAppWidgetOptionsChanged(context, appWidgetManager, id, newOptions)
    // Get the new sizes.
    val sizes = newOptions?.let {
        BundleCompat.getParcelableArrayList(
            it,
            AppWidgetManager.OPTION_APPWIDGET_SIZES,
            SizeF::class.java
        )
    }
    // Check that the list of sizes is provided by the launcher.
    if (sizes.isNullOrEmpty()) {
        return
    }
    // Map the sizes to the RemoteViews that you want.
    val remoteViews = RemoteViews(sizes.associateWith(::createRemoteViews))
    appWidgetManager.updateAppWidget(id, remoteViews)
}

// Create the RemoteViews for the given size.
private fun createRemoteViews(size: SizeF): RemoteViews {
}

تحديد حجم التطبيق المصغّر

يجب أن يحدّد كل تطبيق مصغّر targetCellWidth وtargetCellHeight للأجهزة التي تعمل بنظام Android 12 أو الإصدارات الأحدث، أو minWidth وminHeight لجميع إصدارات Android، ما يشير إلى الحد الأدنى للمساحة التي يشغلها تلقائيًا. ومع ذلك، عندما يضيف المستخدمون تطبيقًا مصغّرًا إلى شاشتهم الرئيسية، فإنّه يشغل عادةً مساحة أكبر من الحد الأدنى للعرض والارتفاع اللذين تحدّدهما.

توفّر الشاشات الرئيسية في Android للمستخدمين شبكة من المساحات المتاحة التي يمكنهم وضع التطبيقات المصغّرة والرموز عليها. يمكن أن تختلف هذه الشبكة حسب الجهاز، فعلى سبيل المثال، توفّر العديد من الهواتف شبكة 5x4، ويمكن أن توفّر الأجهزة اللوحية شبكة أكبر. عند إضافة التطبيق المصغّر، يتم توسيعه ليشغل الحد الأدنى من الخلايا، أفقيًا وعموديًا، اللازمة لاستيفاء قيود targetCellWidth وtargetCellHeight على الأجهزة التي تعمل بنظام Android 12 أو الإصدارات الأحدث، أو قيود minWidth وminHeight على الأجهزة التي تعمل بنظام Android 11 (المستوى 30 من واجهة برمجة التطبيقات) أو الإصدارات الأقدم.

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

عدد الخلايا (العرض × الارتفاع) الحجم المتاح في الوضع العمودي (dp) الحجم المتاح في الوضع الأفقي (dp)
1x1 57x102dp 127x51dp
2x1 130x102dp 269x51dp
3x1 203x102dp 412x51dp
4x1 276x102dp 554x51dp
5x1 349x102dp 697x51dp
5x2 349x220dp 697x117dp
5x3 349x337dp 697x184dp
5x4 349x455dp 697x250dp
... ... ...
n x m (73n - 16) x (118m - 16) (142n - 15) x (66m - 15)

استخدِم أحجام الخلايا في الوضع العمودي لتحديد القيم التي تقدّمها لسمات minWidth وminResizeWidth وmaxResizeWidth. وبالمثل، استخدِم أحجام الخلايا في الوضع الأفقي لتحديد القيم التي تقدّمها لسمات minHeight وminResizeHeight وmaxResizeHeight.

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

على سبيل المثال، إذا كنت تريد أن يكون عرض التطبيق المصغّر قابلاً لتغيير الحجم إلى خلية واحدة على Google Pixel 4، عليك ضبط minResizeWidth على ‎56dp على الأكثر للتأكّد من أنّ قيمة سمة minResizeWidth أصغر من ‎57dp، لأنّ عرض الخلية يبلغ ‎57dp على الأقل في الوضع العمودي. وبالمثل، إذا كنت تريد أن يكون ارتفاع التطبيق المصغّر قابلاً لتغيير الحجم في خلية واحدة على الجهاز نفسه، عليك ضبط minResizeHeight على ‎50dp على الأكثر للتأكّد من أنّ قيمة سمة minResizeHeight أصغر من ‎51dp، لأنّ ارتفاع الخلية يبلغ ‎51dp على الأقل في الوضع الأفقي.

يمكن تغيير حجم كل تطبيق مصغّر ضمن نطاقات الحجم بين سمات minResizeWidth/minResizeHeight وmaxResizeWidth/maxResizeHeight، ما يعني أنّه يجب أن يتكيّف مع أي نطاقات حجم بينهما.

على سبيل المثال، لضبط الحجم التلقائي للتطبيق المصغّر عند وضعه، يمكنك ضبط السمات التالية:

<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
    android:targetCellWidth="3"
    android:targetCellHeight="2"
    android:minWidth="180dp"
    android:minHeight="110dp">
</appwidget-provider>

يعني ذلك أنّ الحجم التلقائي للتطبيق المصغّر هو خلايا 3x2، كما هو محدّد من خلال سمات targetCellWidth وtargetCellHeight، أو ‎180×110dp، كما هو محدّد من خلال minWidth وminHeight للأجهزة التي تعمل بنظام Android 11 أو الإصدارات الأقدم. في الحالة الأخيرة، يمكن أن يختلف الحجم بالخلايا حسب الجهاز.

أيضًا، لضبط نطاقات الحجم المتوافقة مع التطبيق المصغّر، يمكنك ضبط السمات التالية:

<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
    android:minResizeWidth="180dp"
    android:minResizeHeight="110dp"
    android:maxResizeWidth="530dp"
    android:maxResizeHeight="450dp">
</appwidget-provider>

كما هو محدّد من خلال السمات السابقة، يمكن تغيير حجم عرض التطبيق المصغّر من ‎180dp إلى ‎530dp، ويمكن تغيير حجم ارتفاعه من ‎110dp إلى ‎450dp. بعد ذلك، يمكن تغيير حجم التطبيق المصغّر من خلايا 3x2 إلى خلايا 5x2، طالما أنّ الشروط التالية متوفّرة:

  • يتضمّن الجهاز شبكة 5x4.
  • تتّبع عملية الربط بين عدد الخلايا والحجم المتاح بوحدات dp الجدول الذي يعرض تقدير الحد الأدنى للأبعاد في هذه الصفحة.
  • يتكيّف التطبيق المصغّر مع نطاق الحجم هذا.

val smallView = RemoteViews(context.packageName, R.layout.widget_weather_forecast_small)
val mediumView = RemoteViews(context.packageName, R.layout.widget_weather_forecast_medium)
val largeView = RemoteViews(context.packageName, R.layout.widget_weather_forecast_large)

val viewMapping: Map<SizeF, RemoteViews> = mapOf(
    SizeF(180f, 110f) to smallView,
    SizeF(270f, 110f) to mediumView,
    SizeF(270f, 280f) to largeView
)

appWidgetManager.updateAppWidget(appWidgetId, RemoteViews(viewMapping))

لنفترض أنّ التطبيق المصغّر يستخدم التنسيقات السريعة الاستجابة المحدّدة في مقتطفات الرمز البرمجي السابقة. يعني ذلك أنّه يتم استخدام التنسيق المحدّد على أنّه R.layout.widget_weather_forecast_small من ‎180dp (minResizeWidth) × ‎110dp (minResizeHeight) إلى ‎269x279dp (نقاط القطع التالية - ‎1). وبالمثل، يتم استخدام R.layout.widget_weather_forecast_medium من ‎270x110dp إلى ‎270x279dp، ويتم استخدام R.layout.widget_weather_forecast_large من ‎270x280dp إلى ‎530dp (maxResizeWidth) × ‎450dp (maxResizeHeight).

أثناء تغيير المستخدم لحجم التطبيق المصغّر، يتغيّر مظهره ليتكيّف مع كل حجم بالخلايا، كما هو موضّح في الأمثلة التالية.

مثال على أداة الطقس في أصغر حجم شبكة 3x2 تعرض واجهة المستخدم اسم الموقع الجغرافي (طوكيو) ودرجة الحرارة (14 درجة مئوية) ورمزًا يشير إلى طقس غائم جزئيًا.
الشكل 2. 3x2 R.layout.widget_weather_forecast_small.

مثال على أداة الطقس بحجم &quot;متوسط&quot; 4x2 تستند عملية تغيير حجم الأداة بهذه الطريقة إلى جميع عناصر واجهة المستخدم من حجم الأداة السابق، وتضيف التصنيف &quot;غائم جزئيًا&quot; وتوقعات درجات الحرارة من الساعة 4 مساءً حتى الساعة 7 مساءً.
الشكل 3. 4x2 R.layout.widget_weather_forecast_medium.

مثال على تطبيق مصغّر للطقس بحجم &quot;متوسط&quot; 5x2 سيؤدي تغيير حجم الأداة بهذه الطريقة إلى ظهور واجهة المستخدم نفسها كما في الحجم السابق، ولكن سيتم تمديدها بمقدار طول خلية واحدة لتشغل مساحة أفقية أكبر.
الشكل 4. 5x2 R.layout.widget_weather_forecast_medium.

مثال على تطبيق مصغّر للطقس بحجم &quot;كبير&quot; 5x3 يستند تغيير حجم التطبيق المصغّر بهذه الطريقة إلى جميع عناصر واجهة المستخدم من أحجام التطبيق المصغّر السابقة، ويضيف طريقة عرض داخل التطبيق المصغّر تتضمّن توقعات الطقس ليومَي الثلاثاء والأربعاء. رموز تشير إلى الطقس المشمس أو الممطر
            ودرجات الحرارة المرتفعة والمنخفضة لكل يوم
الشكل 5. 5x3 R.layout.widget_weather_forecast_large.

مثال على تطبيق مصغّر للطقس بحجم &quot;كبير&quot; 5×4 يستند تغيير حجم الأداة بهذه الطريقة إلى جميع عناصر واجهة المستخدم من أحجام الأداة السابقة، ويضيف يومَي الخميس والجمعة (ورموزهما المقابلة التي تشير إلى نوع الطقس بالإضافة إلى درجة الحرارة العالية والمنخفضة لكل يوم).
الشكل 6. 5x4 R.layout.widget_weather_forecast_large.