دعم النوافذ المتعددة

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

الشكل 1. عرض تطبيقَين جنبًا إلى جنب في وضع تقسيم الشاشة

تعتمد تجربة المستخدم على إصدار نظام التشغيل Android ونوع الجهاز:

  • يوفّر Android 7.0 (المستوى 24 من واجهة برمجة التطبيقات) وضع تقسيم الشاشة على الأجهزة ذات الشاشات الصغيرة ووضع "نافذة ضمن النافذة" على أجهزة محدّدة.

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

    يتيح وضع "نافذة ضمن النافذة" للمستخدمين مواصلة تشغيل الفيديو أثناء التفاعل مع تطبيق آخر (راجِع إتاحة استخدام ميزة "نافذة ضمن النافذة").

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

    يمكنك ضبط كيفية تعامل تطبيقك مع وضع النوافذ المتعددة من خلال تحديد الحد الأدنى للأبعاد المسموح بها لنشاطك. يمكنك أيضًا إيقاف وضع النوافذ المتعددة لتطبيقك من خلال ضبط resizeableActivity="false" لضمان أن يعرض النظام تطبيقك في وضع ملء الشاشة دائمًا.

  • يعمل Android 8.0 (المستوى 26 من واجهة برمجة التطبيقات) على توسيع نطاق وضع "نافذة ضمن النافذة" ليشمل الأجهزة ذات الشاشات الصغيرة.
  • Android 12 (المستوى 31 من واجهة برمجة التطبيقات) يجعل السلوك العادي لوضع النوافذ المتعددة هو السلوك العادي.

    في الشاشات الكبيرة (sw >= 600dp)، يتيح النظام الأساسي جميع التطبيقات في وضع النوافذ المتعددة بغض النظر عن إعداداتها. إذا resizeableActivity="false"، يتم ضبط التطبيق في وضع التوافق عند الضرورة لاستيعاب أبعاد العرض.

    على الشاشات الصغيرة (sw < 600dp)، يتحقّق النظام من minWidth و minHeight للنشاط لتحديد ما إذا كان يمكن تنفيذ النشاط في وضع النوافذ المتعددة. إذا resizeableActivity="false"، يتم منع تشغيل التطبيق في وضع النوافذ المتعددة بغض النظر عن الحد الأدنى للعرض والارتفاع.

    ملاحظة: يمكن للشركات المصنّعة للأجهزة إلغاء هذه السلوكيات.

وضع تقسيم الشاشة

يمكن للمستخدمين تفعيل وضع تقسيم الشاشة من خلال تنفيذ ما يلي:

  1. افتح شاشة "العناصر الأخيرة".
  2. تمرير أحد التطبيقات سريعًا للعرض
  3. اضغط على رمز التطبيق في شريط عناوين التطبيق.
  4. تحديد خيار القائمة لتقسيم الشاشة
  5. يُرجى اختيار تطبيق آخر من شاشة "التطبيقات الأخيرة" أو إغلاق شاشة "التطبيقات الأخيرة" وتشغيل تطبيق آخر.

يمكن للمستخدمين الخروج من وضع تقسيم الشاشة عن طريق سحب أداة تقسيم النافذة إلى حافة الشاشة - لأعلى أو لأسفل أو لليسار أو اليمين.

تشغيل بشكل مجاور

إذا كان تطبيقك يحتاج إلى الوصول إلى المحتوى من خلال هدف، يمكنك استخدام FLAG_ACTIVITY_LAUNCH_ADJACENT لفتح المحتوى في نافذة مجاورة مقسّمة إلى أجزاء.

تم تقديم FLAG_ACTIVITY_LAUNCH_ADJACENT في نظام Android 7.0 (المستوى 24 من واجهة برمجة التطبيقات) للسماح للتطبيقات التي تعمل في وضع تقسيم الشاشة بتشغيل الأنشطة في النافذة المجاورة.

تم توسيع نطاق تعريف العلامة في نظام التشغيل Android 12L (المستوى 32 من واجهة برمجة التطبيقات) والإصدارات الأحدث للسماح للتطبيقات التي تعمل في وضع ملء الشاشة لتفعيل وضع تقسيم الشاشة ثم بدء الأنشطة في النافذة المجاورة.

لتشغيل نشاط مجاور، استخدِم FLAG_ACTIVITY_LAUNCH_ADJACENT بالاقتران مع FLAG_ACTIVITY_NEW_TASK، على سبيل المثال:

