شیت یک کامپوننت UI است که در بخش پایین صفحه بالای محتوای اصلی ظاهر شده و اقدامات یا اطلاعات اضافی ارائه میدهد. Bottom Sheet رایجترین نوع است که در راهنمای Material Design 3 (Google, 2024) تعریف شده است. به پنجرههای دیالوگ در تعارض، Sheet تعامل با پسزمینه را به طور کامل مسدود نمیکند و از وضعیتهای collapsed و expanded پشتیبانی میکند. درک انواع و رفتار Sheet برای ساخت ناوبری راحت در نرم افزارهای موبایل ضروری است.
نکات کلیدی
Sheet — یک کامپوننت سطحی UI است که از پایین صفحه خارج شده و محتوای اضافی یا اقداماتی را بدون انتقال کاربر از صفحه فعلی نمایش میدهد. به انتقالهای تمامصفحه در تعارض، Sheet زمینه را حفظ میکند: کاربر صفحه پسزمینه را میبیند و متوجه میشود که Sheet از کجا ظاهر شده است.
معماری Sheet بر پایه کانتینری با ارتفاع قابل تغییر است. در حالت حداقل (collapsed) تنها بخشی از محتوا قابل مشاهده است — معمولاً عنوان یا پانل کوچک. کاربر میتواند Sheet را به بالا بکشد تا آن را باز کند (expanded) یا به پایین بکشد تا آن را ببندد. این رفتار یادآور یک برگ کاغذ است که از زیر یک دسته خارج میشود — از اینجا نام آن گرفته شده است.
Google در راهنمای Material Design 3 (2024) دو سناریوی کلیدی برای استفاده از Sheet را مشخص کرده است: نمایش اقدامات اضافی که در نوار ابزار اصلی جا نگرفتهاند و نمایش فرمها یا اطلاعات جزئیات بدون انتقال به صفحه جداگانه. Apple از iOS 15 به بعد از طریق UISheetPresentationController پشتیبانی سیستمی Sheet را اضافه کرده است که جهانی بودن این الگو را تایید میکند.
Material Design سه نوع Bottom Sheet را تعریف میکند که هر کدام رفتار و زمینه کاربردی خاص خود را دارند. انتخاب نوع مناسب مستقیماً بر تجربه کاربر و مطابقت با راهنمای پلتفرم تأثیر میگذارد.
Bottom Sheet استاندارد — یک کامپوننت غیرمادال: کاربر میتواند بدون بستن Sheet با صفحه پسزمینه تعامل کند. به عنوان مثال، هنگامی که کاربر لیست محصولات را در پنجره پسزمینه مرور میکند، فیلترها را در Bottom Sheet میبیند و میتواند بدون بستن پانل آنها را تغییر دهد. Sheet ارتفاع خود را با محتوا تنظیم میکند — از 30% تا 90% صفحه.
Bottom Sheet استاندارد پسزمینه را مسدود نمیکند و با محتوای اصلی تعامل را ممکن میسازد. این تفاوت کلیدی با Sheet مادال است که برای ادامه کار نیاز به اقدام اجباری دارد. زمانی از Sheet استاندارد استفاده کنید که اطلاعات اضافی برای سناریوی اصلی حیاتی نباشد.
Bottom Sheet مادال تا زمانی که کاربر درون Sheet اقدامی انجام ندهد، تعامل با صفحه پسزمینه را مسدود میکند. چنین Sheet همواره در وضعیت expanded نمایش داده میشود و نیاز به بستن صریح دارد — از طریق دکمه، اقدام یا کشیدن به پایین. Material Design برای فرمهای ورود، تاییدیهها و تنظیمات حیاتی از Sheet مادال استفاده میکند.
در Android، Bottom Sheet مادال از طریق BottomSheetDialogFragment پیادهسازی میشود که به طور خودکار پسزمینه را مسدود میکند. در iOS رفتار مشابهی توسط نسخه مادال UISheetPresentationController با پارامتر .mediumDetent ارائه میشود. Sheet مادال تنها زمانی باید استفاده شود که زمینه نیازمند توجه کاربر باشد.
Bottom Sheet گسترده ویژگیهای استاندارد و مادال را ترکیب میکند: در وضعیت collapsed به صورت غیرمادال شروع میشود، اما با کشیدن به بالا مادال میشود. در عمل، این به آن معنی است که کاربر میتواند ابتدا نگاهی به محتوا بیندازد و سپس تصمیم بگیرد که Sheet را برای بررسی جزئیات باز کند یا ببندد.
این الگو به ویژه در نقشهها و مسیریابها محبوب است، جایی که پانل پایین اطلاعات کوتاهی درباره نقطه مسیر را نشان میدهد و با کشیدن به بالا با جزئیات باز میشود. Google Maps از این نوع Sheet گسترده برای نمایش اطلاعات مکانها و مسیرها استفاده میکند.
| نوع Sheet | مسدودسازی پسزمینه | وضعیت اولیه | مثال |
|---|---|---|---|
| استاندارد | خیر | Collapsed | فیلترها در کاتالوگ |
| مادال | بلی | Expanded | فرم ورود |
| گسترده | به صورت جزئی | Collapsed | کارت مکان |
Android SDK چندین API برای پیادهسازی Bottom Sheet از رویکرد کلاسیک View تا Jetpack Compose مدرن ارائه میدهد. Material Components Library برای Android شامل پیادهسازیهای آماده BottomSheetDialogFragment و BottomSheetBehavior است.
BottomSheetBehavior — یک کلاس از Material Components است که به هر View متصل شده و موقعیت آن را در صفحه مدیریت میکند. توسعهدهنده سه وضعیت تعیین میکند: STATE_COLLAPSED (بسته)، STATE_EXPANDED (باز) و STATE_HIDDEN (مخفی). Behavior به طور خودکار جستهای کشیدن و انیمیشن را مدیریت میکند.
val sheet = findViewById<View>(R.id.bottom_sheet)
val behavior = BottomSheetBehavior.from(sheet)
behavior.state = BottomSheetBehavior.STATE_COLLAPSED
behavior.peekHeight = 200
Jetpack Compose از طریق کامپوننت ModalBottomSheet از Material 3 API دکلاراتیوهتری ارائه میدهد. به رویکرد View در تعارض، در Compose Bottom Sheet یک تابع composable است که وضعیت و محتوا را میپذیرد. Sheet به طور خودکار ظاهر شدن، مخفی شدن و تغییر ارتفاع در حین کشیدن را انیمیت میدهد.
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun FilterSheet(onDismiss: () -> Unit) {
ModalBottomSheet(onDismissRequest = onDismiss) {
Text("فیلترها")
Button(onClick = onDismiss) { Text("اعمال") }
}
}
BottomSheetDialogFragment — یک DialogFragment تخصصی است که به صورت Bottom Sheet نمایش داده میشود. آن به طور خودکار مادال بودن، چرخه حیات و تغییرات پیکربندی را مدیریت میکند. توسعهدهنده تنها نیاز به لغو onCreateView و بازگرداندن layout Sheet را دارد. بر اساس مستندات Google (Android Developers, 2024)، BottomSheetDialogFragment روش توصیه شده برای Bottom Sheet های مادال در Android کلاسیک است.
Apple از iOS 15 به بعد از طریق UISheetPresentationController پشتیبانی سیستمی Sheet را اضافه کرده است. پیش از آن، توسعهدهندگان Bottom Sheet را به صورت دستی از طریق custom transition یا کتابخانههای شخص ثالث پیاده میکردند. Sheet خود Apple از detents — سطوح از پیش تعریف شده بازشدگی پشتیبانی میکند.
UISheetPresentationController — یک کنترلر ارائه داخلی است که View Controller را به عنوان Sheet نمایش میدهد. توسعهدهنده یک مجموعه از detents — مقادیر ارتفاع که Sheet میتواند در آن بایستد تعیین میکند. iOS 16 detents سفارشی با ارتفاع دلخواه را اضافه کرده است. Apple استفاده از medium (.medium) و large (.large) detents را به عنوان اصلی توصیه میکند.
let viewController = MySheetViewController()
if let sheet = viewController.sheetPresentationController {
sheet.detents = [.medium, .large]
sheet.prefersGrabberVisible = true
sheet.preferredCornerRadius = 16
}
present(viewController, animated: true)
SwiftUI مودیفایر .sheet را ارائه میدهد که نمایش Sheet را به وضعیت متصل میکند. وقتی متغیر published true میشود، SwiftUI به طور خودکار Sheet را نمایش میدهد. SwiftUI همچنین از detents از طریق مودیفایر .presentationDetents اضافه شده در iOS 16 پشتیبانی میکند.
struct ContentView: View {
@State private var showSheet = false
var body: some View {
Button("نمایش Sheet") { showSheet = true }
.sheet(isPresented: $showSheet) {
FilterView()
.presentationDetents([.medium, .large])
}
}
}
چارچوبهای چندسیستمی نیز از Bottom Sheet پشتیبانی میکنند و رفتار را با پلتفرم هدف سازگار میکنند. Flutter و React Native پیادهسازیهای داخلی و سفارشی با درجات مختلف انعطافپذیری ارائه میدهند.
Flutter SDK شامل دو روش برای نمایش Bottom Sheet است: showBottomSheet (استاندارد) و showModalBottomSheet (مادال). Material Design در Flutter از همان اصولی پیروی میکند که در Android وجود دارد — Sheet از پایین ظاهر میشود، از کشیدن و ارتفاع قابل تنظیم پشتیبانی میکند. برای رفتار گسترده با detents از DraggableScrollableSheet استفاده میشود.
Scaffold.of(context).showBottomSheet((context) {
return Container(
padding: EdgeInsets.all(16),
child: Column(
children: [
Text("محتوای Sheet"),
ElevatedButton(
onPressed: () => Navigator.of(context).pop(),
child: Text("بستن")
)
]
)
);
})
React Native در هسته خود کامپوننت Bottom Sheet داخلی ندارد، بنابراین توسعهدهندگان از کتابخانههای شخص ثالث استفاده میکنند. محبوبترین — @gorhom/bottom-sheet (بیش از 7 هزار ستاره در GitHub، 2024). آن یک Bottom Sheet gesture-driven با پشتیبانی از snap points، آنیمیشنها و عناوین مثبت ارائه میدهد. کتابخانه بر اساس Reanimated 2 و Gesture Handler برای کارایی 60 FPS نوشته شده است.
استفاده صحیح از Bottom Sheet مستلزم رعایت دستورالعملهای پلتفرم و درک سناریوهایی است که Sheet در آنها مناسب است. توصیههای کلیدی و اشتباهات رایج در طراحی Sheet را مرور میکنیم.
Bottom Sheet بهینه است برای اقداماتی که نسبت به محتوای اصلی صفحه اضافی هستند. فیلترها، مرتبسازی، انتخاب گزینهها، اطلاعات کوتاه درباره یک عنصر — سناریوهای تیپیکی. Material Design استفاده از Bottom Sheet را برای ابزارهایی توصیه میکند که نباید کل صفحه را بگیرند، اما بیشتر از Action Sheet یا Popup Menu فضا نیاز دارند.
از Bottom Sheet برای هشدارهای حیاتی یا خطاها استفاده نکنید — برای این منظور پنجرههای دیالوگ مناسبتر هستند. از Sheetهایی با تعداد زیاد فیلدورد که نیاز به اسکرول دارند خودداری کنید: کاربر در دسترسی به صفحه کلید دچار مشکل شده و زمینه را از دست میدهد. اگر Sheet شامل بیش از هفت عنصر است، به جای Sheet از یک صفحه جداگانه استفاده کنید.
یک اشتباه رایج تنظیم peekHeight (ارتفاع در حالت بسته) به بیش از 40% صفحه است. کاربر نمیفهمد که Sheet را تماما میبیند یا میتواند آن را باز کند. Material Design peekHeight را در محدوده 15–30% ارتفاع صفحه توصیه میکند تا بخش قابل توجهی از محتوا مخفی باقی بماند و کاربر را به کشیدن ترغیب کند.
در iOS، کاربران انتظار دارند که Sheet را بتوانند از هر مکانی با کشیدن به پایین ببندند. اگر این ژست را غیرفعال کنید (از طریق UISheetPresentationController.prefersEdgeAttachedInCompactHeight)، کاربر در تلاش برای بستن Sheet به شیوه معمولی ناامید میشود. Apple Human Interface Guidelines (2024) تاکید میکند که کشیدن برای بستن یک انتظار اساسی کاربر iOS است.
سوالات متداول
Bottom Sheet پسزمینه را تماما مسدود نمیکند و کشیدن را پشتیبانی میکند، در حالی که پنجره دیالوگ مادال است و نیاز به اقدام اجباری دارد. Bottom Sheet برای گزینههای اضافی مناسبتر است، و پنجره دیالوگ برای تاییدیههای حیاتی.
بلی، اما نیاز به تنظیم adjustResize یا adjustPan در مانیفست Android دارد. در iOS، صفحه کلید به طور خودکار Sheet را بالا میبرد. Flutter و React Native برای موقعیتیابی صحیح نیاز به پردازش دستی از طریق MediaQuery دارند.
توصیه میشود در Sheet استاندارد حداکثر 5–7 عنصر. اگر محتوا بیشتر است — از اسکرول یا تقسیم به دستهبندیها استفاده کنید. Material Design توصیه میکند در وضعیت expanded از 90% ارتفاع صفحه تجاوز نکنید.
برای Sheet مادال setCancelable(true) را در Android یا isModalInPresentation = false را در iOS تنظیم کنید. در Jetpack Compose، onDismissRequest به طور خودکار کلیک روی پسزمینه را مدیریت میکند. در SwiftUI، کشیدن به پایین رفتار پیشفرض است.
بلی، تمام پیادهسازیهای ذاتی از VoiceOver و TalkBack پشتیبانی میکنند. مطمئن شوید که FocusManager فوکوس را به درستی به Sheet در حین باز شدن منتقل کرده و در حین بستن آن را بازگرداند. پیادهسازیهای سفارشی نیاز به پیکربندی دستی دسترسی دارند.
نتیجهگیری
ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد
IT Sectr از سال 2017 برنامههای iOS و Android را برای استارتاپها و کسبوکارها ایجاد میکند. ما به شما مشاوره میدهیم و بهترین راهحل را پیشنهاد خواهیم کرد.
همچنین بخوانید