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

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

هنگامی که SDK 35 یا بالاتر را در دستگاهی با Android 15 یا بالاتر هدف قرار دهید، برنامه شما لبه به لبه نمایش داده می شود. پنجره با کشیدن پشت نوارهای سیستم، تمام عرض و ارتفاع نمایشگر را در بر می گیرد. نوارهای سیستم شامل نوار وضعیت، نوار شرح و نوار ناوبری است.

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

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

شکل 1. میله های سیستم در یک طرح لبه به لبه.

هنگام اجرای طرح بندی لبه به لبه در برنامه خود، موارد زیر را در نظر داشته باشید:

  1. نمایش لبه به لبه را فعال کنید
  2. هرگونه همپوشانی بصری را مدیریت کنید.
  3. نمایش scrims در پشت میله های سیستم را در نظر بگیرید.
نمونه ای از تصاویر پشت نوار وضعیت
شکل 2. نمونه ای از تصاویر پشت نوار وضعیت.

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

اگر برنامه شما SDK 35 یا بالاتر را هدف قرار می دهد، لبه به لبه به طور خودکار برای دستگاه های Android 15 یا بالاتر فعال می شود.

برای فعال کردن لبه به لبه در نسخه‌های قبلی اندروید، موارد زیر را انجام دهید:

  1. یک وابستگی به کتابخانه androidx.activity در فایل build.gradle برنامه یا ماژول خود اضافه کنید:

    کاتلین

    dependencies {
        val activity_version = activity_version
        // Java language implementation
        implementation("androidx.activity:activity:$activity_version")
        // Kotlin
        implementation("androidx.activity:activity-ktx:$activity_version")
    }

    شیار

    dependencies {
        def activity_version = activity_version
        // Java language implementation
        implementation 'androidx.activity:activity:$activity_version'
        // Kotlin
        implementation 'androidx.activity:activity-ktx:$activity_version'
    }
  2. تابع افزونه enableEdgeToEdge را به برنامه خود وارد کنید:

با فراخوانی enableEdgeToEdge در onCreate of your Activity ، لبه به لبه را به صورت دستی فعال کنید. باید قبل از setContentView فراخوانی شود.

کاتلین

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

جاوا

     @Override
     protected void onCreate(@Nullable Bundle savedInstanceState) {
       EdgeToEdge.enable(this);
       super.onCreate(savedInstanceState);
       ...
     }
   

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

تابع enableEdgeToEdge() به طور خودکار اعلام می کند که برنامه باید لبه به لبه قرار گیرد و رنگ نوارهای سیستم را تنظیم می کند.

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

همپوشانی ها را با استفاده از درپوش ها کنترل کنید

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

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

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

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

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

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

درج میله های سیستم

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

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

نمونه ای از لبه به لبه پیاده سازی شده است، اما نوار ناوبری FAB را پوشش می دهد
شکل 3. نوار ناوبری که روی یک 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 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 want the window insets to keep passing
  // down to descendant views.
    return WindowInsetsCompat.CONSUMED;
});

اگر این راه حل را برای مثال نشان داده شده در شکل 3 اعمال کنید، همانطور که در شکل 4 نشان داده شده است، هیچ همپوشانی بصری در حالت دکمه ایجاد نمی شود:

یک نوار ناوبری شفاف که FAB را نمی پوشاند
شکل 4. حل همپوشانی بصری در حالت دکمه.

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

لبه به لبه با ناوبری ژست
شکل 5. حل همپوشانی بصری در حالت ناوبری حرکتی.

نمایش ورودی های برش

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

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

کاتلین

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" />

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

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

نمونه ای از ژست های درونی سیستم
شکل 6. درج حرکات سیستم.

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

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

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

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

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

کاتلین

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){:.external} به طور خودکار از جمله BottomAppBar ، BottomNavigationView ، NavigationRailView و NavigationView استفاده می‌کنند.

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

نحوه مدیریت inset ها با Material Components را در Compose بخوانید.

حالت فراگیر

برخی از محتواها به بهترین وجه در تمام صفحه تجربه می شوند و تجربه ای فراگیرتر را به کاربر می دهند. می توانید با استفاده از کتابخانه های 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());

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

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

هنگامی که برنامه شما SDK 35 یا بالاتر را هدف قرار می دهد، لبه به لبه اجرا می شود . نوار وضعیت سیستم و نوارهای پیمایش حرکتی شفاف هستند، اما نوار ناوبری سه دکمه شفاف است.

برای حذف حفاظت پیش‌فرض ناوبری سه دکمه‌ای شفاف، Window.setNavigationBarContrastEnforced را روی false تنظیم کنید.

منابع اضافی

برای اطلاعات بیشتر در مورد WindowInsets ، پیمایش اشاره‌ای و نحوه عملکرد insets به مراجع زیر مراجعه کنید: