Sheet este o componentă UI care apare în partea de jos a ecranului deasupra conținutului principal și oferă acțiuni sau informații suplimentare. Bottom Sheet este cel mai răspândit tip, definit în ghidurile Material Design 3 (Google, 2024). Spre deosebire de ferestrele de dialog, Sheet nu blochează complet interacțiunea cu fundalul și suportă stările collapsed și expanded. Înțelegerea tipurilor și comportamentului Sheet este necesară pentru construirea unei navigații confortabile în aplicațiile mobile.
Principalele
Sheet — este o componentă UI de suprafață care iese din partea de jos a ecranului și afișează conținut sau acțiuni suplimentare fără a muta utilizatorul de pe ecranul curent. Spre deosebire de tranzițiile pe ecran întreg, Sheet păstrează contextul: utilizatorul vede ecranul de fundal și înțelege de unde a apărut Sheet.
Arhitectura Sheet se bazează pe un container cu înălțime variabilă. În starea minimă (collapsed) este vizibilă doar o parte din conținut — de obicei titlul sau un panou mic. Utilizatorul poate trage Sheet în sus pentru a-l extinde (expanded) sau în jos pentru a-l închide. Acest comportament amintește de o foaie de hârtie care este scoasă de sub un teanc — de aici și numele.
Google în ghidurile Material Design 3 (2024) evidențiază două scenarii cheie de utilizare a Sheet: afișarea acțiunilor suplimentare care nu au încăput pe bara de instrumente principală și afișarea formularelor sau informațiilor detaliate fără a naviga la un ecran separat. Apple a adăugat suport sistem pentru Sheet începând cu iOS 15 prin UISheetPresentationController, ceea ce confirmă universalitatea acestui model.
Material Design definește trei tipuri de Bottom Sheet, fiecare cu propriul comportament și domeniu de aplicare. Alegerea tipului corect influențează direct experiența utilizatorului și conformitatea cu ghidurile platformei.
Bottom Sheet standard — componentă nemodală: utilizatorul poate interacționa cu ecranul de fundal fără a închide Sheet. De exemplu, navigând prin lista de produse în fereastra de fundal, utilizatorul vede filtrele în Bottom Sheet și le poate modifica fără a închide panoul. Sheet își ajustează înălțimea în funcție de conținut — de la 30% la 90% din ecran.
Bottom Sheet standard nu blochează fundalul și permite interacțiunea cu conținutul principal. Aceasta este diferența cheie față de Sheet modal, care necesită o acțiune obligatorie pentru a continua. Folosește Sheet standard atunci când informațiile suplimentare nu sunt critice pentru scenariul principal.
Bottom Sheet modal blochează interacțiunea cu ecranul de fundal până când utilizatorul efectuează o acțiune în interiorul Sheet. Un astfel de Sheet este afișat întotdeauna în starea expanded și necesită închidere explicită — prin buton, acțiune sau glisare în jos. Material Design recomandă Sheet modal pentru formulare de autentificare, confirmări și setări critice.
Pe Android, Bottom Sheet modal se implementează prin BottomSheetDialogFragment, care blochează automat fundalul. Pe iOS, comportamentul analog este asigurat de varianta modală a UISheetPresentationController cu parametrul .mediumDetent. Sheet modal trebuie utilizat doar atunci când contextul necesită atenția utilizatorului.
Bottom Sheet extins combină proprietățile standardului și modalului: începe ca nemodal în starea collapsed, dar la tragerea în sus devine modal. În practică, aceasta înseamnă că utilizatorul poate arunca mai întâi o privire asupra conținutului, apoi poate decide — să extindă Sheet pentru studiu detaliat sau să îl închidă.
Acest model este deosebit de popular în hărți și navigatoare, unde panoul inferior arată informații scurte despre un punct de pe traseu, iar la glisarea în sus se deschide cu detalii. Google Maps folosește exact acest Sheet extins pentru afișarea informațiilor despre locuri și rute.
| Tip Sheet | Blocare fundal | Stare inițială | Exemplu |
|---|---|---|---|
| Standard | Nu | Collapsed | Filtre în catalog |
| Modal | Da | Expanded | Formular de autentificare |
| Extins | Parțial | Collapsed | Fișa locului |
Android SDK oferă mai multe API-uri pentru implementarea Bottom Sheet, de la abordarea clasică View până la modernul Jetpack Compose. Material Components Library pentru Android include implementări gata făcute BottomSheetDialogFragment și BottomSheetBehavior.
BottomSheetBehavior — este o clasă din Material Components care se atașează la orice View și gestionează poziția acestuia pe ecran. Dezvoltatorul stabilește trei stări: STATE_COLLAPSED (pliat), STATE_EXPANDED (extins) și STATE_HIDDEN (ascuns). Behavior gestionează automat gesturile de tragere și animația.
val sheet = findViewById<View>(R.id.bottom_sheet)
val behavior = BottomSheetBehavior.from(sheet)
behavior.state = BottomSheetBehavior.STATE_COLLAPSED
behavior.peekHeight = 200
Jetpack Compose oferă o API mai declarativă prin componenta ModalBottomSheet din Material 3. Spre deosebire de abordarea View, în Compose Bottom Sheet este o funcție composable care primește stare și conținut. Sheet animează automat apariția, ascunderea și modificarea înălțimii la tragere.
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun FilterSheet(onDismiss: () -> Unit) {
ModalBottomSheet(onDismissRequest = onDismiss) {
Text("Filtre")
Button(onClick = onDismiss) { Text("Aplicare") }
}
}
BottomSheetDialogFragment — este un DialogFragment specializat care se afișează ca Bottom Sheet. Acesta gestionează automat modalitatea, ciclul de viață și modificările de configurare. Dezvoltatorul trebuie doar să suprascrie onCreateView și să returneze layout-ul Sheet. Conform documentației Google (Android Developers, 2024), BottomSheetDialogFragment este metoda recomandată pentru Bottom Sheet modale în Android clasic.
Apple a introdus suportul sistem pentru Sheet începând cu iOS 15 prin UISheetPresentationController. Înainte, dezvoltatorii implementau Bottom Sheet manual prin custom transition sau biblioteci terțe. Sheet-ul nativ Apple suportă detents — niveluri predefinite de deschidere.
UISheetPresentationController — este un controler de prezentare încorporat care afișează View Controller ca Sheet. Dezvoltatorul stabilește un array de detents — valori de înălțime la care Sheet se poate opri. iOS 16 a adăugat detents personalizate cu înălțime arbitrară. Apple recomandă utilizarea detents medium (.medium) și large (.large) ca principale.
let viewController = MySheetViewController()
if let sheet = viewController.sheetPresentationController {
sheet.detents = [.medium, .large]
sheet.prefersGrabberVisible = true
sheet.preferredCornerRadius = 16
}
present(viewController, animated: true)
SwiftUI oferă modificatorul .sheet, care leagă afișarea Sheet de o stare. Când variabila publicată (published) devine true, SwiftUI afișează automat Sheet. SwiftUI suportă de asemenea detents prin modificatorul .presentationDetents, adăugat în iOS 16.
struct ContentView: View {
@State private var showSheet = false
var body: some View {
Button("Afișare Sheet") { showSheet = true }
.sheet(isPresented: $showSheet) {
FilterView()
.presentationDetents([.medium, .large])
}
}
}
Framework-urile cross-platform suportă de asemenea Bottom Sheet, adaptând comportamentul la platforma țintă. Flutter și React Native oferă implementări încorporate și personalizate cu diferite grade de flexibilitate.
Flutter SDK conține două metode pentru afișarea Bottom Sheet: showBottomSheet (standard) și showModalBottomSheet (modal). Material Design în Flutter urmează aceleași principii ca în Android — Sheet apare în partea de jos, suportă tragerea și înălțimea configurabilă. Pentru comportament extins cu detents se folosește DraggableScrollableSheet.
Scaffold.of(context).showBottomSheet((context) {
return Container(
padding: EdgeInsets.all(16),
child: Column(
children: [
Text("Conținut Sheet"),
ElevatedButton(
onPressed: () => Navigator.of(context).pop(),
child: Text("Închidere")
)
]
)
);
})
React Native nu are o componentă Bottom Sheet încorporată în nucleu, astfel că dezvoltatorii folosesc biblioteci terțe. Cea mai populară — @gorhom/bottom-sheet (peste 7 mii de stele pe GitHub, 2024). Oferă un Bottom Sheet gesture-driven cu suport pentru snap points, animații și anteturi fixate. Biblioteca este scrisă pe baza Reanimated 2 și Gesture Handler pentru performanță la 60 FPS.
Utilizarea corectă a Bottom Sheet necesită respectarea ghidurilor platformei și înțelegerea scenariilor în care Sheet este potrivit. Să analizăm recomandările cheie și greșelile frecvente în proiectarea Sheet.
Bottom Sheet este optim pentru acțiuni care sunt suplimentare față de conținutul principal de pe ecran. Filtre, sortare, selectare opțiuni, informații scurte despre un element — scenarii tipice. Material Design recomandă utilizarea Bottom Sheet pentru instrumente care nu ar trebui să ocupe întregul ecran, dar necesită mai mult spațiu decât Action Sheet sau Popup Menu.
Nu folosi Bottom Sheet pentru avertismente critice sau erori — pentru acestea sunt potrivite ferestrele de dialog. Evită Sheet-urile cu un număr mare de câmpuri de intrare care necesită derulare: utilizatorul are dificultăți în a ajunge la tastatură și pierde contextul. Dacă Sheet conține mai mult de șapte elemente de acțiune, ia în considerare un ecran separat în loc de Sheet.
O greșeală tipică este setarea peekHeight (înălțimea în stare pliată) la mai mult de 40% din ecran. Utilizatorul nu înțelege dacă vede Sheet în întregime sau poate fi extins. Material Design recomandă peekHeight între 15-30% din înălțimea ecranului pentru a lăsa o parte vizibilă din conținut ascunsă și a motiva la tragere.
Pe iOS, utilizatorii se așteaptă ca Sheet să poată fi închis prin glisare în jos din orice poziție. Dacă dezactivați acest gest (prin UISheetPresentationController.prefersEdgeAttachedInCompactHeight), utilizatorul va fi frustrat încercând să închidă Sheet în modul obișnuit. Apple Human Interface Guidelines (2024) subliniază că glisarea pentru închidere este o așteptare de bază a utilizatorului iOS.
Întrebări frecvente
Bottom Sheet nu blochează complet fundalul și suportă tragerea, iar fereastra de dialog este modală și necesită o acțiune obligatorie. Bottom Sheet este mai potrivit pentru opțiuni suplimentare, dialogul — pentru confirmări critice.
Da, dar necesită configurarea adjustResize sau adjustPan în manifestul Android. Pe iOS, tastatura ridică automat Sheet. Flutter și React Native necesită gestionare manuală prin MediaQuery pentru poziționarea corectă.
Se recomandă nu mai mult de 5-7 elemente într-un Sheet standard. Dacă conținutul este mai mare — folosește derulare sau împărțire pe categorii. Material Design sfătuiește să nu depășești 90% din înălțimea ecranului în starea expanded.
Pentru Sheet modal setează setCancelable(true) pe Android sau isModalInPresentation = false pe iOS. În Jetpack Compose, onDismissRequest gestionează automat atingerea fundalului. În SwiftUI, glisarea în jos este comportamentul standard.
Da, toate implementările native suportă VoiceOver și TalkBack. Asigură-te că FocusManager mută corect focalizarea în Sheet la deschidere și o întoarce la închidere. Implementările personalizate necesită configurare manuală a accessibility.
Concluzii
Vom dezvolta o aplicație mobilă la cheie
IT Sectr creează aplicații iOS și Android pentru startup-uri și afaceri din 2017. Vă vom consilia și vă vom propune cea mai bună soluție.
Citiți și