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

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

وقتی کیت توسعه نرم‌افزار ۳۵ یا بالاتر را در دستگاهی که 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 (میانای برنامه‌سازی کاربردی سطح ۲۹ و نسخه‌های قبلی) را اجرا می‌کنند، حاشیه‌ها پس‌از فراخوانی WindowInsetsCompat.CONSUMED به عناصر هم‌سطح ارسال نمی‌شوند، که می‌تواند باعث هم‌پوشانی ناخواسته دیداری شود.

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

برای تأیید اینکه حاشیه‌ها برای همه نسخه‌های پشتیبانی‌شده 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());

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

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

تماس با enableEdgeToEdge تضمین می‌کند که رنگ‌های نماد نوار سیستم هنگام تغییر زمینه دستگاه به‌روزرسانی شود.

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

کاتلین

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

منابع بیشتر

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

وبلاگ‌ها

طراحی

سایر اسناد

ویدیوها