Kotlin

fun openUrlInAdjacentWindow(url: String) {
    Intent(Intent.ACTION_VIEW).apply {
        data = Uri.parse(url)
        addFlags(Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT or
                           Intent.FLAG_ACTIVITY_NEW_TASK)
    }.also { intent ->
        startActivity(intent)
    }
}

Java

public void openUrlInAdjacentWindow(String url) {
    Intent intent = new Intent(Intent.ACTION_VIEW);
    intent.setData(Uri.parse(url));
    intent.addFlags(Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT | Intent.FLAG_ACTIVITY_NEW_TASK);
    startActivity(intent);
}

مراحل النشاط في وضع النوافذ المتعددة

لا يغيّر وضع النوافذ المتعددة دورة حياة النشاط. ومع ذلك، تختلف الحالة الاستئناف من التطبيقات في نوافذ متعددة على إصدارات Android المختلفة.

استئناف متعدد

يتيح نظام التشغيل Android 10 (المستوى 29 من واجهة برمجة التطبيقات) والإصدارات الأحدث ميزة الاستئناف المتعدد، وتظل جميع الأنشطة على حالتها RESUMED عندما يكون الجهاز في وضع النوافذ المتعددة. يمكن إيقاف النشاط مؤقتًا إذا كان النشاط الشفاف أعلى النشاط أو إذا لم يكن النشاط قابلاً للتركيز، على سبيل المثال، وضع "نافذة ضمن النافذة". كما أنه من الممكن أيضًا عدم التركيز على أي نشاط في وقت معين، على سبيل المثال، عندما تكون لائحة الإشعارات مفتوحة. تعمل طريقة onStop كالمعتاد، وتُسمى الطريقة في أي وقت يتم فيه إزالة نشاط ما من الشاشة.

تتوفّر ميزة الاستئناف المتعدد أيضًا على أجهزة محدّدة تعمل بنظام التشغيل Android 9 (المستوى 28 من واجهة برمجة التطبيقات). لتفعيل ميزة السيرة الذاتية المتعدّدة على أجهزة Android 9، أضِف البيانات الوصفية التالية الخاصة بالبيان:

<meta-data android:name="android.allow_multiple_resumed_activities" android:value="true" />

للتحقّق من أنّ جهاز معيّن يتيح استخدام البيانات الوصفية للبيان هذه، يُرجى الرجوع إلى مواصفات الجهاز.

الإصدار 9 من نظام Android

في وضع النوافذ المتعددة على نظام التشغيل Android 9 (المستوى 28 لواجهة برمجة التطبيقات) والإصدارات الأقدم، يكون النشاط الذي تفاعل معه المستخدم مؤخرًا نشطًا في وقت معيَّن. يُعتبَر هذا النشاط الأعلى، وهو النشاط الوحيد في حالة RESUMED. جميع الأنشطة المرئية الأخرى هي STARTED ولكنها ليست RESUMED. ومع ذلك، يمنح النظام هذه الأنشطة المرئية ولكن لم يتم استئنافها أولوية أعلى من الأنشطة غير المرئية. إذا تفاعل المستخدم مع أحد الأنشطة المرئية، سيتم استئناف هذا النشاط، ويدخل النشاط الأعلى في السابق حالة STARTED.

عندما يكون هناك العديد من الأنشطة في عملية تطبيق نشطة واحدة، يتم استئناف النشاط ذو الترتيب الأعلى، ويتم إيقاف الأنشطة الأخرى مؤقتًا.

ملاحظة: في وضع النوافذ المتعددة على نظام التشغيل Android 9 والإصدارات الأقدم، قد لا يكون التطبيق في حالة RESUMED على الرغم من أنّه مرئي للمستخدم، ولكن قد يحتاج التطبيق إلى مواصلة تشغيله على أنّه ليس أعلى مستوى. على سبيل المثال، يجب أن يواصل تطبيق الفيديو في هذه الحالة تشغيل الفيديو الخاص به. لهذا السبب، ننصح ألا تؤدي الأنشطة التي تؤدي إلى تشغيل الفيديو إلى إيقاف تشغيل الفيديو مؤقتًا استجابةً لحدث مراحل نشاط ON_PAUSE. بدلاً من ذلك، من المفترض أن يبدأ تشغيل النشاط استجابةً للسمة ON_START، وأن يتم إيقافه مؤقتًا استجابةً للسمة ON_STOP. إذا عالجت أحداث مراحل النشاط بشكل مباشر بدلاً من استخدام حزمة رحلة المستخدم، عليك إيقاف تشغيل الفيديو مؤقتًا في معالِج onStop() واستئناف التشغيل في onStart().

