האפליקציה פועלת בצורה מצוינת בטלפונים בתצוגה לאורך, ולכן הגבלת את האפליקציה לתצוגה לאורך בלבד. אבל אתם רואים הזדמנות לעשות יותר במסכים גדולים במצב אופקי.
איך אפשר להגביל את האפליקציה לכיוון לאורך במסכים קטנים, אבל לאפשר כיוון לרוחב במסכים גדולים?
המדריך הזה הוא אמצעי זמני עד שתשפרו את האפליקציה כדי לספק תמיכה מלאה בכל תצורות המכשירים.
תוצאות
האפליקציה שלך נשארת בפריסה לאורך במסכים קטנים, ללא קשר לסיבוב המכשיר. במסכים גדולים, האפליקציה תומכת בכיווני מסך לרוחב ולאורך.
ניהול הכיוון של האפליקציה
כדי להפעיל את הכיוון לרוחב במסכים גדולים, צריך להגדיר במניפסט של האפליקציה שהאפליקציה תטפל בשינויים בכיוון כברירת מחדל. בזמן הריצה, קובעים את הגודל של חלון האפליקציה. אם חלון האפליקציה קטן, אפשר להגביל את כיוון האפליקציה על ידי שינוי ההגדרה של כיוון המסך במניפסט.
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
'
משתמשים בשיטה Jetpack WindowManager
WindowMetricsCalculator#computeMaximumWindowMetrics()
כדי לקבל את גודל המסך של המכשיר כאובייקט WindowMetrics
. אפשר להשוות את מדדי החלון לסיווגים של גודל החלון כדי להחליט מתי להגביל את הכיוון.
סיווגי גודל של חלונות מספקים את נקודות העצירה בין מסכים קטנים לגדולים.
משתמשים בנקודות עצירה (breakpoints) 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()
כי אפשר להפעיל את האפליקציה במצב ריבוי חלונות, שמתעלם מההגדרה של כיוון המסך. אין טעם לקבוע את גודל חלון האפליקציה ולבטל את הגדרת הכיוון, אלא אם חלון האפליקציה הוא המסך כולו של המכשיר.
הוראות להצהרה על תלות כדי שהשיטה computeMaximumWindowMetrics()
תהיה זמינה באפליקציה מופיעות במאמר בנושא WindowManager.
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: קבוצה של ספריות שמאפשרות לקבוע את הגודל ויחס הגובה-רוחב של חלון האפליקציה. יש תאימות לאחור עד לרמת API 14
-
Activity#setRequestedOrientation()
: שיטה שבעזרתה אפשר לשנות את כיוון האפליקציה בזמן הריצה
אוספים שכוללים את המדריך הזה
המדריך הזה הוא חלק מאוספים של מדריכים מהירים שנבחרו בקפידה ועוסקים ביעדים רחבים יותר של פיתוח ל-Android:
