xamluser-interfacemauiwear-ospicker

In .net MAUI, which control to select a number for small screen?


I'm using .Net MAUI to build an app for watches (wear os and IOS): small screens. I'd like the user to select a number between 0 and 60.

I've tried a picker, but the layout is horrible on small screen like watches (see below).

Are there better controls for this, like a "rolling" control to pick a number like when setting an alarm on Android for instance? If not, is there a way to customize the picker "selection" UI?

Picker on Android


Solution

  • The right approach is to use vertical a carousel (doc)

        <ContentView.Content>
            <StackLayout VerticalOptions="Center" HorizontalOptions="Center" Spacing="0">
                <CarouselView ItemsSource="{Binding Source={x:Reference Root}, Path=Numbers}" 
                              CurrentItem="{Binding Source={x:Reference Root}, Path=Number}"
                              IsSwipeEnabled="{Binding Source={x:Reference Root}, Path=IsSwipeEnabled}">
                    <CarouselView.ItemsLayout>
                        <LinearItemsLayout Orientation="Vertical" />
                    </CarouselView.ItemsLayout>
                    <CarouselView.ItemTemplate>
                        <DataTemplate>
                            <Label x:Name="NumberLabel" Text="{Binding ., StringFormat='{}{0:D2}'}" FontSize="Title" VerticalOptions="Center" 
                                   HorizontalOptions="Center" HorizontalTextAlignment="Center" VerticalTextAlignment="Center"
                                   WidthRequest="50" TextColor="White"/>
                        </DataTemplate>
                    </CarouselView.ItemTemplate>
                </CarouselView>
    
                <BoxView HeightRequest="2" BackgroundColor="White" VerticalOptions="Start" HorizontalOptions="FillAndExpand"/>
            </StackLayout>
        </ContentView.Content>
    
    public partial class NumberPicker : ContentView
    {
        public static readonly BindableProperty NumberProperty = BindableProperty.Create(nameof(Number), typeof(int), typeof(NumberPicker), 0);
        public static readonly BindableProperty IsSwipeEnabledProperty = BindableProperty.Create(nameof(IsSwipeEnabled), typeof(bool), typeof(DigitPicker), true);
    
        public List<int> Numbers { get; } = new (Enumerable.Range(0, 59));
    
        public bool IsSwipeEnabled
        {
            get => (bool)GetValue(IsSwipeEnabledProperty);
            set
            {
                SetValue(IsSwipeEnabledProperty, value);
                OnPropertyChanged(nameof(IsSwipeEnabled));
            }
        }
    
        public int Number
        {
            get => (int)GetValue(NumberProperty);
            set => SetValue(NumberProperty, value);
        }
    
    
        public NumberPicker()
        {
            InitializeComponent();
        }
    }