جهت‌گیری برنامه را در تلفن‌ها محدود کنید، اما نه در دستگاه‌های صفحه بزرگ

برنامه شما روی گوشی‌هایی که در حالت عمودی هستند عالی کار می‌کند، بنابراین برنامه را فقط به حالت عمودی محدود کرده‌اید. اما شما فرصتی را می‌بینید که بتوانید کارهای بیشتری را روی صفحه نمایش‌های بزرگ در حالت افقی انجام دهید.

چطور می‌توانید هر دو حالت را داشته باشید—برنامه را در صفحه نمایش‌های کوچک به حالت عمودی محدود کنید، اما در صفحه نمایش‌های بزرگ، حالت افقی را فعال کنید؟

این راهنما یک اقدام موقت است تا زمانی که بتوانید برنامه خود را برای پشتیبانی کامل از تمام پیکربندی‌های دستگاه بهبود بخشید.

نتایج

برنامه شما صرف نظر از چرخش دستگاه، در صفحه نمایش‌های کوچک در جهت عمودی باقی می‌ماند. در صفحه نمایش‌های بزرگ، برنامه از جهت‌های افقی و عمودی پشتیبانی می‌کند.

مدیریت جهت‌گیری برنامه

برای فعال کردن جهت‌گیری افقی در صفحه نمایش‌های بزرگ، مانیفست برنامه خود را طوری تنظیم کنید که به طور پیش‌فرض تغییرات جهت‌گیری را مدیریت کند. در زمان اجرا، اندازه پنجره برنامه را تعیین کنید. اگر پنجره برنامه کوچک است، با لغو تنظیمات جهت‌گیری مانیفست، جهت‌گیری برنامه را محدود کنید.

۱. تنظیمات جهت‌گیری را در مانیفست برنامه مشخص کنید

شما می‌توانید از تعریف عنصر screenOrientation در فایل manifest برنامه خودداری کنید (که در این صورت orientation به صورت پیش‌فرض روی unspecified تنظیم می‌شود) یا screen orientation را روی fullUser تنظیم کنید. اگر کاربر چرخش مبتنی بر حسگر را قفل نکرده باشد، برنامه شما از همه جهت‌گیری‌های دستگاه پشتیبانی خواهد کرد.

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

تفاوت بین unspecified و fullUser ظریف اما مهم است. اگر مقداری برای screenOrientation تعریف نکنید، سیستم جهت را انتخاب می‌کند و سیاستی که سیستم برای تعریف جهت استفاده می‌کند ممکن است از دستگاهی به دستگاه دیگر متفاوت باشد. از سوی دیگر، تعیین fullUser با رفتاری که کاربر برای دستگاه تعریف کرده است، مطابقت بیشتری دارد: اگر کاربر چرخش مبتنی بر حسگر را قفل کرده باشد، برنامه از ترجیح کاربر پیروی می‌کند. در غیر این صورت، سیستم هر یک از چهار جهت ممکن صفحه نمایش (عمودی، افقی، عمودی معکوس یا افقی معکوس) را مجاز می‌داند. به screenOrientation مراجعه کنید.

۲. اندازه صفحه نمایش را تعیین کنید

با تنظیم مانیفست برای پشتیبانی از تمام جهت‌گیری‌های مجاز کاربر، می‌توانید جهت‌گیری برنامه را به صورت برنامه‌نویسی شده بر اساس اندازه صفحه نمایش مشخص کنید.

کتابخانه‌های Jetpack WindowManager را به فایل build.gradle یا build.gradle.kts ماژول اضافه کنید:

کاتلین

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

گرووی

implementation 'androidx.window:window:version'
implementation 'androidx.window:window-core:version'

از متد WindowMetricsCalculator#computeMaximumWindowMetrics() در Jetpack WindowManager برای بدست آوردن اندازه صفحه نمایش دستگاه به عنوان یک شیء WindowMetrics استفاده کنید. معیارهای پنجره را می‌توان با کلاس‌های اندازه پنجره مقایسه کرد تا تصمیم گرفته شود چه زمانی جهت‌گیری را محدود کنید.

کلاس‌های اندازه ویندوز، نقاط شکست بین صفحه نمایش‌های کوچک و بزرگ را فراهم می‌کنند.

برای تعیین اندازه صفحه نمایش از نقاط توقف WindowWidthSizeClass#COMPACT و WindowHeightSizeClass#COMPACT استفاده کنید:

کاتلین

