Skip to content
Håvard Moås edited this page Sep 7, 2020 · 42 revisions

Description

A sheet appears as a card that partially covers the page and can be dragged in a vertical direction to show more content. The page's content is visible behind the sheet to help people to remember the context they suspended when they opened the sheet.

Getting started

👉 To get started, make sure you have followed the getting started steps

A sheet needs to live inside of a ModalityLayout. The ModalityLayout will provide an overlay that is disabled until the modal component closes. It will also add the possibility of tapping the overlay to close the modal component. The ModalityLayout should be placed at the root of your page for the best user experience.

In your XAML page, add the following:

<Contentpage 
   ...
   xmlns:dxui="http://dips.xamarin.ui.com"
   ... >
<dxui:ModalityLayout>
    <dxui:ModalityLayout.Behaviors>
        <dxui:SheetBehavior>
            <dxui:SheetBehavior.SheetContentTemplate>
                <DataTemplate>
                    <!-- sheet content goes here -->
                </DataTemplate>
            </dxui:SheetBehavior.SheetContentTemplate>
        </dxui:SheetBehavior>
    </dxui:ModalityLayout.Behaviors>
    <!-- page content goes here -->
</dxui:ModalityLayout>

👉 All pictures and GIFs are taken from a android simulator, but the look and feel of this component is the same for android / ios devices.

👉 Samples can be found here

👉 A small demonstration of Sheet was visible at .Net Conf:2020

Open a sheet

To open a sheet, set the IsOpen property to True.

👉 This is a bindable property and should be bound to a view model property that changes when people tap a view element inside of the page.

<dxui:ModalityLayout>
    <dxui:ModalityLayout.Behaviors>
        <dxui:SheetBehavior IsOpen="True">
            <dxui:SheetBehavior.SheetContentTemplate>
                <DataTemplate>
                    <!-- sheet content goes here -->
                </DataTemplate>
            </dxui:SheetBehavior.SheetContentTemplate>
        </dxui:SheetBehavior>
    </dxui:ModalityLayout.Behaviors>
    <!-- page content goes here -->
</dxui:ModalityLayout>

Screenshot_1579676014

Adding content to the sheet

Content of the sheet can be set by creating a DataTemplate and setting the SheetContentTemplate property.

👉 You can also use the SheetContent property to set the view, this is the non-lazy approach.

<dxui:ModalityLayout>
    <dxui:ModalityLayout.Behaviors>
        <dxui:SheetBehavior IsOpen="True">
            <dxui:SheetBehavior.SheetContentTemplate>
                <DataTemplate>
                    <!-- sheet content goes here -->
                    <Label Text="This is the sheet content"/>
                </DataTemplate>
            </dxui:SheetBehavior.SheetContentTemplate>
        </dxui:SheetBehavior>
    </dxui:ModalityLayout.Behaviors>
    <!-- page content goes here -->
</dxui:ModalityLayout>

Screenshot_1579675865

Sheet alignment

The sheet's alignment can be changed by setting the Alignment property.

👉 Default is Bottom

<dxui:ModalityLayout>
    <dxui:ModalityLayout.Behaviors>
        <dxui:SheetBehavior IsOpen="True"
                            Alignment="Top" >
            <dxui:SheetBehavior.SheetContentTemplate>
                <DataTemplate>
                    <!-- sheet content goes here -->
                    <Label Text="This is the sheet content"/>
                </DataTemplate>
            </dxui:SheetBehavior.SheetContentTemplate>
        </dxui:SheetBehavior>
    </dxui:ModalityLayout.Behaviors>
    <!-- page content goes here -->
</dxui:ModalityLayout>

Screenshot_1579675953

Setting the position of the sheet

The default behavior of the sheet is to take as much space as it needs when it opens. One exception to that is if a MinPosition is set. The sheet will either take as much space as it needs, or set the position to a MinPosition if the position from the content size is smaller than that.

Another exception is if the consumer of the API has set the Position property. This property has to have values between 0.0 - 1.0 (0% - 100% of the screen).

<dxui:ModalityLayout>
    <dxui:ModalityLayout.Behaviors>
        <dxui:SheetBehavior IsOpen="True"
                            Position="0.5"
                            MinPosition="0.4"
                            MaxPosition="0.7">
            <dxui:SheetBehavior.SheetContentTemplate>
                <DataTemplate>
                    <!-- sheet content goes here -->
                    <Label Text="This is the sheet content"/>
                </DataTemplate>
            </dxui:SheetBehavior.SheetContentTemplate>
        </dxui:SheetBehavior>
    </dxui:ModalityLayout.Behaviors>
    <!-- page content goes here -->
</dxui:ModalityLayout>

👉 This property is a two-way binding, and the consumer can use this to get notified for changes to the sheet.

Screenshot_1579698962

Dragging the sheet

The sheet can be dragged by setting the IsDraggable to True.

<dxui:ModalityLayout>
    <dxui:ModalityLayout.Behaviors>
        <dxui:SheetBehavior IsOpen="True"
                            IsDraggable="True" >
            <dxui:SheetBehavior.SheetContentTemplate>
                <DataTemplate>
                    <!-- sheet content goes here -->
                    <Label Text="This is the sheet content"/>
                </DataTemplate>
            </dxui:SheetBehavior.SheetContentTemplate>
        </dxui:SheetBehavior>
    </dxui:ModalityLayout.Behaviors>
    <!-- page content goes here -->
</dxui:ModalityLayout>

sheet_draggable

sheet_draggable_top

Closing the sheet from sheet content

The content of the sheet might have some kind of view element that should close the sheet. This can be achieved by using our Modality.CloseOnClick attached property on the view element.

<dxui:ModalityLayout>
    <dxui:ModalityLayout.Behaviors>
        <dxui:SheetBehavior IsOpen="True">
            <dxui:SheetBehavior.SheetContentTemplate>
                <DataTemplate>
                    <!-- sheet content goes here -->
                    <StackLayout>
                        <Label Text="This is the sheet content" />
                        <Button Text="Press to close"
                                dxui:Modality.CloseOnClick="True" />
                    </StackLayout>
                </DataTemplate>
            </dxui:SheetBehavior.SheetContentTemplate>
        </dxui:SheetBehavior>
    </dxui:ModalityLayout.Behaviors>
    <!-- page content goes here -->
</dxui:ModalityLayout>

👉 This attached property can be attached to any type of Xamarin.Forms.View element.

sheet_onclose

Auto close

MinPosition together with ShouldAutoClose is used to determine when the sheet should close after a drag is completed.

  • If ShouldAutoClose is set to true and the MinPosition is set to 0.5, the sheet will close if the user stops dragging below 0.5.
<dxui:ModalityLayout>
        <dxui:ModalityLayout.Behaviors>
            <dxui:SheetBehavior IsOpen="True"
                                IsDraggable="True"
                                Position="0.7"
                                MinPosition="0.5"
                                ShouldAutoClose="True">
                <dxui:SheetBehavior.SheetContentTemplate>
                    <DataTemplate>
                        <!-- sheet content goes here -->
                        <Label Text="This is the sheet content" />
                    </DataTemplate>
                </dxui:SheetBehavior.SheetContentTemplate>
            </dxui:SheetBehavior>
        </dxui:ModalityLayout.Behaviors>
        <!-- page content goes here -->
    </dxui:ModalityLayout>

Sheet_AutoClose_true_MinPosition

  • If ShouldAutoClose is set to false and MinPosition is set to 0.5, the sheet will auto-snap to 0.5 when the user stops dragging below 0.5.
  <dxui:ModalityLayout>
        <dxui:ModalityLayout.Behaviors>
            <dxui:SheetBehavior IsOpen="True"
                                IsDraggable="True"
                                Position="0.7"
                                MinPosition="0.5"
                                ShouldAutoClose="False">
                <dxui:SheetBehavior.SheetContentTemplate>
                    <DataTemplate>
                        <!-- sheet content goes here -->
                        <Label Text="This is the sheet content" />
                    </DataTemplate>
                </dxui:SheetBehavior.SheetContentTemplate>
            </dxui:SheetBehavior>
        </dxui:ModalityLayout.Behaviors>
        <!-- page content goes here -->
    </dxui:ModalityLayout>

Sheet_AutoClose_false_MinPosition

Changing colors

The background of the sheet's content, header and the drag-handle's can be changed:

<dxui:ModalityLayout>
    <dxui:ModalityLayout.Behaviors>
        <dxui:SheetBehavior IsOpen="True"
                            IsDraggable="True"
                            HeaderColor="#323E40"
                            ContentColor="#323E40"
                            HandleColor="#D94D1A">
            <!-- sheet content goes here -->
        </dxui:SheetBehavior>
    </dxui:ModalityLayout.Behaviors>
    <!-- page content goes here -->
</dxui:ModalityLayout>

Screenshot_1579677114

Setting BindingContext for the content

The content of the sheet might need it's own BindingContext. This is natural when working with the MVVM pattern.

In the following examples, we have added a SheetPageViewModel that should provide an instance of InsideSheetViewModel.

  • SheetPageViewModel should be the BindingContext of the entire page.
  • InsideSheetViewModel should be the BindingContext of the sheet's content.

xaml:

<ContentPage>
    <ContentPage.BindingContext>
        <local:SheetPageViewModel />
    </ContentPage.BindingContext>
    <dxui:ModalityLayout>
        <dxui:ModalityLayout.Behaviors>
            <dxui:SheetBehavior IsOpen="True"
                                IsDraggable="True"
                                BindingContextFactory="{Binding SheetViewModelFactory}">
                <dxui:SheetBehavior.SheetContentTemplate>
                    <DataTemplate>
                        <!-- sheet content goes here -->
                        <Label Text="{Binding Title}" /> <!-- "Sheet Title" is the value here -->
                    </DataTemplate>
                <dxui:SheetBehavior.SheetContentTemplate>
            </dxui:SheetBehavior>
        </dxui:ModalityLayout.Behaviors>
        <!-- page content goes here -->
    </dxui:ModalityLayout>
</ContentPage>

SheetPageViewModel:

public class SheetPageViewModel : INotifyPropertyChanged
{
    public Func<object> SheetViewModelFactory => () => new InsideSheetViewModel();

    public event PropertyChangedEventHandler PropertyChanged;
}

InsideSheetViewModel:

 public class InsideSheetViewModel : INotifyPropertyChanged
    {
        public string Title => "Sheet Title";

        public event PropertyChangedEventHandler PropertyChanged;
    }

iOS demo

Here is a small demonstration of the sheet running on an iOS simulator with our samples code.

sheet_ios

👉 The demonstration page can be outdated.

Properties

Property Explanation Remarks default value
Alignment Determines the position of the sheet when it appears. Bottom
VerticalContentAlignment Determines how the content of the sheet should align. Fit
SheetContent The content of the sheet. BindingContextFactory to set the binding context when the sheet opens null
BindingContextFactory Used to set the binding context of the content of the sheet when the sheet opens. If this is not set, the BindingContext of the ModalityLayout will be used. null
ContentColor Determines the background color of the content part of the sheet. Color.White
HeaderColor etermines the background color of the header part of the sheet. Color.White
HandleColor Determines the color of the handle in the sheet. ColorPalette.QuinaryAir
HasShadow Determines if the sheet should have shadow. This only works for iOS. false
IsDraggable Determines if the sheet should be drag-able or not. false
IsOpen Determines if the sheet should be visible or not. false
MaxPosition Determines the maximum position of the sheet when it is visible. This will affect the size of the sheet if Position is set to 0.0. This will affect the people that are dragging the sheet. The value have to be between 0.0 and 1.0 (percentage of the screen) 1.0
MinPosition Determines the minimum position of the sheet when it is visible. This position is used to determine where the sheet will auto close if ShouldAutoClose is set to true. his position is used to determine where the sheet will snap to when ShouldAutoClose is set to false. This will affect the size of the sheet if Position is set to 0.0. The value have to be between 0.0 and 1.0 (percentage of the screen) 0.1
OnOpen Event that gets raised when the sheet has completed it's animation and is open.
OnOpenCommand Command that executes when the sheet has completed it's animation and is open null
OnOpenCommandParameter The parameter to pass to theOnOpenCommand null
OnClose Event that gets raised when the sheet has completed it's animation and is closed.
OnCloseCommand TCommand that executes when the sheet has completed it's animation and is closed null
OnCloseCommandParameter The parameter to pass to the OnCloseCommand null
OnBeforeClose Event that gets raised before the sheet start it's animation when closing
OnBeforeCloseCommand Command that execute before the sheet start it's animation when closing. null
OnBeforeCloseCommandParameter The parameter to pass to OnBeforeCloseCommand null
OnBeforeOpen Event that gets raised when the sheet is about to start it's animation to open.
OnBeforeOpenCommand Command that execute when the sheet is about to start it's animation to open. null
OnBeforeOpenCommandParameter Parameter to pass to OnBeforeOpenCommand null
OnPositionChanged Event that gets raised when the sheet has changed it's position. null
OnPositionChangedCommand A command that executes when the position of the sheet changes. The command parameter will be the new positional value, same as Position null
CloseOnOverlayTapped Determines if the sheet should close when the overlay is tapped. true
ShouldAutoClose Determines if the sheet should auto close at the MinPosition. true
ShouldRememberPosition Determines if the sheet should remember the position it had when it is closed. false
ActionButtonSize The size of the label of the action button. NamedSize.Small
ActionCommand Gets or sets the command that is invoked when the action button is activated. null
ActionCommandParameter Parameter passed to ActionCommand. null
ActionClicked Event that gets raised when the user has clicked the action button.
ActionTitleColor Color of text in the action button. Theme.TealPrimary
ActionTitle Action button text. If this is not empty action button is visible. string.Empty
CancelCommand Gets or sets the command that is invoked when the cancel button is activated. Can be set to a CancelSheetCommand to provide a function that decides if the sheet should close when Cancel button is clicked. Sheet is closed by default. null
CancelButtonSize The size of the label of the cancel button. NamedSize.Small
CancelCommandParameter Parameter passed to CancelCommand null
CancelClicked Event that gets raised when the user has clicked the cancel button.
IsCancelButtonVisible Determines if the cancel button is visible. false
CancelTitleColor Color of the text in the cancel button. Theme.TealPrimary
CancelTitle Cancel button text. Cancel
IsTitleSeparatorVisible Determines if the separator between the title and the sheet content should be visible. true
TitleSeparatorColor Color of the title separator. ColorPalette.QuinaryLight
Title Title text
TitleColor Color of the text in title. ColorPalette.TertiaryLight
TitleSize The size of the title label. NamedSize.Medium
Clone this wiki locally