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

توضّح هذه الصفحة التحسينات التي تم إجراؤها على تغيير حجم التطبيقات المصغّرة وتوفير مرونة أكبر في نظام التشغيل 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 ثم تقدير حجم الأداة، إلا أنّ هذا المنطق لا يعمل في جميع الحالات. بالنسبة إلى التطبيقات المصغّرة التي تستهدف الإصدار 12 من نظام التشغيل Android أو الإصدارات الأحدث، نقترح توفير تنسيقات سريعة الاستجابة أو تنسيقات دقيقة.

تحديد قيود إضافية لتغيير حجم الأداة

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

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

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

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

يوضح ملف XML التالي كيفية استخدام سمات المقاس.

<appwidget-provider
  ...
  android:targetCellWidth="3"
  android:targetCellHeight="2"
  android:maxResizeWidth="250dp"
  android:maxResizeHeight="110dp">
</appwidget-provider>

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

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

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

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

Kotlin

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

    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)
}

Java

@Override
public void onUpdate(...) {
    RemoteViews smallView = ...;
    RemoteViews tallView = ...;
    RemoteViews wideView = ...;

    Map<SizeF, RemoteViews> viewMapping = new ArrayMap<>();
    viewMapping.put(new SizeF(150f, 100f), smallView);
    viewMapping.put(new SizeF(150f, 200f), tallView);
    viewMapping.put(new SizeF(215f, 100f), wideView);
    RemoteViews remoteViews = new RemoteViews(viewMapping);

    appWidgetManager.updateAppWidget(id, remoteViews);
}

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

<appwidget-provider
    android:minResizeWidth="160dp"
    android:minResizeHeight="110dp"
    android:maxResizeWidth="250dp"
    android:maxResizeHeight="200dp">
</appwidget-provider>

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

  • يتوافق smallView مع نسبة وحدات بكسل مستقلة الكثافة (minResizeWidth) × 110 بكسل مستقل الكثافة (minResizeHeight) إلى 160 بكسل مستقل الكثافة × 199 بكسل مستقل الكثافة (نقطة الانقطاع التالية عند الوصول إلى 1 بكسل مستقل الكثافة).
  • تتوافق "tallView" مع نسبة 160 بكسل مستقل الكثافة × 200 بكسل مستقل الكثافة إلى 214 بكسل مستقل الكثافة (نقطة الانقطاع التالية عند 1) × 200 بكسل مستقل الكثافة.
  • يتوافق wideView مع الفترة من 215 بكسل مستقل الكثافة × 110 بكسل مستقل الكثافة (minResizeHeight) إلى 250 بكسل مستقل الكثافة (maxResizeWidth) × 200 بكسل مستقل الكثافة (maxResizeHeight).

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

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

تقديم تنسيقات دقيقة

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

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

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

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

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

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

Kotlin

override fun onAppWidgetOptionsChanged(
        context: Context,
        appWidgetManager: AppWidgetManager,
        id: Int,
        newOptions: Bundle?
) {
    super.onAppWidgetOptionsChanged(context, appWidgetManager, id, newOptions)
    // Get the new sizes.
    val sizes = newOptions?.getParcelableArrayList<SizeF>(
            AppWidgetManager.OPTION_APPWIDGET_SIZES
    )
    // 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 { }

Java

@Override
public void onAppWidgetOptionsChanged(
    Context context, AppWidgetManager appWidgetManager, int appWidgetId, Bundle newOptions) {
    super.onAppWidgetOptionsChanged(context, appWidgetManager, appWidgetId, newOptions);
    // Get the new sizes.
    ArrayList<SizeF> sizes =
        newOptions.getParcelableArrayList(AppWidgetManager.OPTION_APPWIDGET_SIZES);
    // Check that the list of sizes is provided by the launcher.
    if (sizes == null || sizes.isEmpty()) {
      return;
    }
    // Map the sizes to the RemoteViews that you want.
    Map<SizeF, RemoteViews> viewMapping = new ArrayMap<>();
    for (SizeF size : sizes) {
        viewMapping.put(size, createRemoteViews(size));
    }
    RemoteViews remoteViews = new RemoteViews(viewMapping);
    appWidgetManager.updateAppWidget(id, remoteViews);
}

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

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

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

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

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

عدد الخلايا (العرض × الارتفاع) الحجم المتوفر في وضع "بورتريه" (dp) الحجم المتوفر في الوضع الأفقي (dp)
1×1 57x102 بكسل مستقل الكثافة 127 × 51 بكسل مستقل الكثافة
2×1 130 × 102 بكسل مستقل الكثافة 269 × 51 بكسل مستقل الكثافة
3×1 203x102 بكسل مستقل الكثافة 412 × 51 بكسل مستقل الكثافة
4×1 276 × 102 بكسل مستقل الكثافة 554 × 51 بكسل مستقل الكثافة
5×1 349 × 102 بكسل مستقل الكثافة 697 × 51 بكسل مستقل الكثافة
5×2 349 × 220 بكسل مستقل الكثافة 697×117 بكسل مستقل الكثافة
5×3 349 × 337 بكسل مستقل الكثافة 697×184 بكسل مستقل الكثافة
5×4 349 × 455 بكسل مستقل الكثافة 697 × 250 بكسل مستقل الكثافة
... ... ...
n x م (73n - 16) × (118 د - 16) (142 - 15) × (66 مترًا - 15)

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

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

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

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

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

<appwidget-provider
    android:targetCellWidth="3"
    android:targetCellHeight="2"
    android:minWidth="180dp"
    android:minHeight="110dp">
</appwidget-provider>

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

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

<appwidget-provider
    android:minResizeWidth="180dp"
    android:minResizeHeight="110dp"
    android:maxResizeWidth="530dp"
    android:maxResizeHeight="450dp">
</appwidget-provider>

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

Kotlin

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))

Java

RemoteViews smallView = 
    new RemoteViews(context.getPackageName(), R.layout.widget_weather_forecast_small);
RemoteViews mediumView = 
    new RemoteViews(context.getPackageName(), R.layout.widget_weather_forecast_medium);
RemoteViews largeView = 
    new RemoteViews(context.getPackageName(), R.layout.widget_weather_forecast_large);

Map<SizeF, RemoteViews> viewMapping = new ArrayMap<>();
viewMapping.put(new SizeF(180f, 110f), smallView);
viewMapping.put(new SizeF(270f, 110f), mediumView);
viewMapping.put(new SizeF(270f, 280f), largeView);
RemoteViews remoteViews = new RemoteViews(viewMapping);

appWidgetManager.updateAppWidget(id, remoteViews);

لنفترض أن الأداة تستخدم التخطيطات سريعة الاستجابة المحددة في مقتطفات الكود السابقة. وهذا يعني أنّ التنسيق R.layout.widget_weather_forecast_small يتم استخدامه بدءًا من 180 بكسل مستقل الكثافة (minResizeWidth) × 110 بكسل مستقل الكثافة (minResizeHeight) إلى 269×279 بكسل مستقل الكثافة (نقاط النهاية التالية - 1). وبالمثل، يتم استخدام R.layout.widget_weather_forecast_medium من 270x110 بكسل مستقل الكثافة إلى 270x279 بكسل مستقل الكثافة، ويُستخدَم R.layout.widget_weather_forecast_large من 270x280 بكسل مستقل الكثافة إلى 530 بكسل مستقل الكثافة (maxResizeWidth) × 450 بكسل مستقل الكثافة (maxResizeHeight).

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

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

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

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

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

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