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

تصف هذه الصفحة التحسينات الخاصة بتغيير حجم التطبيقات المصغّرة والمرونة الأكبر التي تم تقديمها في 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 متوافق من 160 بكسل مستقل الكثافة (minResizeWidth) × 110 بكسل مستقل الكثافة (minResizeHeight) إلى 160 بكسل مستقل الكثافة × 199 بكسل مستقل الكثافة (نقطة الانقطاع التالية - 1 بكسل مستقل الكثافة)
  • تتوافق ميزة tallView من 160 بكسل مستقل الكثافة × 200 بكسل مستقل الكثافة إلى 214 بكسل مستقل الكثافة (نقطة النهاية التالية - 1) × 200 بكسل مستقل الكثافة (dp).
  • 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 للأجهزة التي تعمل بنظام التشغيل Android 12 أو الإصدارات الأحدث، أو minWidth وminHeight لجميع إصدارات Android، مع الإشارة إلى الحدّ الأدنى من المساحة التي يستهلكها تلقائيًا. ومع ذلك، عندما يضيف المستخدمون أداةً إلى شاشتهم الرئيسية، غالبًا ما تشغل هذه الأداة أكثر من الحدّ الأدنى للعرض والارتفاع اللذان تحدّدهما.

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

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

عدد الخلايا (العرض × الارتفاع) الحجم المتاح في الوضع العمودي (dp) الحجم المتاح في الوضع الأفقي (dp)
1x1 57×102 بكسل مستقل الكثافة 127×51 بكسل مستقل الكثافة
2×1 130 × 102 بكسل مستقل الكثافة 269×51 بكسل مستقل الكثافة
3x1 203×102 بكسل مستقل الكثافة 412×51 بكسل مستقل الكثافة
4×1 276 × 102 بكسل مستقل الكثافة 554×51 بكسل مستقل الكثافة
5x1 349 × 102 بكسل مستقل الكثافة 697×51 بكسل مستقل الكثافة
5×2 349×220 بكسل مستقل الكثافة 697 × 117 بكسل مستقل الكثافة
5×3 349 × 337 بكسل مستقل الكثافة 697×184 بكسل مستقل الكثافة
5×4 349×455 بكسل مستقل الكثافة 697×250 بكسل مستقل الكثافة
... ... ...
ن 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 بكسل مستقل الكثافة على الأكثر للتأكّد من أنّ قيمة السمة minResizeHeight أقل من 51 بكسل مستقل الكثافة (dp)، لأنّ قيمة خلية واحدة يبلغ ارتفاعها 51 بكسل مستقل الكثافة على الأقل في الوضع الأفقي.

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

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

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

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

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

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

كما هو موضح من خلال السمات السابقة، يتم تغيير حجم عرض الأداة من 180 بكسل مستقل الكثافة إلى 530 بكسل مستقل الكثافة (dp)، ويمكن تغيير ارتفاعها من 110 بكسل مستقل الكثافة (dp) إلى 450 بكسل مستقل الكثافة (dp). يمكن بعد ذلك تغيير حجم الأداة من خلايا 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 من 270x110dp إلى 270x279dp، ويتم استخدام R.layout.widget_weather_forecast_large من 270x280dp إلى 530dp (maxResizeWidth) x 450dp (maxResizeHeight).

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

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

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

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

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

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