Sheet är en UI-komponent som visas längst ner på skärmen ovanför huvudinnehållet och ger ytterligare åtgärder eller information. Bottom Sheet är den vanligaste typen, definierad i riktlinjerna för Material Design 3 (Google, 2024). Till skillnad från dialogrutor blockerar Sheet inte helt interaktionen med bakgrunden och stöder tillstånden collapsed och expanded. Förståelse för Sheet-typer och beteende är nödvändig för att bygga bekväm navigering i mobilappar.
Huvudpunkter
Sheet är en ytlig UI-komponent som glider upp från botten av skärmen och visar ytterligare innehåll eller åtgärder utan att ta bort användaren från den aktuella skärmen. Till skillnad från helskärmsövergångar behåller Sheet sammanhanget: användaren ser bakgrundsskärmen och förstår var Sheet kom ifrån.
Sheet-arkitekturen är baserad på en behållare med variabel höjd. I minimalt tillstånd (collapsed) är endast en del av innehållet synligt — vanligtvis en rubrik eller en liten panel. Användaren kan dra Sheet uppåt för att expandera det (expanded) eller svepa nedåt för att stänga. Detta beteende påminner om ett fysiskt pappersark som dras fram under en hög — därav namnet.
Google i Material Design 3 (2024) riktlinjer framhäver två viktiga scenarier för användning av Sheet: visning av ytterligare åtgärder som inte får plats på huvudverktygsfältet, och visning av formulär eller detaljerad information utan att navigera till en separat skärm. På iOS lade Apple till systemstöd för Sheet från och med iOS 15 via UISheetPresentationController, vilket bekräftar mönstrets universalitet.
Material Design definierar tre typer av Bottom Sheet, var och en med sitt eget beteende och tillämpningsområde. Valet av rätt typ påverkar direkt användarupplevelsen och efterlevnaden av plattformsriktlinjer.
Standard Bottom Sheet är en icke-modal komponent: användaren kan interagera med bakgrundsskärmen utan att stänga Sheet. Till exempel, medan användaren bläddrar i en produktlista i bakgrundsfönstret, ser denne filter i Bottom Sheet och kan ändra dem utan att stänga panelen. Sheet anpassar sin höjd efter innehållet — från 30% till 90% av skärmen.
Standard Bottom Sheet blockerar inte bakgrunden och möjliggör interaktion med huvudinnehållet. Detta är den viktigaste skillnaden från modal Sheet, som kräver en obligatorisk åtgärd för att fortsätta arbetet. Använd standard Sheet när den extra informationen inte är kritisk för huvudscenariot.
Modal Bottom Sheet blockerar interaktion med bakgrundsskärmen tills användaren utför en åtgärd inuti Sheet. En sådan Sheet visas alltid i expanded-tillstånd och kräver explicit stängning — via knapp, åtgärd eller svep nedåt. Material Design rekommenderar modal Sheet för inloggningsformulär, bekräftelser och kritiska inställningar.
På Android implementeras modal Bottom Sheet via BottomSheetDialogFragment, som automatiskt blockerar bakgrunden. På iOS tillhandahålls liknande beteende av den modala varianten av UISheetPresentationController med parametern .mediumDetent. Modal Sheet bör endast användas när sammanhanget kräver användarens uppmärksamhet.
Utökad Bottom Sheet kombinerar egenskaper från standard och modal: den börjar som icke-modal i collapsed-tillstånd, men blir modal när den dras uppåt. I praktiken innebär detta att användaren först kan få en glimt av innehållet och sedan besluta — expandera Sheet för detaljerad studie eller stänga det.
Detta mönster är särskilt populärt i kartor och navigatorer, där den nedre panelen visar kort information om en ruttpunkt och vid svep uppåt öppnas med detaljer. Google Maps använder precis en sådan utökad Sheet för att visa information om platser och rutter.
| Sheet-typ | Bakgrundsblockering | Initialt tillstånd | Exempel |
|---|---|---|---|
| Standard | Nej | Collapsed | Filter i katalog |
| Modal | Ja | Expanded | Inloggningsformulär |
| Utökad | Delvis | Collapsed | Platskort |
Android SDK tillhandahåller flera API:er för att implementera Bottom Sheet, från det klassiska View-angreppssättet till moderna Jetpack Compose. Material Components Library för Android innehåller färdiga implementationer av BottomSheetDialogFragment och BottomSheetBehavior.
BottomSheetBehavior är en klass från Material Components som kan kopplas till valfri View och hantera dess position på skärmen. Utvecklaren ställer in tre tillstånd: STATE_COLLAPSED (ihopfälld), STATE_EXPANDED (expanderad) och STATE_HIDDEN (dold). Behavior hanterar automatiskt draggester och animation.
val sheet = findViewById<View>(R.id.bottom_sheet)
val behavior = BottomSheetBehavior.from(sheet)
behavior.state = BottomSheetBehavior.STATE_COLLAPSED
behavior.peekHeight = 200
Jetpack Compose erbjuder ett mer deklarativt API via ModalBottomSheet-komponenten från Material 3. Till skillnad från View-angreppssättet är Bottom Sheet i Compose en composable-funktion som tar emot tillstånd och innehåll. Sheet animerar automatiskt visning, döljning och höjdförändring vid dragning.
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun FilterSheet(onDismiss: () -> Unit) {
ModalBottomSheet(onDismissRequest = onDismiss) {
Text("Filters")
Button(onClick = onDismiss) { Text("Apply") }
}
}
BottomSheetDialogFragment är en specialiserad DialogFragment som visas som Bottom Sheet. Den hanterar automatiskt modalitet, livscykel och konfigurationsändringar. Utvecklaren behöver bara åsidosätta onCreateView och returnera Sheet-layouten. Enligt Googles dokumentation (Android Developers, 2024) är BottomSheetDialogFragment den rekommenderade metoden för modal Bottom Sheet i klassisk Android.
Apple introducerade systemstöd för Sheet från och med iOS 15 via UISheetPresentationController. Innan dess implementerade utvecklare Bottom Sheet manuellt via custom transition eller tredjepartsbibliotek. Apples inbyggda Sheet stöder detents — fördefinierade öppningsnivåer.
UISheetPresentationController är en inbyggd presentationskontroller som visar en View Controller som Sheet. Utvecklaren anger en array av detents — höjdvärden där Sheet kan stanna. iOS 16 lade till anpassade detents med godtycklig höjd. Apple rekommenderar att använda medium (.medium) och large (.large) detents som huvudsakliga.
let viewController = MySheetViewController()
if let sheet = viewController.sheetPresentationController {
sheet.detents = [.medium, .large]
sheet.prefersGrabberVisible = true
sheet.preferredCornerRadius = 16
}
present(viewController, animated: true)
SwiftUI tillhandahåller modifieraren .sheet som binder visningen av Sheet till ett tillstånd. När en published-variabel blir true visar SwiftUI automatiskt Sheet. SwiftUI stöder även detents via modifieraren .presentationDetents, som lades till i iOS 16.
struct ContentView: View {
@State private var showSheet = false
var body: some View {
Button("Show Sheet") { showSheet = true }
.sheet(isPresented: $showSheet) {
FilterView()
.presentationDetents([.medium, .large])
}
}
}
Plattformsoberoende ramverk stöder också Bottom Sheet och anpassar beteendet till målplattformen. Flutter och React Native tillhandahåller inbyggda och anpassade implementationer med olika grad av flexibilitet.
Flutter SDK innehåller två metoder för att visa Bottom Sheet: showBottomSheet (standard) och showModalBottomSheet (modal). Material Design i Flutter följer samma principer som i Android — Sheet visas från botten, stöder dragning och konfigurerbar höjd. För utökat beteende med detents används DraggableScrollableSheet.
Scaffold.of(context).showBottomSheet((context) {
return Container(
padding: EdgeInsets.all(16),
child: Column(
children: [
Text("Sheet Content"),
ElevatedButton(
onPressed: () => Navigator.of(context).pop(),
child: Text("Close")
)
]
)
);
})
React Native har ingen inbyggd Bottom Sheet-komponent i sin kärna, så utvecklare använder tredjepartsbibliotek. Det mest populära är @gorhom/bottom-sheet (mer än 7 tusen stjärnor på GitHub, 2024). Det erbjuder en geststyrd Bottom Sheet med stöd för snap points, animationer och fasta rubriker. Biblioteket är skrivet i Reanimated 2 och Gesture Handler för prestanda på 60 FPS.
Korrekt användning av Bottom Sheet kräver efterlevnad av plattformsriktlinjer och förståelse för scenarier där Sheet är lämpligt. Låt oss titta på de viktigaste rekommendationerna och vanliga misstagen vid design av Sheet.
Bottom Sheet är optimalt för åtgärder som är kompletterande till huvudinnehållet på skärmen. Filter, sortering, val av alternativ, kort information om ett element — typiska scenarier. Material Design rekommenderar att använda Sheet för verktyg som inte bör uppta hela skärmen men som behöver mer utrymme än Action Sheet eller Popup Menu.
Använd inte Bottom Sheet för kritiska varningar eller fel — för detta är dialogrutor lämpliga. Undvik Sheet med många inmatningsfält som kräver rullning: användaren har svårt att nå tangentbordet och förlorar sammanhanget. Om Sheet innehåller mer än sju åtgärdselement, överväg en separat skärm istället för Sheet.
Ett typiskt misstag är att ställa in peekHeight (höjd i ihopfällt tillstånd) till mer än 40% av skärmen. Användaren förstår inte om de ser Sheet i sin helhet eller om det kan expanderas. Material Design rekommenderar peekHeight inom intervallet 15-30% av skärmhöjden för att lämna en betydande del av innehållet dold och motivera till dragning.
På iOS förväntar sig användare att Sheet kan stängas genom att svepa nedåt från valfri position. Om du inaktiverar denna gest (via UISheetPresentationController.prefersEdgeAttachedInCompactHeight) blir användaren frustrerad när de försöker stänga Sheet på vanligt sätt. Apple Human Interface Guidelines (2024) betonar att svep för att stänga är en grundläggande förväntning hos iOS-användare.
Vanliga frågor
Bottom Sheet blockerar inte bakgrunden helt och stöder dragning, medan en dialogruta är modal och kräver obligatorisk åtgärd. Bottom Sheet passar bättre för extra alternativ, dialog för kritiska bekräftelser.
Ja, men inställning av adjustResize eller adjustPan i Android-manifestet krävs. På iOS lyfter tangentbordet automatiskt Sheet. Flutter och React Native kräver manuell hantering via MediaQuery för korrekt positionering.
Rekommenderas inte mer än 5-7 element i ett standard Sheet. Om det finns mer innehåll — använd rullning eller kategorisering. Material Design råder att inte överstiga 90% av skärmhöjden i expanded-tillstånd.
För modal Sheet ställ in setCancelable(true) på Android eller isModalInPresentation = false på iOS. I Jetpack Compose hanterar onDismissRequest automatiskt tryck på bakgrunden. I SwiftUI är svep nedåt standardbeteende.
Ja, alla inbyggda implementationer stöder VoiceOver och TalkBack. Se till att FocusManager korrekt flyttar fokus till Sheet när det öppnas och återställer det när det stängs. Anpassade implementationer kräver manuell tillgänglighetsinställning.
Sammanfattning
Vi utvecklar en mobil applikation nyckelfärdigt
IT Sectr skapar iOS- och Android-applikationer för startups och företag sedan 2017. Vi ger dig råd och föreslår den bästa lösningen.
Läs också