نمایش محتوا لبه‌به‌لبه در نماها

امتحان کردن روش Compose
Jetpack Compose جعبه‌ابزار واسط کاربر توصیه‌شده برای Android است. با نحوه کار با لبه‌به‌لبه در Compose آشنا شوید.

وقتی کیت توسعه نرم‌افزار ۳۵ یا بالاتر را در دستگاهی که Android 15 یا بالاتر را اجرا می‌کند هدف‌یابی کنید، برنامه‌تان به‌صورت لبه‌به‌لبه نمایش داده می‌شود. پنجره با رسم در پشت نوارهای سیستم، کل عرض و ارتفاع نمایشگر را دربرمی‌گیرد. نوارهای سیستم شامل نوار وضعیت، نوار عنوان، و نوار پیمایش می‌شود.

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

بسیاری از برنامه‌ها نوار برنامه پایین یا نوار پیمایش پایین نیز دارند. این نوارها باید تا لبه پایین صفحه‌نمایش نیز کشیده شوند و در پشت نوار پیمایش نمایش داده شوند. درغیراین‌صورت، برنامه‌ها باید محتوای پیمایشی را در پشت نوار پیمایش نشان دهند.

شکل ۱. نوارهای سیستم در چیدمان لبه‌به‌لبه.

هنگام پیاده‌سازی چیدمان لبه‌به‌لبه در برنامه‌تان، موارد زیر را درنظر داشته باشید:

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

فعال کردن نمایش لبه‌به‌لبه

اگر برنامه شما کیت توسعه نرم‌افزار ۳۵ یا جدیدتر را هدف‌یابی می‌کند، لبه‌به‌لبه به‌طور خودکار برای دستگاه‌های Android 15 یا جدیدتر فعال می‌شود.

برای فعال کردن لبه‌به‌لبه در نسخه‌های قبلی Android، به‌صورت دستی enableEdgeToEdge را در onCreate از Activity خود فراخوانی کنید.

کاتلین

 override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)
         WindowCompat.enableEdgeToEdge(window)
        ...
      }

جاوا

 @Override
      protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        WindowCompat.enableEdgeToEdge(getWindow());
        ...
      }

به‌طور پیش‌فرض، enableEdgeToEdge() نوارهای سیستم را شفاف می‌کند، به‌جز در حالت پیمایش ۳دکمه‌ای که نوار پیمایش یک لایه نیمه‌شفاف دریافت می‌کند. رنگ‌های نمادهای سیستم و پرده براساس زمینه روشن یا تیره سیستم تنظیم می‌شود.

برای فعال کردن نمایش لبه‌به‌لبه در برنامه‌تان بدون استفاده از تابع enableEdgeToEdge()، راه‌اندازی دستی نمایش لبه‌به‌لبه را ببینید.

مدیریت هم‌پوشانی‌ها بااستفاده از حاشیه‌ها

ممکن است برخی‌از نماهای برنامه‌تان در پشت نوارهای سیستم رسم شود، همان‌طور که در شکل ۳ نشان داده شده است.

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

انواع تورفتگی‌هایی که برای نمایش لبه‌به‌لبه برنامه‌تان اعمال می‌شود عبارت‌اند از:

  • درج‌های نوارهای سیستم: بهترین گزینه برای نماهایی که قابل‌تک‌ضرب زدن هستند و نباید به‌صورت بصری توسط نوارهای سیستم پوشانده شوند.

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

  • درج‌های اشاره سیستم: برای نواحی پیمایش اشاره‌ای که سیستم از آن‌ها استفاده می‌کند و نسبت‌به برنامه شما اولویت دارند.

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

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

برای مثال، دکمه کنش شناور (FAB) در شکل ۳ تاحدی توسط نوار پیمایش پوشانده شده است:

نمونه‌ای از اجرای لبه‌به‌لبه، اما نوار پیمایش دکمه کنش شناور را پوشانده است
شکل ۳. نوار پیمایش که روی دکمه کنش شناور در چیدمان لبه‌تالبه قرار گرفته است.

برای جلوگیری از این نوع هم‌پوشانی دیداری در حالت اشاره یا حالت دکمه، می‌توانید حاشیه‌های نما را بااستفاده از getInsets(int) با WindowInsetsCompat.Type.systemBars() افزایش دهید.

نمونه کد زیر نحوه پیاده‌سازی تورفتگی‌های نوار سیستم را نشان می‌دهد:

کاتلین

ViewCompat.setOnApplyWindowInsetsListener(fab) { v, windowInsets ->
  val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
  // Apply the insets as a margin to the view. This solution sets
  // only the bottom, left, and right dimensions, but you can apply whichever
  // insets are appropriate to your layout. You can also update the view padding
  // if that's more appropriate.
  v.updateLayoutParams<MarginLayoutParams> {
      leftMargin = insets.left
      bottomMargin = insets.bottom
      rightMargin = insets.right
  }

  // Return CONSUMED if you don't want the window insets to keep passing
  // down to descendant views.
  WindowInsetsCompat.CONSUMED
}

جاوا

ViewCompat.setOnApplyWindowInsetsListener(fab, (v, windowInsets) -> {
  Insets insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars());
  // Apply the insets as a margin to the view. This solution sets only the
  // bottom, left, and right dimensions, but you can apply whichever insets are
  // appropriate to your layout. You can also update the view padding if that's
  // more appropriate.
  MarginLayoutParams mlp = (MarginLayoutParams) v.getLayoutParams();
  mlp.leftMargin = insets.left;
  mlp.bottomMargin = insets.bottom;
  mlp.rightMargin = insets.right;
  v.setLayoutParams(mlp);

  // Return CONSUMED if you don't want the window insets to keep passing
  // down to descendant views.
    return WindowInsetsCompat.CONSUMED;
});

اگر این راه‌حل را برای مثال نشان‌داده‌شده در شکل ۳ اعمال کنید، همان‌طور که در شکل ۴ نشان داده شده است، در حالت دکمه هم‌پوشانی بصری وجود نخواهد داشت:

نوار پیمایش نیمه‌شفافی که دکمه اقدام شناور را نمی‌پوشاند
شکل ۴. درحال حل کردن هم‌پوشانی دیداری در حالت دکمه.

همین امر برای حالت پیمایش اشاره‌ای نیز صدق می‌کند، همان‌طور که در شکل ۵ نشان داده شده است:

لبه‌به‌لبه با پیمایش اشاره‌ای
شکل ۵. درحال حل کردن هم‌پوشانی دیداری در حالت پیمایش اشاره‌ای.

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

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

برای مثال، بسیاری از صفحه‌های برنامه فهرستی از موارد را نشان می‌دهند. موارد فهرست را با برش نمایشگر یا نوارهای سیستم نپوشانید.

کاتلین

ViewCompat.setOnApplyWindowInsetsListener(binding.recyclerView) { v, insets ->
  val bars = insets.getInsets(
    WindowInsetsCompat.Type.systemBars()
      or WindowInsetsCompat.Type.displayCutout()
  )
  v.updatePadding(
    left = bars.left,
    top = bars.top,
    right = bars.right,
    bottom = bars.bottom,
  )
  WindowInsetsCompat.CONSUMED
}

جاوا

ViewCompat.setOnApplyWindowInsetsListener(mBinding.recyclerView, (v, insets) -> {
  Insets bars = insets.getInsets(
    WindowInsetsCompat.Type.systemBars()
    | WindowInsetsCompat.Type.displayCutout()
  );
  v.setPadding(bars.left, bars.top, bars.right, bars.bottom);
  return WindowInsetsCompat.CONSUMED;
});

مقدار WindowInsetsCompat را با گرفتن یا منطقی نوار سیستم و انواع برش نمایشگر تعیین کنید.

clipToPadding را روی RecyclerView تنظیم کنید تا لایه حائل با موارد فهرست پیمایش شود. این کار به موارد اجازه می‌دهد وقتی کاربر پیمایش می‌کند، به پشت نوارهای سیستم بروند، همان‌طور که در مثال زیر نشان داده شده است.

