Skip to content

Bottom sheet

github-actions[bot] edited this page Jun 18, 2026 · 19 revisions

Bottom sheet is a component designed for you to display content anchored to the bottom of your page for people to use. This is considered a modal, a mode that people go to but still maintain focus to the context they are in.

Inspiration

Usage

Create your bottom sheet by creating a XAML class that derives from dui:BottomSheet.

<dui:BottomSheet xmlns="http://xamarin.com/schemas/2014/forms"
                 xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                 xmlns:dui="http://dips.com/mobile.ui"
                 x:Class="<MyNameSpace>.MyBottomSheet"
                 ....
                 >
    <!-- Content of bottom sheet goes here -->
</dui:BottomSheet>

Open the bottom sheet using C#:

await BottomSheetService.Open(new MyBottomSheet());

Or by XAML:

<dui:Button Text="Open my bottom sheet"
            Command="{dui:OpenBottomSheetCommand {x:Type sheets: MyBottomSheet}}" />

Features

  • Customizable Position: Adjust the starting position of the bottom sheet.
  • Interactive Close: Control whether users can swipe to close the sheet.
  • Header and Buttons: Includes a default header and support for bottom bar buttons.

Use Cases

  • Display additional options or actions without leaving the current context.
  • Provide modal-like functionality for focused user interactions.

Configuration

  • Position: Set to Fit for size-based positioning.
  • IsInteractiveCloseable: Enable or disable swipe-to-close functionality.
  • Header Behavior: Customize the header with commands and visibility options.

Change start position.

The bottom sheets default position is half of the screen, this can be controlled by setting the Position property. To make it position using its size, set the Position property to Fit.

Make sure people don't accidentally close it.

Use IsInteractiveCloseable to control whether people can close the bottom sheet by swiping it down (iOS and Android) or back button / back swipe (Android). The bottom sheet is still programatically closable. Use this.Close() or BottomSheetService.Close(bottomSheet) to close it.

Handling the back button on Android

When IsInteractiveCloseable is set to false, the back button will not close the bottom sheet on Android. However, you can bind a command to handle the back button press and execute custom logic before deciding whether to close the bottom sheet.

To achieve this, use the OnBackButtonPressedCommand property:

<dui:BottomSheet Title="The title"
                 OnBackButtonPressedCommand="{Binding TryCloseBottomSheetCommand}">
    
</dui:BottomSheet>

In your ViewModel, define the command to handle the back button press:

public ICommand MyBackButtonCommand => new Command<Action>(async closeBottomSheet =>
{
    // Perform your custom logic here
    await ConfirmExitAsync();

    // Close the bottom sheet if needed
    closeBottomSheet.Invoke();
});

This allows you to control the behavior of the back button and decide whether to close the bottom sheet after executing your custom logic.

An Action as CommandParameter is passed to the Command from the BottomSheet, allowing you to invoke it to close the bottom sheet programmatically after performing your custom logic.

Header

The bottom sheet comes with a default header that includes a close button. You can set the title of the bottom sheet by using the Title property, which will be displayed in the header. Additionally, the header can include a back button if needed.

To configure the header use BottomSheetHeaderBehavior.

Close Button

The default close button in the header closes the bottom sheet by default. However, you can override this behavior by binding a command to the close button. For example, you can bind a command to perform an action (e.g., saving data) before closing the bottom sheet:

An Action as CommandParameter is passed to the Command from the BottomSheet, allowing you to invoke it to close the bottom sheet programmatically after performing your custom logic.

<dui:BottomSheet Title="The title">
    
    <dui:BottomSheet.BottomSheetHeaderBehavior>
        <header:BottomSheetHeaderBehavior CloseButtonCommand="{Binding MyCloseCommand}" />
    </dui:BottomSheet.BottomSheetHeaderBehavior>
</dui:BottomSheet>
public ICommand MyCloseCommand => new Command<Action>(async closeBottomSheet =>
{
    // Perform your custom logic here
    await SaveDataAsync();
    
    // Close the bottom sheet
    closeBottomSheet.Invoke();
});

Back Button

To include a back button in the header, you can configure the IsBackButtonVisible property:

<dui:BottomSheet Title="The title">
    
    <dui:BottomSheet.BottomSheetHeaderBehavior>
        <header:BottomSheetHeaderBehavior IsBackButtonVisible="{Binding IsBackButtonVisible}" />
    </dui:BottomSheet.BottomSheetHeaderBehavior>
</dui:BottomSheet>

Title and back button container

You can configure the container that contains the title and back button to execute a bound command by using the TitleAndBackButtonCommand property. This allows you to handle custom actions when interacting with the container.

<dui:BottomSheet Title="The title">
    
    <dui:BottomSheet.BottomSheetHeaderBehavior>
        <header:BottomSheetHeaderBehavior TitleAndBackButtonContainerCommand="{Binding TitleAndBackButtonContainerCommand}" />
    </dui:BottomSheet.BottomSheetHeaderBehavior>
</dui:BottomSheet>

In your ViewModel, define the command to handle the interaction:

public ICommand MyTitleAndBackButtonCommand => new Command(() =>
{
    // Perform your custom logic here
    NavigateToAnotherPage();
});

Disabling the Command

To disable the container command, you can bind the IsTitleAndBackButtonContainerEnabled property to a boolean value in your ViewModel. When set to false, the container will be set to IsEnabled = false, thus, will not execute the Command.

<dui:BottomSheet Title="The title">
    
    <dui:BottomSheet.BottomSheetHeaderBehavior>
        <header:BottomSheetHeaderBehavior TitleAndBackButtonContainerCommand="{Binding TitleAndBackButtonContainerCommand}"
                                          IsTitleAndBackButtonContainerEnabled="{Binding IsContainerEnabled}" />
    </dui:BottomSheet.BottomSheetHeaderBehavior>
</dui:BottomSheet>

BottombarButtons

The bottom sheet supports BottombarButtons, which can be used similarly to ToolbarItems in a regular page. These buttons are displayed floating at the bottom of the sheet. The buttons are displayed horizontally.

<dui:BottomSheet>
    <dui:BottomSheet.BottombarButtons>

        <dui:Button Text="Ghost Large"
                    Style="{dui:Styles Button=GhostLarge}"
                    VerticalOptions="End"/>

        <dui:Button Text="Primary Large"
                    HorizontalOptions="Fill"
                    VerticalOptions="End" />

    </dui:BottomSheet.BottombarButtons>
</dui:BottomSheet>

Most likely you will want to set VerticalOptions="End" on the buttons, otherwise the they will fill out its vertical height to the container.

Persisting the bottom bar across PushAsync sub-views

By default, when you push a sub-view onto the sheet via PushAsync, the bottom bar is only rendered on the root sheet. Set ShowBottombarButtonsOnSubViews="True" to keep the same BottombarButtons visible across every pushed sub-view. The buttons remain bound to the root sheet's BindingContext, so commands continue to target the root sheet's view model rather than the sub-view.

<dui:BottomSheet ShowBottombarButtonsOnSubViews="True">
    <dui:BottomSheet.BottombarButtons>
        <dui:Button Text="Reset"
                    Command="{Binding ResetCommand}"
                    Style="{dui:Styles Button=GhostLarge}"
                    VerticalOptions="End" />
        <dui:Button Text="Apply"
                    Command="{Binding ApplyCommand}"
                    HorizontalOptions="Fill"
                    VerticalOptions="End" />
    </dui:BottomSheet.BottombarButtons>
</dui:BottomSheet>

Properties

Inspect the components properties class to further customise and use it.

Navigasjon

BottomSheet har et internt navigasjons-API som lar deg dytte (push) og poppe visninger inne i et allerede åpent ark. Dette gir mulighet for flerstegsflytar uten å åpne nye ark.

API

Metode / Egenskap Beskrivelse
PushAsync(ContentPage page) Dytter en ContentPage på arkets interne navigasjonsstakk. Sidens Content vises med animasjon og Title brukes i navigasjonsbaren.
PopAsync() Popper øverste visning og returnerer til forrige innhold. Gjør ingenting dersom stakken er tom.
PopToRootAsync() Popper alle visninger fra navigasjonsstakken og returnerer til rotinnholdet med én animert overgang. Gjør ingenting dersom stakken allerede er på rot.
CanPopNavigation booltrue dersom det finnes innhold som kan poppes.
ShowBottombarButtonsOnSubViews Bindable property (bool, default false). Når true, forblir bunnbar-knappene synlige på alle pushede visninger. Knappene er bundet til rot-arkets BindingContext.

Eksempel

var bottomSheet = new MyBottomSheet();
await BottomSheetService.Open(bottomSheet);

// Dytt en ny visning etter at arket er åpnet
await bottomSheet.PushAsync(new MyDetailPage());

// Gå tilbake til forrige visning
await bottomSheet.PopAsync();

// Eller hopp helt tilbake til rotinnholdet, uansett hvor djupt du er
await bottomSheet.PopToRootAsync();

Begrensningar / viktig å vite

  • Arket må være åpentPushAsync kan kun kalles etter at arket er presentert (Open() fullført / Opened-event fyrt). Kall før åpning vil kaste exception.
  • Navigasjonsstakken er intern per BottomSheet-instans – den deles ikke mellom ark.
  • iOS sveip-tilbake – På iOS håndteres sveip-tilbake-gester automatisk; den interne stakken holdes synkronisert.
  • Automatisk tilbake-knapp – Tilbake-knapp i navigasjonsbaren vises automatisk når det finnes innhold på stakken.

Clone this wiki locally