/** 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
}

جاوا

/** 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;
}
    توجه:
  • مثال‌ها به عنوان متدهای یک فعالیت پیاده‌سازی شده‌اند؛ و بنابراین، فعالیت در آرگومان تابع computeMaximumWindowMetrics() به صورت this ارجاع داده می‌شود.
  • متد computeMaximumWindowMetrics() به جای computeCurrentWindowMetrics() استفاده می‌شود، زیرا برنامه می‌تواند در حالت چند پنجره‌ای اجرا شود که تنظیم جهت صفحه نمایش را نادیده می‌گیرد. تعیین اندازه پنجره برنامه و لغو تنظیم جهت گیری هیچ فایده‌ای ندارد، مگر اینکه پنجره برنامه، کل صفحه نمایش دستگاه باشد.

برای دستورالعمل‌های مربوط به اعلان وابستگی‌ها جهت در دسترس قرار دادن متد computeMaximumWindowMetrics() در برنامه‌تان، به WindowManager مراجعه کنید.

۳. تنظیمات مانیفست برنامه را نادیده بگیرید

وقتی تشخیص دادید که دستگاه اندازه صفحه نمایش جمع و جوری دارد، می‌توانید Activity#setRequestedOrientation() برای لغو تنظیم screenOrientation در manifest فراخوانی کنید:

کاتلین

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

جاوا

@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() ، می‌توانید حداکثر معیارهای پنجره را بدست آورید و هر زمان که فعالیت تغییر اندازه می‌دهد یا بین نمایشگرها جابجا می‌شود، مانند بعد از چرخش دستگاه یا وقتی یک دستگاه تاشو تا می‌شود یا باز می‌شود، تنظیمات جهت‌گیری را لغو کنید. برای اطلاعات بیشتر در مورد زمان وقوع تغییرات پیکربندی و زمانی که باعث ایجاد مجدد فعالیت می‌شوند، به Handle configuration changes مراجعه کنید.

نکات کلیدی

  • screenOrientation : تنظیمات مانیفست برنامه که به شما امکان می‌دهد نحوه واکنش برنامه خود را به تغییرات جهت‌گیری دستگاه مشخص کنید.
  • Jetpack WindowManager : مجموعه‌ای از کتابخانه‌ها که به شما امکان می‌دهند اندازه و نسبت ابعاد پنجره برنامه را تعیین کنید؛ سازگار با API سطح ۱۴
  • Activity#setRequestedOrientation() : متدی که با آن می‌توانید جهت‌گیری برنامه را در زمان اجرا تغییر دهید.

مجموعه‌هایی که حاوی این راهنما هستند

این راهنما بخشی از این مجموعه‌های راهنمای سریعِ برگزیده است که اهداف گسترده‌تر توسعه اندروید را پوشش می‌دهد:

برنامه خود را فعال کنید تا از یک تجربه کاربری بهینه در تبلت‌ها، دستگاه‌های تاشو و دستگاه‌های ChromeOS پشتیبانی کند.

سوالی یا بازخوردی دارید؟

به صفحه سوالات متداول ما بروید و درباره راهنماهای سریع اطلاعات کسب کنید یا با ما تماس بگیرید و نظرات خود را با ما در میان بگذارید.
،

برنامه شما روی گوشی‌هایی که در حالت عمودی هستند عالی کار می‌کند، بنابراین برنامه را فقط به حالت عمودی محدود کرده‌اید. اما شما فرصتی را می‌بینید که بتوانید کارهای بیشتری را روی صفحه نمایش‌های بزرگ در حالت افقی انجام دهید.

چطور می‌توانید هر دو حالت را داشته باشید—برنامه را در صفحه نمایش‌های کوچک به حالت عمودی محدود کنید، اما در صفحه نمایش‌های بزرگ، حالت افقی را فعال کنید؟

این راهنما یک اقدام موقت است تا زمانی که بتوانید برنامه خود را برای پشتیبانی کامل از تمام پیکربندی‌های دستگاه بهبود بخشید.

نتایج

برنامه شما صرف نظر از چرخش دستگاه، در صفحه نمایش‌های کوچک در جهت عمودی باقی می‌ماند. در صفحه نمایش‌های بزرگ، برنامه از جهت‌های افقی و عمودی پشتیبانی می‌کند.

مدیریت جهت‌گیری برنامه

برای فعال کردن جهت‌گیری افقی در صفحه نمایش‌های بزرگ، مانیفست برنامه خود را طوری تنظیم کنید که به طور پیش‌فرض تغییرات جهت‌گیری را مدیریت کند. در زمان اجرا، اندازه پنجره برنامه را تعیین کنید. اگر پنجره برنامه کوچک است، با لغو تنظیمات جهت‌گیری مانیفست، جهت‌گیری برنامه را محدود کنید.

۱. تنظیمات جهت‌گیری را در مانیفست برنامه مشخص کنید

شما می‌توانید از تعریف عنصر screenOrientation در فایل manifest برنامه خودداری کنید (که در این صورت orientation به صورت پیش‌فرض روی unspecified تنظیم می‌شود) یا screen orientation را روی fullUser تنظیم کنید. اگر کاربر چرخش مبتنی بر حسگر را قفل نکرده باشد، برنامه شما از همه جهت‌گیری‌های دستگاه پشتیبانی خواهد کرد.

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

تفاوت بین unspecified و fullUser ظریف اما مهم است. اگر مقداری برای screenOrientation تعریف نکنید، سیستم جهت را انتخاب می‌کند و سیاستی که سیستم برای تعریف جهت استفاده می‌کند ممکن است از دستگاهی به دستگاه دیگر متفاوت باشد. از سوی دیگر، تعیین fullUser با رفتاری که کاربر برای دستگاه تعریف کرده است، مطابقت بیشتری دارد: اگر کاربر چرخش مبتنی بر حسگر را قفل کرده باشد، برنامه از ترجیح کاربر پیروی می‌کند. در غیر این صورت، سیستم هر یک از چهار جهت ممکن صفحه نمایش (عمودی، افقی، عمودی معکوس یا افقی معکوس) را مجاز می‌داند. به screenOrientation مراجعه کنید.

۲. اندازه صفحه نمایش را تعیین کنید

با تنظیم مانیفست برای پشتیبانی از تمام جهت‌گیری‌های مجاز کاربر، می‌توانید جهت‌گیری برنامه را به صورت برنامه‌نویسی شده بر اساس اندازه صفحه نمایش مشخص کنید.

کتابخانه‌های Jetpack WindowManager را به فایل build.gradle یا build.gradle.kts ماژول اضافه کنید:

کاتلین

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

گرووی

implementation 'androidx.window:window:version'
implementation 'androidx.window:window-core:version'

از متد WindowMetricsCalculator#computeMaximumWindowMetrics() در Jetpack WindowManager برای بدست آوردن اندازه صفحه نمایش دستگاه به عنوان یک شیء WindowMetrics استفاده کنید. معیارهای پنجره را می‌توان با کلاس‌های اندازه پنجره مقایسه کرد تا تصمیم گرفته شود چه زمانی جهت‌گیری را محدود کنید.

کلاس‌های اندازه ویندوز، نقاط شکست بین صفحه نمایش‌های کوچک و بزرگ را فراهم می‌کنند.

برای تعیین اندازه صفحه نمایش از نقاط توقف WindowWidthSizeClass#COMPACT و WindowHeightSizeClass#COMPACT استفاده کنید:

کاتلین

/** 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
}

جاوا

/** 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;
}
    توجه:
  • مثال‌ها به عنوان متدهای یک فعالیت پیاده‌سازی شده‌اند؛ و بنابراین، فعالیت در آرگومان تابع computeMaximumWindowMetrics() به صورت this ارجاع داده می‌شود.
  • متد computeMaximumWindowMetrics() به جای computeCurrentWindowMetrics() استفاده می‌شود، زیرا برنامه می‌تواند در حالت چند پنجره‌ای اجرا شود که تنظیم جهت صفحه نمایش را نادیده می‌گیرد. تعیین اندازه پنجره برنامه و لغو تنظیم جهت گیری هیچ فایده‌ای ندارد، مگر اینکه پنجره برنامه، کل صفحه نمایش دستگاه باشد.

برای دستورالعمل‌های مربوط به اعلان وابستگی‌ها جهت در دسترس قرار دادن متد computeMaximumWindowMetrics() در برنامه‌تان، به WindowManager مراجعه کنید.

۳. تنظیمات مانیفست برنامه را نادیده بگیرید

وقتی تشخیص دادید که دستگاه اندازه صفحه نمایش جمع و جوری دارد، می‌توانید Activity#setRequestedOrientation() برای لغو تنظیم screenOrientation در manifest فراخوانی کنید:

کاتلین

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

جاوا

@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() ، می‌توانید حداکثر معیارهای پنجره را بدست آورید و هر زمان که فعالیت تغییر اندازه می‌دهد یا بین نمایشگرها جابجا می‌شود، مانند بعد از چرخش دستگاه یا وقتی یک دستگاه تاشو تا می‌شود یا باز می‌شود، تنظیمات جهت‌گیری را لغو کنید. برای اطلاعات بیشتر در مورد زمان وقوع تغییرات پیکربندی و زمانی که باعث ایجاد مجدد فعالیت می‌شوند، به Handle configuration changes مراجعه کنید.

نکات کلیدی

  • screenOrientation : تنظیمات مانیفست برنامه که به شما امکان می‌دهد نحوه واکنش برنامه خود را به تغییرات جهت‌گیری دستگاه مشخص کنید.
  • Jetpack WindowManager : مجموعه‌ای از کتابخانه‌ها که به شما امکان می‌دهند اندازه و نسبت ابعاد پنجره برنامه را تعیین کنید؛ سازگار با API سطح ۱۴
  • Activity#setRequestedOrientation() : متدی که با آن می‌توانید جهت‌گیری برنامه را در زمان اجرا تغییر دهید.

مجموعه‌هایی که حاوی این راهنما هستند

این راهنما بخشی از این مجموعه‌های راهنمای سریعِ برگزیده است که اهداف گسترده‌تر توسعه اندروید را پوشش می‌دهد:

برنامه خود را فعال کنید تا از یک تجربه کاربری بهینه در تبلت‌ها، دستگاه‌های تاشو و دستگاه‌های ChromeOS پشتیبانی کند.

سوالی یا بازخوردی دارید؟

به صفحه سوالات متداول ما بروید و درباره راهنماهای سریع اطلاعات کسب کنید یا با ما تماس بگیرید و نظرات خود را با ما در میان بگذارید.