تغييرات الإعدادات

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

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

إذا كان المستخدِم يغيِّر حجم نافذة وجعلها أكبر في أيٍّ من البُعدَين، يغيّر النظام حجم النشاط ليتوافق مع إجراء المستخدِم ويصدِر تغييرات الإعدادات حسب الحاجة. إذا كان التطبيق متأخرًا في الرسم في المناطق المكشوفة حديثًا، يملأ النظام مؤقتًا هذه المناطق باللون المحدّد في السمة windowBackground أو حسب سمة النمط windowBackgroundFallback التلقائية.

الوصول الحصري إلى المراجع

للمساعدة في إتاحة ميزة الاستئناف المتعدد، تتوفّر ميزة جديدة لمعاودة الاتصال خلال مراحل النشاط onTopResumedActivityChanged().

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

Kotlin

override fun onTopResumedActivityChanged(topResumed: Boolean) {
    if (topResumed) {
        // Top resumed activity
        // Can be a signal to re-acquire exclusive resources
    } else {
        // No longer the top resumed activity
    }
}

Java

@Override
public void onTopResumedActivityChanged(boolean topResumed) {
    if (topResumed) {
        // Top resumed activity
        // Can be a signal to re-acquire exclusive resources
    } else {
        // No longer the top resumed activity
    }
}

يُرجى ملاحظة أنّه يمكن أن يفقد أحد التطبيقات الموارد لأسباب أخرى، مثل إزالة جهاز مشترَك.

وعلى أي حال، يجب أن يتعامل التطبيق بأمان مع الأحداث ويذكر التغييرات التي تؤثر في الموارد المتاحة.

بالنسبة إلى التطبيقات التي تستخدم كاميرا، يقدّم CameraManager.AvailabilityCallback#onCameraAccessPrioritiesChanged() تلميحًا إلى أنّ هذا هو الوقت المناسب لمحاولة الوصول إلى الكاميرا. تتوفّر هذه الطريقة اعتبارًا من الإصدار Android 10 (المستوى 29 من واجهة برمجة التطبيقات).

يُرجى العلم أنّ resizeableActivity=false لا يضمن الوصول الحصري إلى الكاميرا، إذ يمكن فتح التطبيقات الأخرى التي تستخدم الكاميرا على شاشات أخرى.

الكاميرا في وضع النوافذ المتعددة

الشكل 2. الكاميرا في وضع النوافذ المتعددة

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

بعد أن يتلقّى التطبيق إشعار CameraDevice.StateCallback#onDisconnected() بمعاودة الاتصال، سيتم إرسال علامة CameraAccessException عند المكالمات اللاحقة على جهاز الكاميرا.

شاشات متعددة

يتيح Android 10 (المستوى 29 من واجهة برمجة التطبيقات) الأنشطة على الشاشات الثانوية. إذا كان النشاط قيد التشغيل على جهاز مزوّد بشاشات عرض متعددة، يمكن للمستخدمين نقل النشاط من شاشة إلى أخرى. ينطبق السيرة الذاتية المتعددة على سيناريوهات الشاشات المتعددة أيضًا؛ يمكن أن تتلقى أنشطة متعددة مدخلات المستخدم في نفس الوقت.

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

عندما ينتقل نشاط إلى عرض ثانوي، يمكن أن يمر عبر تحديث السياق، وتغيير حجم النوافذ، وتغييرات التكوين والموارد. وفي حال كان النشاط يشمل التغيير في الإعدادات، يتم إرسال إشعار بذلك النشاط في onConfigurationChanged()، وفي حال عدم إجراء ذلك، ستتم إعادة بدء النشاط.

يجب أن يتحقّق النشاط من الشاشة الحالية في onCreate وonConfigurationChanged في حال التعامل مع تغييرات الإعدادات. تأكد من تحديث الموارد والتخطيطات عند تغيير العرض.

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

نُسخ متعددة من نشاط على شاشات عرض متعددة

الشكل 3. نُسخ متعددة من نشاط على شاشات عرض متعددة

يمكنك أيضًا الاطلاع على واجهات برمجة التطبيقات للشاشات المتعددة التي تم تقديمها في Android 8.0.

سياق النشاط مقابل التطبيق

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

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

تحدد تهيئة نافذة النشاط والعرض الرئيسي الموارد والسياق. احصل على الشاشة الحالية على النحو التالي:

Kotlin

val activityDisplay = activity.getDisplay()

Java

Display activityDisplay = activity.getDisplay();

الحصول على مقاييس فترة النشاط الحالية:

Kotlin

val windowMetrics = activity.getWindowManager().getCurrentWindowMetrics()

Java

WindowMetrics windowMetrics = activity.getWindowManager().getCurrentWindowMetrics();

احصل على الحد الأقصى لمقاييس الفترات الزمنية للإعدادات الحالية للنظام:

Kotlin

val maximumWindowMetrics = activity.getWindowManager().getMaximumWindowMetrics()

Java

WindowMetrics maximumWindowMetrics = activity.getWindowManager().getMaximumWindowMetrics();

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

قواطع للعرض

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

الشاشات الثانوية

ويمكنك الحصول على الشاشات المتاحة من خدمة نظام DisplayManager:

Kotlin

val displayManager = getSystemService(Context.DISPLAY_SERVICE) as DisplayManager
val displays = displayManager.getDisplays()

Java

DisplayManager displayManager = (DisplayManager) getSystemService(Context.DISPLAY_SERVICE);
Display[] displays = displayManager.getDisplays();

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

تحديد ما إذا كان يمكن بدء النشاط على شاشة أم لا:

Kotlin

val activityManager = getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
val activityAllowed = activityManager.isActivityStartAllowedOnDisplay(context, displayId, intent)

Java

ActivityManager activityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
boolean activityAllowed = activityManager.isActivityStartAllowedOnDisplay(context, displayId, intent);

بعد ذلك، شغِّل النشاط على الشاشة:

Kotlin

val options = ActivityOptions.makeBasic()
options.setLaunchDisplayId(targetDisplay.displayId)
startActivity(intent, options.toBundle())

Java

ActivityOptions options = ActivityOptions.makeBasic();
options.setLaunchDisplayId(targetDisplay.displayId);
startActivity(intent, options.toBundle());

دعم الشاشات المتعددة

يوفر Android إمكانية استخدام شاشات متعددة مع لوحات المفاتيح البرمجية والخلفيات ومشغّلات التطبيقات.

لوحة مفاتيح برمجية

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

لوحة مفاتيح على شاشة ثانوية

الشكل 4. لوحة مفاتيح على شاشة ثانوية

الخلفية

في نظام التشغيل Android 10 (المستوى 29 من واجهة برمجة التطبيقات)، يمكن أن تتضمّن الشاشات الثانوية خلفية. ينشئ إطار العمل مثيلاً منفصلاً لـ WallpaperService.Engine لكل عرض. احرص على رسم سطح كل محرك بشكل مستقل. يمكن لمطوّري البرامج تحميل مواد العرض باستخدام سياق العرض في WallpaperService.Engine#getDisplayContext(). يجب أيضًا التأكّد من WallpaperInfo.xml مجموعة الملفات android:supportsMultipleDisplays="true".

خلفية على الهاتف والشاشة الثانوية.

الشكل 5. خلفية على الهاتف والشاشة الثانوية.

مشغّلات التطبيقات

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

<activity>
    ...
    <intent-filter>
        <category android:name="android.intent.category.SECONDARY_HOME" />
        ...
    </intent-filter>
</activity>

يجب أن يتضمن النشاط وضع تشغيل لا يمنع ظهور مثيلات متعددة ويمكن أن يتكيف مع أحجام الشاشات المختلفة. لا يمكن أن يكون وضع الإطلاق singleInstance أو singleTask.

على سبيل المثال، يدعم تنفيذ AOSP للسمة Launcher3 نشاط SECONDARY_HOME.

مشغّل التطبيقات متعددة الأبعاد على هاتف

الشكل 6. مشغّل التطبيقات متعددة الأبعاد على هاتف

مشغّل تطبيقات Material Design على شاشة ثانوية

الشكل 7. مشغّل تطبيقات Material Design على شاشة ثانوية

مقاييس الفترة الزمنية

قدّم Android 11 (المستوى 30 لواجهة برمجة التطبيقات) طُرق WindowManager التالية لتوفير حدود التطبيقات التي تعمل في وضع النوافذ المتعددة:

توفّر طريقتا مكتبة Jetpack WindowManager computeCurrentWindowMetrics() وcomputeMaximumWindowMetrics() وظائف مماثلة على التوالي، ولكن مع التوافق مع الأنظمة القديمة مع المستوى 14 من واجهة برمجة التطبيقات.

للحصول على مقاييس لشاشات عرض أخرى غير العرض الحالي، يمكنك إجراء ما يلي:

  • إنشاء سياق عرض
  • إنشاء سياق نافذة للعرض
  • الحصول على WindowManager لسياق النافذة
  • احصل على WindowMetrics من أقصى مساحة عرض متاحة للتطبيق.

Kotlin

val windowMetrics = context.createDisplayContext(display)
                    .createWindowContext(WindowManager.LayoutParams.TYPE_APPLICATION, null)
                    .getSystemService(WindowManager::class.java)
                    .maximumWindowMetrics

Java

WindowMetrics windowMetrics = context.createDisplayContext(display)
                              .createWindowContext(WindowManager.LayoutParams.TYPE_APPLICATION, null)
                              .getSystemService(WindowManager.class)
                              .getMaximumWindowMetrics();

الطرق المتوقّفة نهائيًا

تم إيقاف طرق Display getSize() وgetMetrics() في المستوى 30 من واجهة برمجة التطبيقات لصالح طرق WindowManager الجديدة.

يوقف Android 12 (مستوى واجهة برمجة التطبيقات 31) نهائيًا Display طرق getRealSize() وgetRealMetrics() ويعدّل سلوكها لتتطابق بشكل وثيق مع سلوك getMaximumWindowMetrics().

ضبط وضع النوافذ المتعددة

إذا كان تطبيقك يستهدف الإصدار 7.0 من نظام التشغيل Android (المستوى 24 لواجهة برمجة التطبيقات) أو إصدارًا أحدث، يمكنك ضبط كيفية عمل تطبيقك وما إذا كانت أنشطة تطبيقك تتوافق مع وضع النوافذ المتعددة. ويمكنك ضبط السمات في ملف البيان للتحكّم في كل من الحجم والتنسيق. تنطبق إعدادات سمة النشاط الجذر على جميع الأنشطة ضمن حزمة المهام الخاصة به. على سبيل المثال، إذا كان النشاط الجذر يحتوي على android:resizeableActivity="true"، يمكن تغيير حجم جميع الأنشطة في حزمة المهام. على بعض الأجهزة الأكبر حجمًا، مثل أجهزة Chromebook، قد يتم تشغيل تطبيقك في نافذة يمكن تغيير حجمها حتى في حال تحديد android:resizeableActivity="false". إذا كان هذا سيؤدي إلى إيقاف تطبيقك، يمكنك استخدام الفلاتر لتقييد مدى توفر تطبيقك على هذه الأجهزة.

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

الإعداد التلقائي لنظام التشغيل Android 12 (مستوى واجهة برمجة التطبيقات 31) هو وضع النوافذ المتعددة. في الشاشات الكبيرة (sw >= 600dp)، تعمل جميع التطبيقات في وضع النوافذ المتعددة بغض النظر عن إعدادات التطبيق. على الشاشات الصغيرة، يتحقّق النظام من إعدادات minWidth وminHeight و resizeableActivity النشاط لتحديد ما إذا كان يمكن تشغيله في وضع النوافذ المتعددة.

نشاط قابل لتغيير الحجم

اضبط هذه السمة في عنصر <activity> أو <application> في البيان لتفعيل وضع النوافذ المتعددة أو إيقافه على المستوى 30 من واجهة برمجة التطبيقات والإصدارات الأدنى:

<application
  android:name=".MyActivity"
  android:resizeableActivity=["true" | "false"] />

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

إذا كان تطبيقك يستهدف المستوى 24 من واجهة برمجة التطبيقات أو مستوى أعلى، ولكنك لم تحدّد قيمة لهذه السمة، يتم ضبط قيمة السمة تلقائيًا على "صحيح".