<androidx.recyclerview.widget.RecyclerView
    android:id="@+id/recycler_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:clipToPadding="false"
    app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />

درج‌های اشاره سیستم

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

نمونه‌ای از درج‌های اشاره سیستم
شکل ۶. درج‌های اشاره سیستم.

مانند تورفتگی‌های نوار سیستم، می‌توانید از هم‌پوشانی تورفتگی‌های اشاره سیستم جلوگیری کنید بااستفاده از getInsets(int) با WindowInsetsCompat.Type.systemGestures().

از این تورفتگی‌ها برای جابه‌جا کردن یا فاصله‌گذاری نماهای تندکشیدنی از لبه‌ها استفاده کنید. موارد استفاده رایج شامل برگه‌های پایین، تند کشیدن در بازی‌ها، و گردونه‌های پیاده‌سازی‌شده بااستفاده از ViewPager2 است.

در Android 10 یا نسخه‌های جدیدتر، حاشیه‌های اشاره سیستم شامل یک حاشیه پایین برای اشاره صفحه اصلی و یک حاشیه چپ و راست برای اشاره‌های برگشت است:

نمونه‌ای از اندازه‌گیری‌های درج اشاره سیستم
شکل ۷. اندازه‌گیری‌های درج اشاره سیستم.

نمونه کد زیر نحوه پیاده‌سازی درج‌های اشاره سیستم را نشان می‌دهد:

کاتلین

ViewCompat.setOnApplyWindowInsetsListener(view) { view, windowInsets ->
    val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemGestures())
    // Apply the insets as padding to the view. Here, set all the dimensions
    // as appropriate to your layout. You can also update the view's margin if
    // more appropriate.
    view.updatePadding(insets.left, insets.top, insets.right, insets.bottom)

    // Return CONSUMED if you don't want the window insets to keep passing down
    // to descendant views.
    WindowInsetsCompat.CONSUMED
}

جاوا

ViewCompat.setOnApplyWindowInsetsListener(view, (v, windowInsets) -> {
    Insets insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemGestures());
    // Apply the insets as padding to the view. Here, set all the dimensions
    // as appropriate to your layout. You can also update the view's margin if
    // more appropriate.
    view.setPadding(insets.left, insets.top, insets.right, insets.bottom);

    // Return CONSUMED if you don't want the window insets to keep passing down
    // to descendant views.
    return WindowInsetsCompat.CONSUMED;
});

اجزای طراحی مواد

بسیاری از مؤلفه‌های طراحی مواد Android مبتنی بر نما (com.google.android.material) به‌طور خودکار تورفتگی‌ها را مدیریت می‌کنند، ازجمله BottomAppBar، BottomNavigationView، NavigationRailView و NavigationView

بااین‌حال، AppBarLayout به‌طور خودکار حاشیه‌های داخلی را مدیریت نمی‌کند. ‫android:fitsSystemWindows="true" را برای مدیریت درج‌های بالا اضافه کنید.

با نحوه مدیریت کردن تورفتگی‌ها با مؤلفه‌های Material در Compose آشنا شوید.

ارسال درج سازگار با نسخه قدیمی

برای متوقف کردن ارسال حاشیه‌ها به نماهای فرزند و جلوگیری از لایه‌گذاری بیش‌ازحد، می‌توانید حاشیه‌ها را بااستفاده از ثابت WindowInsetsCompat.CONSUMED مصرف کنید. بااین‌حال، در دستگاه‌هایی که Android 10 (سطح API‏ ۲۹ و نسخه‌های قدیمی‌تر) را اجرا می‌کنند، پس‌از فراخوانی WindowInsetsCompat.CONSUMED، درج‌ها به هم‌نیاها ارسال نمی‌شوند، که می‌تواند باعث هم‌پوشانی بصری ناخواسته شود.

نمونه ارسال درج خراب
شکل ۸. نمونه ارسال درج شکسته. در Android 10 (سطح API‏ ۲۹) و نسخه‌های قدیمی‌تر، پس‌از اینکه ViewGroup 1 حاشیه‌ها را مصرف می‌کند، حاشیه‌ها به نماهای هم‌نیا ارسال نمی‌شوند و این امر باعث می‌شود TextView 2 با نوار پیمایش سیستم هم‌پوشانی داشته باشد. بااین‌حال، همان‌طور که انتظار می‌رود، در Android نسخه ۱۱ (سطح API‏ ۳۰) و بالاتر، درج‌ها به نماهای هم‌نیا ارسال می‌شوند.

برای تأیید اینکه تورفتگی‌ها برای همه نسخه‌های Android پشتیبانی‌شده به هم‌نیاها ارسال می‌شوند، از ViewGroupCompat#installCompatInsetsDispatch قبل‌از مصرف تورفتگی‌ها استفاده کنید که در AndroidX Core و Core-ktx 1.16.0-alpha01 و نسخه‌های بالاتر دردسترس است.

کاتلین

// Use the i.d. assigned to your layout's root view, e.g. R.id.main
val rootView = findViewById(R.id.main)
// Call before consuming insets
ViewGroupCompat.installCompatInsetsDispatch(rootView)

جاوا

// Use the i.d. assigned to your layout's root view, e.g. R.id.main
LinearLayout rootView = findViewById(R.id.main);
// Call before consuming insets
ViewGroupCompat.installCompatInsetsDispatch(rootView);
نمونه ارسال درج ثابت
شکل ۹. ارسال درج ثابت پس‌از فراخوانی ViewGroupCompat#installCompatInsetsDispatch.

حالت فراگیر

برخی‌از محتواها در حالت تمام‌صفحه بهترین تجربه را ارائه می‌دهند و تجربه فراگیرتری برای کاربر فراهم می‌کنند. می‌توانید نوارهای سیستم را برای حالت فراگیر بااستفاده از کتابخانه‌های WindowInsetsController و WindowInsetsControllerCompat پنهان کنید:

کاتلین

val windowInsetsController =
      WindowCompat.getInsetsController(window, window.decorView)

// Hide the system bars.
windowInsetsController.hide(Type.systemBars())

// Show the system bars.
windowInsetsController.show(Type.systemBars())

جاوا

Window window = getWindow();
WindowInsetsControllerCompat windowInsetsController =
      WindowCompat.getInsetsController(window, window.getDecorView());
if (windowInsetsController == null) {
    return;
  }
// Hide the system bars.
windowInsetsController.hide(WindowInsetsCompat.Type.systemBars());

// Show the system bars.
windowInsetsController.show(WindowInsetsCompat.Type.systemBars());

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

نمادهای نوار سیستم

Calling enableEdgeToEdge ensures system bar icon colors update when the device theme changes.

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

کاتلین

WindowCompat.getInsetsController(window, window.decorView)
    .isAppearanceLightStatusBars = false

جاوا

WindowCompat.getInsetsController(window, window.getDecorView())
    .setAppearanceLightStatusBars(false);

محافظت از نوار سیستم

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

بااین‌حال، پیش‌فرض‌های سیستم ممکن است برای همه موارد استفاده کار نکنند. برای تعیین اینکه از نوارهای سیستم شفاف یا نیمه‌شفاف استفاده کنید، به راهنمای طراحی نوارهای سیستم Android و طراحی لب‌به‌لب مراجعه کنید.

ایجاد نوارهای سیستم شفاف

با هدف‌یابی Android 15 (کیت توسعه نرم‌افزار ۳۵) یا بالاتر یا با فراخوانی enableEdgeToEdge() با آرگومان‌های پیش‌فرض برای نسخه‌های قبلی، نوار وضعیت شفاف ایجاد کنید.

با هدف قرار دادن Android 15 یا بالاتر یا با فراخوانی enableEdgeToEdge() با آرگومان‌های پیش‌فرض برای نسخه‌های قبلی، نوار پیمایش اشاره‌ای شفاف ایجاد کنید. برای نوار پیمایش سه‌دکمه‌ای، Window.setNavigationBarContrastEnforced را روی false تنظیم کنید، درغیراین‌صورت لایه نیمه‌شفافی اعمال خواهد شد.

ایجاد نوارهای سیستم نیمه‌شفاف

برای ایجاد نوار وضعیت نیمه‌شفاف، کارهای زیر را انجام دهید:

  1. وابستگی androidx-core را به 1.16.0-beta01 یا بالاتر به‌روز کنید
  2. طرح‌بندی XML خود را در androidx.core.view.insets.ProtectionLayout بپیچید و شناسه‌ای اختصاص دهید.
  3. برای تنظیم محافظت‌ها، به‌صورت برنامه‌نویسی‌شده به ProtectionLayout دسترسی پیدا کنید و سمت و GradientProtection را برای نوار وضعیت مشخص کنید.

<androidx.core.view.insets.ProtectionLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/list_protection"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ScrollView
        android:id="@+id/item_list"
        android:clipToPadding="false"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <!--items-->

    </ScrollView>

</androidx.core.view.insets.ProtectionLayout>

findViewById<ProtectionLayout>(R.id.list_protection)
    .setProtections(
        listOf(
            GradientProtection(
                WindowInsetsCompat.Side.TOP,
                // Ideally, this is the pane's background color
                paneBackgroundColor
            )
        )
    )

مطمئن شوید ColorInt منتقل‌شده به GradientProtection با پس‌زمینه محتوا مطابقت داشته باشد. برای مثال، چیدمان فهرست-جزئیات که در دستگاه تاشو نمایش داده می‌شود ممکن است GradientProtections متفاوتی با رنگ‌های متفاوت برای پانل فهرست و پانل جزئیات داشته باشد.

شکل ۱. محافظت گرادیان رنگ‌های مختلف.

نوار پیمایش اشاره‌ای نیمه‌شفاف ایجاد نکنید. برای ایجاد نوار پیمایش سه‌دکمه‌ای نیمه‌شفاف، یکی از کارهای زیر را انجام دهید:

  • اگر ازقبل چیدمانتان را در ProtectionView قرار داده‌اید، می‌توانید ColorProtection یا GradientProtection دیگری را به روش setProtections منتقل کنید. قبل‌از انجام این کار، مطمئن شوید window.isNavigationBarContrastEnforced = false.
  • درغیراین‌صورت، window.isNavigationBarContrastEnforced = true را تنظیم کنید.

نکته‌های دیگر

نکات بیشتر هنگام کار با حاشیه‌ها.

لبه‌به‌لبه کردن محتوای پیمایشی

بررسی کنید که آخرین مورد فهرست توسط نوارهای سیستم در RecyclerView یا NestedScrollView با مدیریت تورفتگی‌ها و تنظیم clipToPadding روی false پنهان نشده باشد.

ویدیو زیر RecyclerView را با نمایش لبه‌به‌لبه غیرفعال (سمت راست) و فعال (سمت چپ) نشان می‌دهد:

برای مشاهده نمونه کد، تکه‌کدهای موجود در بخش ایجاد فهرست‌های پویا با RecyclerView را ببینید.

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

برای تمام‌صفحه کردن مکالمه لبه‌به‌لبه، enableEdgeToEdge را در «مکالمه» فراخوانی کنید.

کاتلین

class MyAlertDialogFragment : DialogFragment() {
    override fun onStart(){
        super.onStart()
        dialog?.window?.let { WindowCompat.enableEdgeToEdge(it) }
    }
    ...
}

جاوا

public class MyAlertDialogFragment extends DialogFragment {
    @Override
    public void onStart() {
        super.onStart();
        Dialog dialog = getDialog();
        if (dialog != null) {
            Window window = dialog.getWindow();
            if (window != null) {
                WindowCompat.enableEdgeToEdge(window);
            }
        }
    }
    ...
}

منابع بیشتر

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

وبلاگ‌ها

طراحی

سایر مدارک

ویدیوها