This is the fifth blog post in the "Building the Logify Client App" series. If you have not followed the series in its entirety, please use the following links to review our previous posts.
- Xamarin.Forms UI Controls - Building the Logify Client App (Part 1)
- Xamarin.Forms UI Controls - Building the Logify Client App (Part 2)
- Xamarin.Forms UI Controls - Building the Logify Client App (Part 3)
- Xamarin.Forms UI Controls - Building the Logify Client App (Part 4)
In our previous blog post, we detailed our four-tab layout and why we chose this UI metaphor for the Logify client app. To recap – though we prefer simple navigation options, complex apps often require more advanced navigation logic.
As you know, we used the DevExpress DrawerPage within the Logify client to deliver the best possible user experience. This control incorporates a navigation side menu panel and is a good option if you need to incorporate additional UI elements, such as folders or filter selectors.
Filter View – Our Implementation
Logify allows users to purchase multiple subscriptions and each subscription can include multiple development teams. An account holder can belong to single team within a given subscription or to multiple teams across multiple subscriptions.
As you can see in the screenshot above, the Logify Mobile client includes built-in filters to restrict incoming crash/exception report traffic based on subscription, team, app name, and report status. The reason for these filters is quite simple – without a way to filter information and restrict results by app and status, Logify’s report list would be overwhelming.
Of course, we could have created a user interface that allows users to apply filters within the results grid itself (without using the filter panel), but we felt that it’s best to apply to filter before data is displayed. This approach allows us to reduce HTTP traffic between server and client.
The application filter itself uses the DevExpress Xamarin DataGrid with a single DataTemplate column. The cell within the column consists of a Xamarin Forms grid with a couple of cells. These cells contain the app name and selection indicator.
The status filter uses Xamarin.Forms FlexLayout with BindableLayout for binding the status ItemTemplate. You can review the full markup using this link.
<?xml version="1.0" encoding="UTF-8"?> <Grid x:Name="reportsFilterView" x:Class="Logify.Views.ReportsFilterView"> <Grid.BindingContext> <vm:ReportsFilterViewModel/> </Grid.BindingContext> <Grid Grid.Row="0" HeightRequest="28" Margin="24,0" IsVisible="{Binding Source={x:Static vm:SubscriptionsViewModel.Instance}, Path=IsMultiItems}"> <Label Grid.Column="0" Text="SUBSCRIPTION" FontAttributes="Bold"/> <controls:PickerView Grid.Column="1" Title="SUBSCRIPTION" ItemsSource="{Binding Source={x:Static vm:SubscriptionsViewModel.Instance}, Path=Items}" SelectedItem="{Binding Source={x:Static vm:SubscriptionsViewModel.Instance}, Path=SelectedItem, Mode=TwoWay}"/> </Grid> ... <BoxView Grid.Row="2" Color="{DynamicResource FiltersStatusItemBorderColor}"/> <StackLayout Grid.Row="3"> <Grid> ... <Label Grid.Row="0" Style="{StaticResource FilterLabelsBoldStyle}" FontAttributes="Bold" Text="APPLICATIONS"/> <dxg:DataGridView Grid.Row="1" RowTapCommand="{Binding ApplicationTapCommand}" ItemsSource="{Binding Applications}"> <dxg:DataGridView.Columns> <dxg:TemplateColumn> <dxg:TemplateColumn.DisplayTemplate> <DataTemplate> <Grid HeightRequest="30"> ... <Label Grid.Column="0" Text="{Binding Item.Name}" TextColor="{Binding Item.Selected, Converter={StaticResource selectedToLabelColorConverter}}"/> <editors:IconView Grid.Column="1" ImageSource="cross.svg" ForegroundColor="{Binding Item.Selected, Converter={StaticResource selectedToIconColorConverter}}"/> </Grid> </DataTemplate> </dxg:TemplateColumn.DisplayTemplate> </dxg:TemplateColumn> </dxg:DataGridView.Columns> </dxg:DataGridView> </Grid> <Grid> ... <BoxView Grid.Row="0" Color="{DynamicResource FiltersStatusItemBorderColor}"/> <Label Text="STATUS FILTER" FontAttributes="Bold"/> <ScrollView Grid.Row="2"> <FlexLayout BindableLayout.ItemsSource="{Binding Statuses}"> <BindableLayout.ItemTemplate> <DataTemplate x:DataType="vm:StatusInfo"> <locals:ReportFilterStatus Status="{Binding Status}" IsSelected="{Binding Selected}" SelectedChangedCommand="{Binding BindingContext.SelectedChangedCommand, Source={x:Reference reportsFilterView}}"/> </DataTemplate> </BindableLayout.ItemTemplate> </FlexLayout> </ScrollView> </Grid> </StackLayout> </Grid>
DrawerPage – Our Implementation
The DevExpress DrawerPage control offers flexible appearance and size customization options for its UI elements. You can customize popover behavior, on-screen location (display the DrawerPage on the left, right, top, or bottom) and appearance (for example, DrawerPage allows you to enable shadow and customize its appearance). Additionally, our DrawerPage control looks much the same on both mobile platforms.
To use the DrawerPage, we first add the control to the DrawerReportsFilterView. We then set the DrawerContent and MainContent properties of the DrawerPage class instance. DrawerContent holds the contents of the slide drawer, and MainContent is responsible for main page content.
<?xml version="1.0" encoding="UTF-8"?> <dxn:DrawerPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:dxn="clr-namespace:DevExpress.XamarinForms.Navigation;assembly=DevExpress.XamarinForms.Navigation" xmlns:views="clr-namespace:Logify.Views" xmlns:editors="clr-namespace:DevExpress.XamarinForms.Editors;assembly=DevExpress.XamarinForms.Editors" x:Class="Logify.Views.DrawerReportsFilterView"> <dxn:DrawerPage.DrawerContent> <views:ReportsFilterView x:Name="reportsFilterView" /> </dxn:DrawerPage.DrawerContent> <dxn:DrawerPage.MainContent> <NavigationPage> <x:Arguments> <views:ReportsView> <NavigationPage.TitleView> <AbsoluteLayout HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand"> <Label AbsoluteLayout.LayoutBounds="1,1,1,1" AbsoluteLayout.LayoutFlags="All" Text="REPORTS" FontAttributes="Bold" VerticalOptions="Center" HorizontalOptions="Center" /> <StackLayout AbsoluteLayout.LayoutBounds="1,0.5,40,24" AbsoluteLayout.LayoutFlags="PositionProportional"> <StackLayout.GestureRecognizers> <TapGestureRecognizer Tapped="Handle_FilterButtonClicked" /> </StackLayout.GestureRecognizers> <editors:IconView ImageSource="Filter.svg" ForegroundColor="{DynamicResource TitleIconColor}" WidthRequest="24" HeightRequest="24" HorizontalOptions="End"> <editors:IconView.Margin> <OnPlatform x:TypeArguments="Thickness" Android="0,0,16,0" iOS="0,0,4,0" /> </editors:IconView.Margin> </editors:IconView> </StackLayout> </AbsoluteLayout> </NavigationPage.TitleView> </views:ReportsView> </x:Arguments> </NavigationPage> </dxn:DrawerPage.MainContent> </dxn:DrawerPage>
DrawerPage Customization
As you might expect, we now need to customize the DrawerPage so it mirrors our design. We set DrawerPosition to the right side of the screen and specify DrawerBehavior (in our case, we need to push the contents of the main page to the side). We also need to specify DrawerWidth and DrawerContentHeight. You can review the full markup using this link.
In our next post, we’ll show you how we customized the app’s Report Detail view and how you can leverage our Xamarin Data Grid to deliver some amazing user experiences.
Application Source Code
For those who’ve been wondering...we will share the source code for the Logify Mobile client once we’ve completed this blog post series. Should you have any questions in the interim, please post your comments below.