With Maui being released, I probably won’t make too many more Xamarin.Forms tutorials, and besides there are a lot already. However, I am still currently working on Xamarin.Forms projects that still need some TLC and you probably are too.

So if you are ever in need of a drawer and want to know the simplest way to implement one, I’ve got just what you need. In my DrawerPOC repository on GitHub, I have thrown together a little sample of an animated pop-out drawer from the bottom using an mvvm pattern (no framework). Feel free to steal the code yourself, but notice the attribution I used for the icon. It’s not free. And the colors look a bit better an android, but you can change this to whatever you like. My son asked for blue, and that’s what we got!

The Drawer control:

Using a ContentView I created a reusable control that contains three buttons. The first button is the one you tap to pop open the drawer. Its an arrow that animates by flipping over to show you tap it again to close the drawer. Pretty simple.

<?xml version="1.0" encoding="UTF-8"?>
<ContentView xmlns="http://xamarin.com/schemas/2014/forms" 
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="DrawerPOC.BottomDrawerView">
  <ContentView.Content>
        <StackLayout
            VerticalOptions="End">
            <!--Icon by <a href="https://freeicons.io/profile/3">icon king1</a> on <a href="https://freeicons.io">freeicons.io</a>-->
            <ImageButton x:Name="drawerIcon"
                         Source="arrow.png" 
                         BackgroundColor="White" 
                         BorderColor="Black" 
                         HorizontalOptions="Center" 
                         Command="{Binding ToggleDrawerCommand}"/>
            <Line BackgroundColor="Black" HorizontalOptions="Fill" />
            <StackLayout Orientation="Horizontal"
                         BackgroundColor="Blue"
                         HorizontalOptions="FillAndExpand">
                <Button Text="Back" HorizontalOptions="FillAndExpand"/>
                <Button Text="Continue" HorizontalOptions="FillAndExpand"/>
            </StackLayout>
        </StackLayout>
    </ContentView.Content>
</ContentView>

The Code behind:

The code behind has the bindable properties and tracks the changes when the UI is notified. The magic is in the TranslateTo methods being called when the propertychanged is triggered on the bindable bool. You’ll notice that when it is closed it is set to the height of the button that activates the drawer to open and close.

using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Xamarin.Essentials;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;

namespace DrawerPOC
{
    [XamlCompilation(XamlCompilationOptions.Compile)]
    public partial class BottomDrawerView : ContentView
    {
        public BottomDrawerView()
        {
            InitializeComponent();
			Task.Run(async () = >await this.TranslateTo(0, 60, 600, Easing.SinInOut));
		}

		public static readonly BindableProperty IsSlideOpenProperty =
			BindableProperty.Create(
				nameof(IsSlideOpen),
				typeof(bool),
				typeof(BottomDrawerView),
				false,
				propertyChanged: SlideOpenClose);

		public bool IsSlideOpen
		{
			get => (bool)GetValue(IsSlideOpenProperty); 
			set =>  SetValue(IsSlideOpenProperty, value); 
		}
		
		private static async void SlideOpenClose(BindableObject bindable, object oldValue, object newValue)
		{
				if ((bool)newValue)
				{
					await (bindable as BottomDrawerView).TranslateTo(0, 0, 250, Easing.SinInOut);
					await (bindable as BottomDrawerView).drawerIcon.RotateTo(180);
			    }
				else
				{
					await (bindable as BottomDrawerView).TranslateTo(0, 60, 600, Easing.SinInOut);
					await (bindable as BottomDrawerView).drawerIcon.RotateTo(0);
				}
		}
	}
}

The View

Using the out of the box MainPage from the Xamarin.Forms shell project, I inserted my drawer control at the bottom and bound it to the viewmodel.

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:view="clr-namespace:DrawerPOC"
             x:Class="DrawerPOC.MainPage">
        <Grid>
        <StackLayout>
            <Frame BackgroundColor="#2196F3" Padding="24" CornerRadius="0">
                <Label Text="Welcome to Xamarin.Forms!" HorizontalTextAlignment="Center" TextColor="White" FontSize="36"/>
            </Frame>
            <Label Text="Start developing now" FontSize="Title" Padding="30,10,30,10"/>
            <Label Text="Make changes to your XAML file and save to see your UI update in the running app with XAML Hot Reload. Give it a try!" FontSize="16" Padding="30,0,30,0"/>
            <Label FontSize="16" Padding="30,24,30,0">
                <Label.FormattedText>
                    <FormattedString>
                        <FormattedString.Spans>
                            <Span Text="Learn more at "/>
                            <Span Text="https://aka.ms/xamarin-quickstart" FontAttributes="Bold"/>
                        </FormattedString.Spans>
                    </FormattedString>
                </Label.FormattedText>
            </Label>
        </StackLayout>
        <view:BottomDrawerView  
            IsSlideOpen="{Binding IsDrawerOpen}" />
    </Grid>
</ContentPage>

The ViewModel

Because I am not using an mvvm library, I needed to update the UI using INotifyPropertyChanged.

using System.ComponentModel;
using Xamarin.Forms;

namespace DrawerPOC
{
	internal class MainViewModel : INotifyPropertyChanged
	{
		public MainViewModel()
		{
			ToggleDrawerCommand = new Command(UpdateDrawerStatus);
		}

		public Command ToggleDrawerCommand { get; set; }
		
		public bool IsDrawerOpen { get; set; }

        public event PropertyChangedEventHandler PropertyChanged;

        private void UpdateDrawerStatus()
		{
			if (IsDrawerOpen)
			{
				IsDrawerOpen = false;
			}
			else
			{
				IsDrawerOpen = true;
			}

			PropertyChanged(this, new PropertyChangedEventArgs(nameof(IsDrawerOpen)));
		}
	}
}

App.Xaml.Cs

Because I didn’t use an ioc container or an mvvm library, I assigned the binding context here. You could also do it in the mainpage codebehind.

using System;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;

namespace DrawerPOC
{
    public partial class App : Application
    {
        private MainPage _mainPage = null;
        private MainViewModel _viewModel = null;
        public App()
        {
            _viewModel = new MainViewModel();
            _mainPage = new MainPage();
            _mainPage.BindingContext = _viewModel;
            
            InitializeComponent();
            
            MainPage = _mainPage;
        }

        protected override void OnStart()
        {   
        }

        protected override void OnSleep()
        {
        }

        protected override void OnResume()
        {
        }
    }
}

Conclusion

Its truly as simple as that. Not much more that has to happen to make a small amount of real estate to be fully functional. You can modify the code to make the drawers be on the sides or the top just by playing with the layout and x/y values. Good luck, and hope this helps!

Categories:

No responses yet

Leave a Reply

Follow Blog via Email

Enter your email address to follow this blog and receive notifications of new posts by email.

Join 99 other subscribers
Follow me on Twitter
Advertisements
%d bloggers like this: