להגביל את הכיוון של האפליקציה בטלפונים, אבל לא במכשירים עם מסך גדול

האפליקציה פועלת בצורה מצוינת בטלפונים בתצוגה לאורך, ולכן הגבלת את האפליקציה לתצוגה לאורך בלבד. אבל אתם רואים הזדמנות לעשות יותר במסכים גדולים במצב אופקי או במכשירים מתקפלים במצב פתוח.

איך אפשר להגביל את האפליקציה לתצוגה לאורך במסך החיצוני של מכשירים מתקפלים, אבל לאפשר תצוגה לרוחב במסך הפנימי?

המדריך הזה הוא אמצעי זמני עד שתשפרו את האפליקציה כדי לספק תמיכה מלאה בכל תצורות המכשירים.

תוצאות

האפליקציה שלך נשארת בפריסה לאורך במסכים קטנים, ללא קשר לסיבוב המכשיר. במסכים גדולים, האפליקציה תומכת בכיווני מסך לרוחב ולאורך.

תאימות גרסאות

ההטמעה הזו תואמת לכל רמות ה-API.

תלויות

Kotlin

implementation("androidx.window:window:1.5.1")
implementation("androidx.window:window-core:1.5.1")

Groovy

implementation "androidx.window:window:1.5.1"
implementation "androidx.window:window-core:1.5.1"

ניהול הכיוון של האפליקציה

כדי להפעיל את הכיוון לרוחב במסכים גדולים, צריך להגדיר את קובץ מניפסט של אפליקציה כך שיטפל בשינויי כיוון כברירת מחדל. בזמן הריצה, קובעים את גודל חלון האפליקציה. אם חלון האפליקציה קטן, אפשר להגביל את כיוון האפליקציה על ידי שינוי ההגדרה של כיוון המניפסט.

1. ציון הגדרת הכיוון בקובץ מניפסט של אפליקציה

אפשר להימנע מהצהרה על רכיב screenOrientation במניפסט של האפליקציה (במקרה כזה, כיוון המסך מוגדר כברירת מחדל ל-unspecified) או להגדיר את כיוון המסך ל-fullUser. אם המשתמש לא נעל את הסיבוב שמבוסס על חיישן, האפליקציה שלכם תתמוך בכל כיווני המכשיר.

<activity
    android:name=".MyActivity"
    android:screenOrientation="fullUser">

ההבדל בין unspecified לבין fullUser הוא קטן אבל חשוב. אם לא מצהירים על ערך של screenOrientation, המערכת בוחרת את הכיוון, והמדיניות שהמערכת משתמשת בה כדי להגדיר את הכיוון עשויה להיות שונה ממכשיר למכשיר.

לעומת זאת, אם מציינים fullUser, ההתנהגות תהיה דומה יותר למה שהמשתמש הגדיר למכשיר: אם המשתמש נעל את הסיבוב שמבוסס על חיישן, האפליקציה תפעל לפי ההעדפה של המשתמש. אחרת, המערכת תאפשר כל אחת מארבע האפשרויות האפשריות של כיוון המסך (לאורך, לרוחב, לאורך הפוך או לרוחב הפוך).

בנוסף, אפשר להשתמש ב-nosensor כדי לקבוע את הכיוון בלי להתחשב בנתוני החיישן, אבל הקוד הבא יפעל באותו אופן. מידע נוסף מפורט ב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) WindowSizeClass#minWidthDp ו-WindowSizeClass#minHeightDp כדי לקבוע את גודל המסך:

/** 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 =
        BREAKPOINTS_V1.computeWindowSizeClass(width / density, height / density)
    return windowSizeClass.minWidthDp == 0
}
    הערה:
  • הדוגמאות מיושמות כשיטות של פעילות, ולכן הפעילות מבוטלת כ-this בארגומנט של computeMaximumWindowMetrics().
  • השיטה computeMaximumWindowMetrics() משמשת במקום computeCurrentWindowMetrics() כי אפשר להפעיל את האפליקציה במצב ריבוי חלונות, שמתעלם מההגדרה של כיוון המסך. אין טעם לקבוע את גודל חלון האפליקציה ולבטל את הגדרת הכיוון, אלא אם חלון האפליקציה הוא המסך כולו של המכשיר.

הוראות להצהרה על תלות כדי שהשיטה computeMaximumWindowMetrics() תהיה זמינה באפליקציה מופיעות במאמר בנושא WindowManager.

3. שינוי ההגדרה של קובץ המניפסט של האפליקציה

אחרי שקובעים שלמכשיר יש מסך קומפקטי, אפשר להתקשר אל Activity#setRequestedOrientation() כדי לבטל את ההגדרה screenOrientation בקובץ המניפסט:

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

הוספת הלוגיקה לשיטות onCreate() ו-View.onConfigurationChanged() מאפשרת לקבל את מדדי החלון המקסימליים ולשנות את הגדרת הכיוון בכל פעם שגודל הפעילות משתנה או שהיא מועברת בין מסכים, למשל אחרי סיבוב המכשיר או כשמכשיר מתקפל נפתח או נסגר. מידע נוסף על מקרים שבהם מתבצעים שינויים בהגדרות ועל מקרים שבהם השינויים גורמים ליצירה מחדש של פעילות זמין במאמר טיפול בשינויים בהגדרות.

אם אתם משתמשים ב-Jetpack פיתוח נייטיב, אתם יכולים להשתמש באותה פונקציה compactScreen() ב-Composable הבסיסי של האפליקציה כדי להשיג את אותה התוצאה.

נקודות עיקריות

  • screenOrientation: הגדרה בקובץ המניפסט של האפליקציה שמאפשרת לציין איך האפליקציה מגיבה לשינויים באוריינטציה של המכשיר
  • Jetpack WindowManager: קבוצה של ספריות שמאפשרות לקבוע את הגודל ויחס הגובה-רוחב של חלון האפליקציה. יש תאימות לאחור עד לרמת API‏ 14
  • Activity#setRequestedOrientation(): שיטה שבעזרתה אפשר לשנות את כיוון האפליקציה בזמן הריצה

אוספים שכוללים את המדריך הזה

המדריך הזה הוא חלק מאוספים של מדריכים מהירים שנבחרו בקפידה ועוסקים ביעדים רחבים יותר של פיתוח ל-Android:

כדאי להפעיל באפליקציה תמיכה בחוויית משתמש אופטימלית בטאבלטים, במכשירים מתקפלים ובמכשירי ChromeOS.

יש לך שאלות או משוב?

אפשר לעבור לדף השאלות הנפוצות שלנו כדי לקרוא מדריכים מהירים, או לפנות אלינו ולספר לנו מה דעתך.