إذا كان تطبيقك يستهدف المستوى 31 من واجهة برمجة التطبيقات أو مستوى أعلى، تعمل هذه السمة بشكل مختلف على الشاشات الصغيرة والكبيرة:

  • الشاشات الكبيرة (sw >= 600dp): تتيح جميع التطبيقات وضع النوافذ المتعددة. تشير السمة إلى ما إذا كان يمكن تغيير حجم النشاط أم لا. إذا resizeableActivity="false"، يتم ضبط التطبيق في وضع التوافق عند ضرورة التوافق مع أبعاد العرض.
  • الشاشات الصغيرة (sw < 600dp): إذا كان resizeableActivity="true" والنشاط ضمن الحدّ الأدنى للعرض والحد الأدنى للارتفاع ضمن متطلبات النوافذ المتعددة، يوفّر النشاط وضع النوافذ المتعددة. في حال resizeableActivity="false"، يعني هذا أن النشاط لا يتيح وضع النوافذ المتعددة بغض النظر عن الحد الأدنى للعرض والارتفاع للنشاط.

متوافق مع ImageInImage

يمكنك ضبط هذه السمة في العقدة <activity> في ملف البيان لتوضيح ما إذا كان النشاط يتيح استخدام وضع "نافذة ضمن النافذة".

<activity
  android:name=".MyActivity"
  android:supportsPictureInPicture=["true" | "false"] />

ملاحظة: في حال supportsPictureInPicture="true"، يجب ضبط السمة android:configChanges لتفعيل نشاطك من أجل معالجة تغييرات الإعدادات ( إتاحة استخدام نافذة ضمن النافذة).

تغييرات الإعدادات

للتعامل مع التغييرات في إعدادات النوافذ المتعددة بنفسك، مثلاً عند تغيير المستخدم لحجم نافذة، أضِف السمة android:configChanges إلى بيان التطبيق <activity> مع تضمين القيم التالية على الأقل:

<activity
  android:name=".MyActivity"
  android:configChanges="screenSize | smallestScreenSize
      | screenLayout | orientation" />

بعد إضافة android:configChanges، يتلقّى نشاطك وأجزاءك استدعاء إلى onConfigurationChanged() بدلاً من تلفها وإعادة إنشائها. يمكنك بعد ذلك تحديث طرق العرض، وإعادة تحميل الموارد، وتنفيذ عمليات أخرى يدويًا حسب الحاجة.

<التنسيق>

في نظام التشغيل Android 7.0 (مستوى واجهة برمجة التطبيقات 24) والإصدارات الأحدث، يتوافق عنصر البيان <layout> مع العديد من السمات التي تؤثر في سلوك النشاط في وضع النوافذ المتعددة:

android:defaultHeight، android:defaultWidth
الارتفاع والعرض التلقائي للنشاط عند تشغيله في وضع التصميم المرن.
android:gravity
الموضع الأول للنشاط عند إطلاقه في وضع التصميم المرن. اطّلِع على السمة Gravity لمعرفة القيم المناسبة.
android:minHeight، android:minWidth
الحد الأدنى للارتفاع والحد الأدنى للعرض للنشاط في وضعَي "تقسيم الشاشة" والوضع المرن. إذا حرّك المستخدم الفاصل في وضع تقسيم الشاشة لجعل النشاط أصغر من الحد الأدنى المحدَّد، يقتصّ النظام النشاط إلى الحجم الذي يطلبه المستخدم.

توضح التعليمة البرمجية التالية كيفية تحديد الحجم والموقع الافتراضيين للنشاط والحد الأدنى لحجمه عند عرض النشاط في وضع التصميم المرن:

<activity android:name=".MyActivity">
    <layout android:defaultHeight="500dp"
          android:defaultWidth="600dp"
          android:gravity="top|end|..."
          android:minHeight="450dp"
          android:minWidth="300dp" />
</activity>

وضع النوافذ المتعددة في وقت التشغيل

بدءًا من نظام التشغيل Android 7.0، يوفر النظام وظائف لدعم التطبيقات التي يمكن تشغيلها في وضع النوافذ المتعددة.

الميزات غير المفعّلة في وضع النوافذ المتعددة

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

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

يتجاهل النظام التغييرات في السمة android:screenOrientation.

طلبات البحث ومعاودة الاتصال في وضع النوافذ المتعددة

تقدّم فئة Activity الطُرق التالية لإتاحة وضع النوافذ المتعددة:

isInMultiWindowMode()
يشير
إلى ما إذا كان النشاط يتم في وضع النوافذ المتعددة.
isInPictureInPictureMode()
يشير
إلى ما إذا كان النشاط في وضع "نافذة ضمن النافذة".
ملاحظة: يُعدّ وضع "نافذة ضمن النافذة" حالة خاصة لوضع النوافذ المتعددة. وإذا كانت قيمة myActivity.isInPictureInPictureMode() تعرض القيمة "صحيح"، ستكون قيمة myActivity.isInMultiWindowMode() أيضًا هي "صحيح".
onMultiWindowModeChanged()
يستدعي النظام هذه الطريقة عندما يدخل النشاط في وضع النوافذ المتعددة أو يخرج منه. ويمرِّر النظام القيمة "true" إذا كان النشاط يدخل في وضع النوافذ المتعددة أو على "خطأ" إذا كان النشاط يغادر وضع النوافذ المتعددة.
onPictureInPictureModeChanged()
يستدعي النظام هذه الطريقة عند دخول النشاط في وضع "نافذة ضمن النافذة" أو خارجه. ويمرِّر النظام القيمة "صحيح" إذا دخل النشاط في وضع "نافذة ضمن النافذة" أو على "خطأ" إذا كان النشاط يغادر وضع "نافذة ضمن النافذة".

تعرض الفئة Fragment إصدارات من العديد من هذه الطرق، على سبيل المثال، Fragment.onMultiWindowModeChanged().

وضع "نافذة ضمن النافذة"

لتفعيل وضع "نافذة ضمن النافذة"، اتصِل بـ enterPictureInPictureMode() ليس لهذه الطريقة أي تأثير إذا لم يكن الجهاز يتيح استخدام وضع "نافذة ضمن النافذة". لمزيد من المعلومات، يُرجى الاطّلاع على صفحة دعم ميزة "نافذة ضمن النافذة".

أنشطة جديدة في وضع النوافذ المتعددة

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

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

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

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

سحب وإفلات

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

نسخ متعددة

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

يتيح لك نظام التشغيل Android 12 (المستوى 31 من واجهة برمجة التطبيقات) تشغيل مثيلين من النشاط جنبًا إلى جنب في نافذة المهمة نفسها.

إذا كنت تريد السماح للمستخدمين ببدء نسخة أخرى من تطبيقك من مشغِّل التطبيقات أو شريط التطبيقات، تأكّد من ضبط رمز النشاط في مشغّل التطبيقات android:resizeableActivity="true" وعدم استخدام وضع تشغيل يمنع حدوث عدة مثيلات. على سبيل المثال، يمكن إنشاء مثيل لنشاط singleInstancePerTask عدة مرات في مهام مختلفة عند ضبط FLAG_ACTIVITY_MULTIPLE_TASK أو FLAG_ACTIVITY_NEW_DOCUMENT. ملاحظة: مشغّل التطبيقات هو مربع حوار نظام يعرض قائمة بالتطبيقات التي تلبي هدفًا محددًا. يمكن للمستخدمين تشغيل تطبيق عن طريق اختياره من القائمة. اطّلِع على أنواع الأهداف.

لا تخلِط بين التكرار المتعدد المثيلات والتنسيق المتعدد اللوحات، مثل العرض التقديمي بتفاصيل القائمة الذي يستخدم SlidingPaneLayout، والذي يتم تشغيله داخل نافذة واحدة.

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

التحقّق من وضع النوافذ المتعددة

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

أجهزة الاختبار

تتوافق الأجهزة التي تعمل بنظام التشغيل Android 7.0 (المستوى 24 لواجهة برمجة التطبيقات) أو الإصدارات الأحدث مع وضع النوافذ المتعددة.

المستوى 23 من واجهة برمجة التطبيقات أو مستوى أقل

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

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

إذا أعلن التطبيق عن اتجاه ثابت، يجب أن تحاول وضع التطبيق في وضع النوافذ المتعددة. تحقق من أنه عند القيام بذلك، يظل التطبيق في وضع ملء الشاشة.

مستويات واجهة برمجة التطبيقات من 24 إلى 30

