يعمل تطبيقك بشكل رائع على الهواتف في الوضع العمودي، لذا حصرت استخدام التطبيق على الوضع العمودي فقط. ولكنّك ترى فرصة لتحقيق المزيد على الشاشات الكبيرة في الوضع الأفقي.
كيف يمكن تحقيق ذلك؟ أي حصر التطبيق على الاتجاه العمودي على الشاشات الصغيرة، ولكن السماح بالاتجاه الأفقي على الشاشات الكبيرة؟
هذا الدليل هو إجراء مؤقت إلى أن تتمكّن من تحسين تطبيقك ليتوافق مع جميع إعدادات الأجهزة.
النتائج
يظل تطبيقك في الوضع العمودي على الشاشات الصغيرة بغض النظر عن تدوير الجهاز. على الشاشات الكبيرة، يتيح التطبيق استخدام الاتجاهَين الأفقي والعمودي.
إدارة اتجاه التطبيق
لتفعيل الوضع الأفقي على الشاشات الكبيرة، اضبط بيان التطبيق على التعامل مع تغييرات الاتجاه تلقائيًا. تحديد حجم نافذة التطبيق في وقت التشغيل إذا كانت نافذة التطبيق صغيرة، يمكنك حصر اتجاه التطبيق من خلال تجاهل إعداد الاتجاه في ملف البيان.
1. تحديد إعداد اتجاه الشاشة في بيان التطبيق
يمكنك إما تجنُّب تعريف العنصر screenOrientation
في ملف بيان التطبيق (وفي هذه الحالة، يتم ضبط اتجاه الشاشة تلقائيًا على unspecified
) أو ضبط اتجاه الشاشة على fullUser
. إذا لم يفعّل المستخدم قفل التدوير المستند إلى المستشعر، سيتوافق تطبيقك مع جميع اتجاهات الجهاز.
<activity
android:name=".MyActivity"
android:screenOrientation="fullUser">
الفرق بين unspecified
وfullUser
بسيط ولكنه مهم. إذا لم تحدّد قيمة screenOrientation
، سيختار النظام اتجاه الشاشة، وقد تختلف السياسة التي يستخدمها النظام لتحديد اتجاه الشاشة من جهاز إلى آخر. من ناحية أخرى، يحدّد الخيار fullUser
المطابقات
بشكل أكثر دقة السلوك الذي حدّده المستخدم للجهاز: إذا كان المستخدم قد
أوقف التدوير المستند إلى المستشعر، يتبع التطبيق الإعداد المفضّل للمستخدم، وإلا
سيسمح النظام بأي من اتجاهات الشاشة الأربعة الممكنة (عمودي أو أفقي أو عمودي معكوس أو أفقي معكوس). يمكنك الاطّلاع على screenOrientation
.
2- تحديد حجم الشاشة
عند ضبط ملف البيان على إتاحة جميع الاتجاهات التي يسمح بها المستخدم، يمكنك تحديد اتجاه التطبيق آليًا استنادًا إلى حجم الشاشة.
أضِف مكتبات Jetpack WindowManager إلى ملف build.gradle
أو build.gradle.kts
الخاص بالوحدة:
Kotlin
implementation("androidx.window:window:version
") implementation("androidx.window:window-core:version
")
Groovy
implementation 'androidx.window:window:version
' implementation 'androidx.window:window-core:version
'
استخدِم طريقة WindowMetricsCalculator#computeMaximumWindowMetrics()
في Jetpack WindowManager للحصول على حجم شاشة الجهاز كعنصر WindowMetrics
. يمكن مقارنة مقاييس النافذة بفئات أحجام النوافذ لتحديد وقت حظر الاتجاه.
توفّر فئات حجم النوافذ نقاط التوقف بين الشاشات الصغيرة والكبيرة.
استخدِم نقاط التوقّف WindowWidthSizeClass#COMPACT
وWindowHeightSizeClass#COMPACT
لتحديد حجم الشاشة:
Kotlin
/** Determines whether the device has a compact screen. **/ fun compactScreen() : Boolean { val metrics = WindowMetricsCalculator.getOrCreate().computeMaximumWindowMetrics(this) val width = metrics.bounds.width() val height = metrics.bounds.height() val density = resources.displayMetrics.density val windowSizeClass = WindowSizeClass.compute(width/density, height/density) return windowSizeClass.windowWidthSizeClass == WindowWidthSizeClass.COMPACT || windowSizeClass.windowHeightSizeClass == WindowHeightSizeClass.COMPACT }
Java
/** Determines whether the device has a compact screen. **/ private boolean compactScreen() { WindowMetrics metrics = WindowMetricsCalculator.getOrCreate().computeMaximumWindowMetrics(this); int width = metrics.getBounds().width(); int height = metrics.getBounds().height(); float density = getResources().getDisplayMetrics().density; WindowSizeClass windowSizeClass = WindowSizeClass.compute(width/density, height/density); return windowSizeClass.getWindowWidthSizeClass() == WindowWidthSizeClass.COMPACT || windowSizeClass.getWindowHeightSizeClass() == WindowHeightSizeClass.COMPACT; }
- ملاحظة:
- يتم تنفيذ الأمثلة كطُرق لنشاط معيّن، وبالتالي يتم إلغاء الإشارة إلى النشاط كـ
this
في وسيطcomputeMaximumWindowMetrics()
. - يتم استخدام طريقة
computeMaximumWindowMetrics()
بدلاً منcomputeCurrentWindowMetrics()
لأنّه يمكن تشغيل التطبيق في وضع النوافذ المتعددة الذي يتجاهل إعداد اتجاه الشاشة. لا جدوى من تحديد حجم نافذة التطبيق وتجاهل إعداد اتجاه الشاشة ما لم تكن نافذة التطبيق هي شاشة الجهاز بأكملها.
راجِع WindowManager للحصول على تعليمات حول كيفية تعريف التبعيات لإتاحة طريقة computeMaximumWindowMetrics()
في تطبيقك.
3- إلغاء إعداد بيان التطبيق
بعد التأكّد من أنّ الجهاز يتضمّن شاشة صغيرة الحجم، يمكنك استدعاء Activity#setRequestedOrientation()
لتجاوز الإعداد screenOrientation
في ملف البيان:
Kotlin
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) requestedOrientation = if (compactScreen()) ActivityInfo.SCREEN_ORIENTATION_PORTRAIT else ActivityInfo.SCREEN_ORIENTATION_FULL_USER ... // Replace with a known container that you can safely add a // view to where the view won't affect the layout and the view // won't be replaced. val container: ViewGroup = binding.container // Add a utility view to the container to hook into // View.onConfigurationChanged. This is required for all // activities, even those that don't handle configuration // changes. You can't use Activity.onConfigurationChanged, // since there are situations where that won't be called when // the configuration changes. View.onConfigurationChanged is // called in those scenarios. container.addView(object : View(this) { override fun onConfigurationChanged(newConfig: Configuration?) { super.onConfigurationChanged(newConfig) requestedOrientation = if (compactScreen()) ActivityInfo.SCREEN_ORIENTATION_PORTRAIT else ActivityInfo.SCREEN_ORIENTATION_FULL_USER } }) }
Java
@Override protected void onCreate(Bundle savedInstance) { super.onCreate(savedInstanceState); if (compactScreen()) { setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); } else { setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_USER); } ... // Replace with a known container that you can safely add a // view to where the view won't affect the layout and the view // won't be replaced. ViewGroup container = binding.container; // Add a utility view to the container to hook into // View.onConfigurationChanged. This is required for all // activities, even those that don't handle configuration // changes. You can't use Activity.onConfigurationChanged, // since there are situations where that won't be called when // the configuration changes. View.onConfigurationChanged is // called in those scenarios. container.addView(new View(this) { @Override protected void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); if (compactScreen()) { setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); } else { setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_USER); } } }); }
من خلال إضافة منطق إلى الطريقتَين onCreate()
وView.onConfigurationChanged()
، يمكنك الحصول على مقاييس الحد الأقصى للنافذة وتجاوز إعداد الاتجاه كلما تم تغيير حجم النشاط أو نقله بين الشاشات، مثلاً بعد تدوير الجهاز أو عند طي جهاز قابل للطي أو فتحه.
لمزيد من المعلومات حول وقت حدوث تغييرات الإعدادات ومتى تؤدي إلى إعادة إنشاء النشاط، يُرجى الاطّلاع على التعامل مع تغييرات الإعدادات.
النقاط الرئيسية
screenOrientation
: إعداد في بيان التطبيق يتيح لك تحديد طريقة استجابة تطبيقك لتغييرات اتجاه الجهاز- Jetpack WindowManager: مجموعة من المكتبات تتيح لك تحديد حجم نافذة التطبيق ونسبة العرض إلى الارتفاع، وهي متوافقة مع الإصدارات القديمة حتى المستوى 14 من واجهة برمجة التطبيقات
-
Activity#setRequestedOrientation()
: طريقة يمكنك من خلالها تغيير اتجاه التطبيق في وقت التشغيل
المجموعات التي تتضمّن هذا الدليل
يشكّل هذا الدليل جزءًا من مجموعات "الأدلة السريعة" المنسّقة التي تغطي أهدافًا أوسع نطاقًا لتطوير تطبيقات Android، وهي:
