Material Design - James Montemagno https://staging.montemagno.com/tag/material-design/ https://staging.montemagno.com/content/images/2017/08/MonogramIcon_Orange_NoBuffer.png Material Design - James Montemagno https://staging.montemagno.com/tag/material-design/ Hugo -- gohugo.io Tue, 13 Oct 2026 23:21:57 GMT 60 The Beautiful & Complex FlexLayout Comes to Hanselman.Forms https://staging.montemagno.com/flexlayout-image/ 5c821c36b2f3d500bff4c965 Fri, 08 Mar 2019 18:22:00 GMT

Last week I wrote about my new quest to fully optimize and enhance Hanselman.Forms. This involves using the latest and greatest in Xamarin.Forms and Xamarin.Essentials, but it also means spicing up the app with some lovely visuals and design. My first quest was to re-design the podcast section of the mobile app to create a list in grid form of different podcast that Hanselman produces.

So, first things first we should design a card to hold each podcast in. This can be accomplished with a simple Frame with a drop shadow on it:

<Frame
    Padding="0"
    VerticalOptions="Start"
    HasShadow="True">
    <Grid Padding="0">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <Image Source="{Binding Art}" Aspect="AspectFill"/>
        <Label Grid.Row="1" Margin="10,0" Text="{Binding Title}"/>
    </Grid>
</Frame>

This simple code results in a pretty nice look for album artwork:

Pod

I will absolutely want to try out the new Visual Frame/CardView enhancements now that Xamarin.Forms 3.6 is out to make sure it also looks great on iOS.

Wrapping Podcasts

Wrapping the multiple podcasts into columns and rows dymanically would be pretty ideal for something like a CollectionView, but it is still in preview. I thought instead that the the FlexLayout would be a great option because it can arrange its children horizontally and vertically in a stack in addition to wrapping items. Here is one of the samples from the documentation:

ExperimentAlignContent2-Large

Taking this concept I was able to combine the FlexLayout with a BindableLayout to make something pretty spectacular:

 <ScrollView>
    <FlexLayout BindableLayout.ItemsSource="{Binding Podcasts}"
           Wrap="Wrap"
           Direction="Row"
           JustifyContent="Start"
           AlignItems="Start"
           AlignContent="Start"
           Padding="8">
        <BindableLayout.ItemTemplate>
            <DataTemplate>
                <Grid Margin="4,4,4,4"
                      FlexLayout.Basis="{OnIdiom Phone='50%', Tablet='33%'}"
                      FlexLayout.AlignSelf="Start">

                   <local:PodcastCardView />

                </Grid>
            </DataTemplate>
        </BindableLayout.ItemTemplate>
    </FlexLayout>
</ScrollView>

It tooke me a long time how to figure out how to space each of the cards correctly and wrap to the next line while still starting on the left hand side. This was accomplished by setting all of the Align properties to Start as well as the JustifyContent. It resulted in a really great Android version:

53674791-420bf280-3c45-11e9-9438-eb608208ce7d

Better yet, when I ran it on UWP or changed the orientation the FlexLayout reacted very nicely:

ezgif.com-resize-1

Seeing this in action I was very content and wrapped up a great week 2 of live streaming updating the app on Twitch.

You can check out the full pull request on GitHub to see how I setup a full mock data source, handled tab transitions, and the final implementation for FlexLayout in the app. Don't forget that I am accepting pull requests and feature requests too on the official GitHub page.

My final take away thoughts are that while the FlexLayout is relatively complicated and has tons of little settings to tweak, it is still extremely powerful and worth dedicating some time to.

]]>
Modernizing Hanselman.Forms: A Customizable Brand Mobile App https://staging.montemagno.com/updating-hanselman-forms-bottom-tabs-bindable-layout/ 5c77172d720b5500bfd5d630 Fri, 01 Mar 2019 16:42:00 GMT

The night before we launched Xamarin.Forms in mid-2014, I was having a conversation with Nat about creating a nice out of the box real world example of a Xamarin.Forms app. We discussed several different app ideas, but we were short on time as it was already 8PM at night. Then I thought perhaps I could create an app for my idol and fellow Chipotle lover Scott Hanselman. Fast-forward 8 hours and several cups of coffee later and Hanselman.Forms was born! It was very simple with an about page, Twitter feed, and blog rss reader with a simple Master Detail setup:

Hanselman1

Scott liked it so much that he wrote an awesome blog about it.

Over the years it morphed to include an Android Wear and Apple Watch app that was featured at the .NET Conf keynote.

Over time I added more features such as circle images and podcast playback:

hanseman

The project has received several updates including migrating to the latest versions of Xamarin.Forms, .NET Standard, Xamarin.Essentials, and all of the NuGet packages that I use. However, it has never really gotten a great modern user interface make over. So, in 2019 I want to change that and I am kicking off the Hanselman.Forms modernization project!

This project will be on going on my Twitch stream where I will morphing this app into a beautiful modern design mobile app. I plan on using some of the latest features in Xamarin.Forms 4.0, adding offline sync, enhancing the audio player, changing the navigation, and who knows what else. I want it to be fun and interactive where we can work on the project together and make it a spectacular reference app. Last week I kicked off the first round of improvements, and here is what I accomplished.

Week 1 Accomplishments

Last week on my Twitch livestream I created a huge list of issues that can be worked on by anyone! I decided to start by creating a new vnext branch that we can work off together. I decided to start off by implementing new TabbedPage navigation with lovely bottom tabs on Android:

bottomtabs

After that it was off to re-factor all of the social links on the home page. In the past I had put a bunch of images with tap gesture recognizers on them.

<StackLayout Orientation="Horizontal"
         HorizontalOptions="CenterAndExpand"
         Spacing="10">

    <Image x:Name="twitter" Source="twitter.png"/>
    <Image x:Name="facebook" Source="facebook.png"/>
    <Image x:Name="instagram" Source="instagram.png"/>
</StackLayout>
twitter.GestureRecognizers.Add(new TapGestureRecognizer()
{
    Command = new Command(async () =>
    {
        //try to launch twitter or tweetbot app, else launch browser
        var launch = DependencyService.Get<ILaunchTwitter>();
        if (launch == null || !launch.OpenUserName("shanselman"))
            await Browser.OpenAsync("http://m.twitter.com/shanselman");
    })
});

facebook.GestureRecognizers.Add(new TapGestureRecognizer()
{
    Command = new Command(async () => await Browser.OpenAsync("https://m.facebook.com/shanselman"))
});

instagram.GestureRecognizers.Add(new TapGestureRecognizer()
{
    Command = new Command(async () => await Browser.OpenAsync("https://www.instagram.com/shanselman"))
});

This was very hacky code and didn't fit in with MVVM at all. Luckily we now have Bindable Layouts in Xamarin.Forms. So now, the XAML is all nice and organized and there is NO code in the code behind as it is all in the View Model :)

<StackLayout Orientation="Horizontal"
                     HorizontalOptions="CenterAndExpand"
                     Spacing="10" BindableLayout.ItemsSource="{Binding SocialItems}">
      <BindableLayout.ItemTemplate>
          <DataTemplate>
            <Image Source="{Binding Icon}">
              <Image.GestureRecognizers>
                    <TapGestureRecognizer
                            Command="{Binding OpenUrlCommand}" />
              </Image.GestureRecognizers>
            </Image>
          </DataTemplate>
      </BindableLayout.ItemTemplate>
</StackLayout>

I am thinking that I can probably get rid of the tap gesture recognizer and use the new ImageButton with a transparent background :)

Get Involved

I would love if you would come hang out with me as I code every Friday at 2PM Pacific live on Twitch so we can rev on this together. I am also interested in feature requests, design ideas, and reviewing pull requests live while I stream. Head over to the GitHub page to give it a star and submit or comment on some issues.

]]>
Xamarin.Forms: Drop Shadow/Elevation on Android Bottom Navigation TabbedPage https://staging.montemagno.com/xamarin-forms-drop-shadow-elevation-on-android-bottom-navigation-tabbedpage/ 5c6271e1720b5500bfd5d611 Thu, 14 Feb 2019 20:58:00 GMT

It is a tale as old of time fighting with Android elevation and drop shadows. First it was the Toolbar on a Navigation page and now it is the new fancy bottom tabs that we got in Xamarin.Forms 3.1. I know what you are thinking... another custom renderer... NOPE! You just have to know to set a few different properties correctly.

BeforeAfter

Here is what we are starting with:

<TabbedPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:android="clr-namespace:Xamarin.Forms.PlatformConfiguration.AndroidSpecific;assembly=Xamarin.Forms.Core"
             android:TabbedPage.ToolbarPlacement="Bottom"
             x:Class="GeoContacts.View.HomePage">
<!-- Pages Here-->
</TabbedPage>

As we can see there is no fancy shadow or elevation :(

Screenshot_20190211-164745

That Background Color!

The BottomNavigationView is a tricky beast regardless if you are in Android XML or Xamarin.Forms. To get a drop shadow/elevation on it you MUST set the background color! It is true, I even mentioned it way back in August 2017 when I wrote my original blog on it. All we need to do is set the background color on our TabbedPage and we are set:

BarBackgroundColor="{OnPlatform Android=White}"

And here we go:

Screenshot_20190211-163121

That is literally it! You can of course set it to any color you would like and you should still see a nice shadow appear to separate out your content. Now if for some reason you have to support a really really old device that doesn't support elevation, then you will have to do some custom work here. Don't worry as you can custom render it :)

Custom Android Layouts & Renderer

To do this manually you will need to create 2 resource files:

  • Resources/drawable/shadow.xml
  • Resource/layout/view_shadow.axml

The shadow.xml is a very simple reverse gradient:

<?xml version="1.0" encoding="utf-8" ?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <gradient
        android:startColor="#1F000000"
        android:endColor="@android:color/transparent"
        android:angle="90" />
</shape>

For the view_shadow.axml this is just a dummy view with the background set to shadow.

<View
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="4dp"
    android:background="@drawable/shadow"/>

Now, it is time for our custom renderer inside of our Android project. This code is actually very simple and just injects the view_shadow onto the top of our navigation view:

using Android.Views;
using Xamarin.Forms.Platform.Android.AppCompat;
using Xamarin.Forms.Platform.Android;
using Android.Support.Design.Widget;
using Android.Content;
using Android.Widget;

[assembly: ExportRenderer(typeof(TabbedPage), typeof(MyTabsRenderer))]
namespace GeoContacts.Droid
{
    public class MyTabsRenderer : TabbedPageRenderer
    {
        public MyTabsRenderer()
        {

        }
        public MyTabsRenderer(Context context)
        {

        }

        protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.TabbedPage> e)
        {
            base.OnElementChanged(e);

            if (!(GetChildAt(0) is ViewGroup layout))
                return;

            if (!(layout.GetChildAt(1) is BottomNavigationView bottomNavigationView))
                return;

            var topShadow = LayoutInflater.From(Context).Inflate(Resource.Layout.view_shadow, null);

            var layoutParams =
                new Android.Widget.RelativeLayout.LayoutParams(LayoutParams.MatchParent, 15);
            layoutParams.AddRule(LayoutRules.Above, bottomNavigationView.Id);

            layout.AddView(topShadow, 2, layoutParams);

        }
    }
}

There you have it! Regardless of your implementation the shadow adds some nice flare and takes minimal effort.

]]>
Material Design Theming for Xamarin.Forms Android Apps https://staging.montemagno.com/material-design-theming-for-xamarinforms-android/ 598df8f2c121b60019bf300d Sun, 05 Apr 2015 00:03:06 GMT Update: As of Xamarin.Forms 1.5.1 Material Design AppCompat is included! See the official blog to convert your app: https://blog.xamarin.com/material-design-for-your-xamarin-forms-android-apps/

I am an extremely big fan of Material Design for Android applications. Case and point is this tweet that I sent out last night:

Over the past six months have I present on Material Design at Xamarin Evolve and also at user groups and the number one question I get is: “How can we use Material Design in Xamarin.Forms?” 

That is a loaded question because Material Design is not only the core theming of the application, but it is custom controls, animations, transitions, and a plethora of other things. Check out Google’s Material Design guidelines  for everything that is really part of material design. 

When it comes to Xamarin.Forms and Material Design it is a tricky question. All the custom control, animations, transitions, and jazz like that you most likely will not be able to do with out some work and some renderers.  However, you still have the ability to add in a little Material Design Theming and of course you can follow proper spacing and guidelines on the 4dp grid.

The AppCompat Debate

Revision 21 of AppCompat v7 was pretty ground breaking. Traditionally, AppCompat brought the use of the ActionBar to older platforms, but Revision 21 changed all of this by bringing Material Design Themes and controls to older devices. This is important since Lollipop is currently 3.5% of the market! Currently, Xamarin.Forms does not use AppCompat which means we can not take advantage of the new compat theming, but there is NO reason that we can’t make our Lollipop users happy by adding a little material theming to their app. This will bring not only material design themes, but also all the fancy touch events, and other core Lollipop control features from the core OS, which will be very nice.

Base Styles:

The first step is to ensure that you have you Resources/values/styles.xml and base theme setup to use Holo. In your Android project under Resources/values simply create a new xml file and name it styles.xml. Then you can place this XML in it:

Next is to create our Lollipop specific styles under Resources/values-v21/styles.xml, which you will place:

I like to put all of my color resources in Resources/values/colors.xml, and this is what mine looks like, which you can see I am referencing in the values-v21/styles.xml:

Update ApplicationManifest.xml

You must now of course tell your Android app to use this new fancy theme that you have created by setting the android:theme attribute:

Remove App Icon from ActionBar

The new default in Lollipop is to hide the app icon from the main action bar and you can easily do this inside of your MainActivity.cs with just a few lines of code:

Update Hamburger Button (optional)

If you are using the MasterDetailPage you will want to update your hamburger icon so that on v21 it uses the new full triple line. You can do this by download the set from the Android Asset Studio and then creating new drawable folders with the extension of -v21 at the end like this:

Then you will set the Icon to “slideout.png” or whatever you called it for your MasterDetailPage.

Here is the final result of just a few minutes of work in my Hansleman.Forms app:

Nice new styling for the colors, larger action bar, better fonts, and of course a nice new hamburger button! So can you get Material Design in your Xamarin.Forms application? Absolutely, but you just don’t get everything and it is for a limited amount of users. However, the number of Lollipop users is only going up so why not add a bit of flare to your app?

]]>
Lollipop AppCompat PreferenceActivity https://staging.montemagno.com/lollipop-appcompat-preferenceactivity/ 598df8f2c121b60019bf3019 Sat, 03 Jan 2015 17:39:36 GMT I fell in love with material design the moment I saw it and at Evolve 2014 my good friend and co-worker Jérémie Laval and I actually gave 2 sessions on the concept and implementation of material design in your apps. With the introduction of v7 app compat library rev 21 you are now able to upgrade your apps while maintain compatibility with older versions of Android. If you are looking to get started integrating the support library into your apps then check out my samples over on the Xamarin documentation site. While transitioning my Bike Now app over to v7 appcompat I ran into one small issue, which is that there is no updated PreferenceActivity with a SupportActionBar or one that takes advantage of the new Toolbar and back arrow. However, there is an awesome workaround that will allow you to get that beautiful material design in your preference activity.

Special Themes

You should already have a base theme of your application that you are using that inherits from Theme.AppCompat of some sort that is used throughout your application, but you will need to create a new theme specific for the PreferenceActivity.

This will ensure that your toolbar is properly themed with the up indicator and will use your primary colors correctly as well, while still inheriting from your base theme.

Settings Layout

Normally with a preference activity there is no layout file at all because everything is generated for you through the preference xml file. However, we will actually need to insert a new v7 Toolbar at the top of the preference activity. I have a universal Toolbar that I use throughout my application that I specify in my Toolbar.axml and then I created a new Settings.axml which simply stacks the toolbar ontop of a FrameLayout that we will use later on to insert the main preference ListView.

Update PreferenceActivity

The last piece is to now trick our PreferenceActivity into using our new Settings.axml. This is done in the SetContentView where we will combine the two layouts together cleverly.

With that in place you are all set to now have a beautiful preference activity with the back arrow properly in place. In addition to this since you have a full Toolbar you can still use menu items and handle them appropriately as well.

]]>