إذا كان تطبيقك يستهدف مستويات واجهة برمجة التطبيقات من 24 إلى 30 ولا يوقف إتاحة النوافذ المتعددة، تحقَّق من السلوك التالي في وضعَي "تقسيم الشاشة" و"التصميم المرن":

  • شغِّل التطبيق في وضع ملء الشاشة، ثم بدِّل إلى وضع النوافذ المتعددة من خلال الضغط مع الاستمرار على زر "التطبيقات الأخيرة". تأكَّد من تبديل التطبيق بشكل صحيح.
  • شغِّل التطبيق مباشرةً في وضع النوافذ المتعددة وتحقَّق من تشغيل التطبيق بشكل صحيح. يمكنك تشغيل تطبيق في وضع النوافذ المتعددة من خلال الضغط على زر التطبيقات الأخيرة، ثم الضغط مع الاستمرار على شريط عنوان التطبيق وسحبه إلى إحدى المناطق التي تم تمييزها على الشاشة.
  • يمكنك تغيير حجم التطبيق في وضع تقسيم الشاشة عن طريق سحب أداة تقسيم الشاشة. تأكَّد من أنّ حجم التطبيق يتم تغييره بدون أن يتعطّل وأنّ العناصر الضرورية في واجهة المستخدم مرئية.
  • إذا كنت قد حددت الحد الأدنى من الأبعاد لتطبيقك، فحاول تغيير حجم التطبيق بحيث يكون أقل من تلك الأبعاد. تحقَّق من أنه لا يمكنك تغيير حجم التطبيق ليكون أصغر من الحد الأدنى المحدد للأبعاد.
  • يُرجى التأكّد من أنّ أداء تطبيقك مقبول من خلال جميع الاختبارات. على سبيل المثال، تأكَّد من عدم وجود تأخّر طويل جدًا لتحديث واجهة المستخدم بعد تغيير حجم التطبيق.

المستوى 31 من واجهة برمجة التطبيقات أو مستوى أعلى

إذا كان تطبيقك يستهدف المستوى 31 من واجهة برمجة التطبيقات أو أعلى وكان الحدّ الأدنى للعرض والحد الأدنى للارتفاع للنشاط الرئيسي أقل من أو مساوَين للأبعاد ذات الصلة لمساحة العرض المتاحة، يُرجى التحقّق من جميع السلوكيات المدرَجة بشأن مستويات واجهة برمجة التطبيقات من 24 إلى 30.

ملاحظة: يمكنك أن تحدّد آليًا ما إذا كان تطبيقك في وضع النوافذ المتعددة من خلال التحقّق من القيمة المعروضة Activity#isInMultiWindowMode().

قائمة التحقق للاختبار

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

  • الدخول إلى وضع النوافذ المتعددة والخروج منه
  • بدِّل من تطبيقك إلى تطبيق آخر، وتحقَّق من أنّ التطبيق يعمل بشكل صحيح عندما يكون مرئيًا ولكنّه غير نشط. على سبيل المثال، إذا كان تطبيقك يشغّل فيديو، تأكَّد من أنّ الفيديو يستمر في تشغيله أثناء تفاعل المستخدم مع تطبيق آخر.
  • في وضع تقسيم الشاشة، حاوِل تحريك أداة تقسيم الشاشة لجعل تطبيقك أكبر أو أصغر حجمًا. يمكنك تجربة هذه العمليات جنبًا إلى جنب مع طريقة واحدة فوق الإعدادات الأخرى. تأكَّد من أنّ التطبيق لا يتعطّل وأنّ الوظائف الأساسية ظاهرة وأنّ عملية تغيير الحجم لا تستغرق وقتًا طويلاً.
  • تنفيذ عدة عمليات لتغيير الحجم في تتابع سريع. تأكَّد من عدم تعطُّل تطبيقك أو تسريب الذاكرة. يوفّر "محلل الذاكرة" في "استوديو Android" معلومات حول استخدام تطبيقك للذاكرة (راجِع فحص استخدام ذاكرة التطبيق باستخدام "محلل الذاكرة").
  • استخدم تطبيقك بشكل طبيعي في عدد من عمليات ضبط النوافذ المختلفة، وتأكَّد من أنّ التطبيق يعمل بشكل صحيح. تأكَّد من أنّ النص سهل القراءة وأنّ عناصر واجهة المستخدم ليست صغيرة جدًا بحيث لا يمكن التفاعل معها.

تم إيقاف إتاحة النوافذ المتعددة

في مستويات واجهة برمجة التطبيقات من 24 إلى 30، إذا أوقفت إتاحة النوافذ المتعددة من خلال ضبط android:resizeableActivity="false"، عليك تشغيل التطبيق على جهاز يعمل بالإصدار 7.0 إلى الإصدار 11 من نظام التشغيل Android ومحاولة تحويل التطبيق إلى وضعَي الشاشة المنقسمة والنمط المرن. تحقق من أنه عند القيام بذلك، يظل التطبيق في وضع ملء الشاشة.

مراجع إضافية

لمزيد من المعلومات عن إتاحة النوافذ المتعددة في Android، يُرجى الاطّلاع على: