MAUI UI July 2023 – Replicating Wolt app

For my last year’s contribution to the .NET MAUI UI July event, I replicated the F1 TV app. This year I decided to replicate the Wolt app, which is a food delivery service here in Norway.

Here’s a screenshot of the Wolt app running on Android:

I will be replicating the “front page” of this app (as shown above), even though there are other screens to this app. Some things might be a bit off, like the font and the tabbar highlight color.

Getting started

Since this app uses some icons, I wanted to use the old reliable Material icons. I used this great NuGet package AathifMahir.Maui.MauiIcons.Material in order to easily use all the material icons directly in my XAML. Check it out here.

As a main page here, I am using a Tabbed Page, since the main view has a tab bar on the bottom.

Top section

The top section displays your preferred location of delivery, which you can toggle with the expand button on the right. In this screenshot it says “Din nåværende lokasjon”, meaning “Your current location”. For demonstration purposes I have just made this a non-interactive MauiIcon using the NuGet package I mentioned (same goes for the GPS icon), but it could just as well have been a Button.

<HorizontalStackLayout Margin="16,10" VerticalOptions="Center">
            <Border
                Padding="6"
                BackgroundColor="#ecf7fd"
                Stroke="Black"
                StrokeThickness="0">
                <Border.StrokeShape>
                    <RoundRectangle CornerRadius="30" />
                </Border.StrokeShape>
                <material:MauiIcon
                    Icon="GpsFixed"
                    IconColor="#00bce1"
                    IconSize="22" />
            </Border>
            <Label
                FontAttributes="Bold"
                Text=" Din nåværende posisjon"
                TextColor="#00bce1"
                VerticalOptions="Center" />
            <material:MauiIcon
                Padding="6"
                Icon="ExpandMore"
                IconColor="#00bce1" />
        </HorizontalStackLayout>

Carousel section

The carousel section displays some videos or still images of different restaurants or special offers. I used a CarouselView here, as it is the obvious choice for a carousel, with some hard-coded item templates for demonstration purposes. It also contains an IndicatorView, which are the ellipsis underneath the carousel. The section also contains a subtitle along with a Button to show all offers.

<CarouselView IndicatorView="indicatorView">
                <CarouselView.ItemTemplate>
                    <DataTemplate>
                        <Border WidthRequest="300">
                            <Border.StrokeShape>
                                <RoundRectangle CornerRadius="10" />
                            </Border.StrokeShape>
                            <Image HeightRequest="230" Source="restaurant.jpg" />
                        </Border>
                    </DataTemplate>
                </CarouselView.ItemTemplate>
                <CarouselView.ItemsSource>
                    <x:Array Type="{x:Type x:String}">
                        <x:String>test</x:String>
                        <x:String>test</x:String>
                        <x:String>test</x:String>
                        <x:String>test</x:String>
                        <x:String>test</x:String>
                        <x:String>test</x:String>
                        <x:String>test</x:String>
                    </x:Array>
                </CarouselView.ItemsSource>
            </CarouselView>
            <IndicatorView
                x:Name="indicatorView"
                Grid.Row="1"
                HorizontalOptions="Center"
                VerticalOptions="Center" />
            <Grid Grid.Row="2" Margin="16,0">
                <Label
                    FontAttributes="Bold"
                    FontSize="18"
                    HorizontalOptions="StartAndExpand"
                    Text="Gatematfestival er her! 💃"
                    VerticalOptions="Center" />
                <Button
                    BackgroundColor="#ecf7fd"
                    HeightRequest="40"
                    HorizontalOptions="End"
                    Text="Vis alle"
                    TextColor="#00bce1" />
            </Grid>

To fake the items in the list, I added some dummy items directly to the XAML as CarouselView.ItemsSource so that the item template would be duplicated X amount of times.

Featured section

The featured section displays currently featured restaurants along with some offers. This is a horizontally scrolled list, so I went with a horizontal CollectionView. The item template uses some Grids to properly place the elements. The discount section uses Border in order to set the corner radius on selected corners.

 <CollectionView Grid.Row="2" ItemsLayout="HorizontalList">
            <CollectionView.ItemTemplate>
                <DataTemplate>
                    <Border Margin="10,0" WidthRequest="300">
                        <Border.StrokeShape>
                            <RoundRectangle CornerRadius="12" />
                        </Border.StrokeShape>
                        <Grid>
                            <Image HeightRequest="200" Source="pizza.jpg" />
                            <Grid RowDefinitions="28, *, 20, 40">
                                <Border
                                    Margin="0,0,14,0"
                                    BackgroundColor="#009de0"
                                    HorizontalOptions="End"
                                    StrokeThickness="0"
                                    WidthRequest="55">
                                    <Border.StrokeShape>
                                        <RoundRectangle CornerRadius="0,0,6,6" />
                                    </Border.StrokeShape>
                                    <Label
                                        FontAttributes="Bold"
                                        HorizontalOptions="Center"
                                        Text="-25%"
                                        TextColor="White"
                                        VerticalOptions="Center" />
                                </Border>
                                <Label
                                    Grid.Row="2"
                                    Padding="10,0,0,0"
                                    FontAttributes="Bold"
                                    FontSize="17"
                                    Text="Mano Pizza"
                                    TextColor="White" />
                                <Label
                                    Grid.Row="3"
                                    Padding="10"
                                    FontAttributes="Bold"
                                    Text="På utvalgte Pizza"
                                    TextColor="White" />
                            </Grid>
                        </Grid>
                    </Border>
                </DataTemplate>
            </CollectionView.ItemTemplate>
            <CollectionView.ItemsSource>
                <x:Array Type="{x:Type x:String}">
                    <x:String>test</x:String>
                    <x:String>test</x:String>
                    <x:String>test</x:String>
                </x:Array>
            </CollectionView.ItemsSource>
        </CollectionView>

Ad section

The bottom section contains an ad promoting some of the Wolt services. Here I opted for an easy route and just display this as an Image. If we wanted this to be clickable, we could have added a click event handler or used some EventToCommand-behavior to bind it to a command.

<StackLayout Grid.Row="3">
            <Image
                Margin="10"
                Source="ad.png"
                VerticalOptions="EndAndExpand" />
        </StackLayout>

Tab section

As mentioned in the beginning, the main page uses a TabbedPage to display the tabs at the bottom. I use the mentioned NuGet package to set material icons here as the icons.

Here’s how it looks in my tabbed page:

<TabbedPage
    x:Class="MAUIUIJuly2023.TabbedPage"
    xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:android="clr-namespace:Microsoft.Maui.Controls.PlatformConfiguration.AndroidSpecific;assembly=Microsoft.Maui.Controls"
    xmlns:local="clr-namespace:MAUIUIJuly2023"
    xmlns:material="clr-namespace:MauiIcons.Material;assembly=MauiIcons.Material"
    android:TabbedPage.ToolbarPlacement="Bottom">
    <local:MainPage Title="Discovery" IconImageSource="{material:Icon Icon=LocationCity}" />
    <local:MainPage Title="Restauranter" IconImageSource="{material:Icon Icon=Fastfood}" />
    <local:MainPage Title="Butikker" IconImageSource="{material:Icon Icon=Store}" />
    <local:MainPage Title="Søk" IconImageSource="{material:Icon Icon=Search}" />
    <local:MainPage Title="Profil" IconImageSource="{material:Icon Icon=Person}" />
</TabbedPage>

Notice how I’m setting the toolbar placement at the bottom, since the default location for tab bars on Android is at the top.

That’s a wrap!

I hope you liked this post and that you follow Twitter this month for all the other contributions that are coming. Check out Matt Goldman’s post for a full overview. The sample code for this Wolt app is located on my GitHub, check that out too!

1 thought on “MAUI UI July 2023 – Replicating Wolt app”

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.