Xamarin.Forms on Android: How to remove the Uppercase from a button text

If you create a button on Android and write its text in lowercase (“my text”), when you launch the app, you can see that the text is all uppercase (“MY TEXT”).This is not a bug but the standard style for Android.Sometimes we prefer to have our text in lowercase so here I’ll show you different methods to do it.First of all, consider a very easy Page:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"             
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"             
             xmlns:local="clr-namespace:Tutorial02"             
             x:Class="Tutorial02.MainPage">
    <Button Text="My Text!"            
            VerticalOptions="Center"            
            HorizontalOptions="Center" />
</ContentPage>

If we run the app on Android, we see that the button text will be : “MY TEXT!” all uppercase. Now let’s see how we can make it lowercase:

CUSTOM RENDERERS

First of all, create an empty class MyButton in you PCL/.NetStandard project:

public class MyButton : Button
{        
}

Now we have to replace the Button with MyButton:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"             
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"             
             xmlns:local="clr-namespace:Tutorial02"             
             x:Class="Tutorial02.MainPage">
    <local:MyButton Text="My Text!"    <- CHANGE HERE          
                    VerticalOptions="Center"            
                    HorizontalOptions="Center" />
</ContentPage>

The next step is to create the custom render, so inside the Android project, create the class MyButtonRenderer:

[assembly: ExportRenderer(typeof(MyButton), typeof(MyButtonRenderer))]
namespace YOURNAMESPACEHERE
{
    public class MyButtonRenderer : ButtonRenderer
    {
        public MyButtonRenderer(Context context) : base(context)
        {
        }

        protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.Button> e)
        {
            base.OnElementChanged(e);
            var button = this.Control;
            button.SetAllCaps(false);
        }
    }
}

It’s very important to add the first line[assembly: ExportRenderer(typeof(MyButton), typeof(MyButtonRenderer))]otherwise the Custom Renderer will not work.If we run the code, we see that now the button text is: “My Text!”.

EDIT THE STYLES.XML FILE

In your Android project open the styles.xml file inside the folder “Resources/values”, it will be something similar to:

<style name="MainTheme" parent="MainTheme.Base">  </style>
  <!-- Base theme applied no matter what API -->
  <style name="MainTheme.Base" parent="Theme.AppCompat.Light.DarkActionBar">
    <!--If you are using revision 22.1 please use just windowNoTitle. Without android:-->
    <item name="windowNoTitle">true</item>
    <!--We will be using the toolbar so no need to show ActionBar-->
    <item name="windowActionBar">false</item>
    <!-- Set theme colors from http://www.google.com/design/spec/style/color.html#color-color-palette -->
    <!-- colorPrimary is used for the default action bar background -->
    <item name="colorPrimary">#2196F3</item>
    <!-- colorPrimaryDark is used for the status bar -->
    <item name="colorPrimaryDark">#1976D2</item>
    <!-- colorAccent is used as the default value for colorControlActivated         which is used to tint widgets -->
    <item name="colorAccent">#FF4081</item>
    <!-- You can also set colorControlNormal, colorControlActivated         colorControlHighlight and colorSwitchThumbNormal. -->
    <item name="windowActionModeOverlay">true</item>
    <item name="android:datePickerDialogTheme">@style/AppCompatDialogStyle</item>
  </style>
  <style name="AppCompatDialogStyle" parent="Theme.AppCompat.Light.Dialog">
    <item name="colorAccent">#FF4081</item>
  </style>

To this file add these lines:

<style name="myTheme" parent="Theme.AppCompat.NoActionBar">
    <item name="android:textAppearanceButton">@style/mybutton.text</item>
  </style>
  <style name="mybutton.text" parent="Base.TextAppearance.AppCompat.Button">
    <item name="textAllCaps">false</item>
    <item name="android:textAllCaps">false</item>
  </style>

so that your styles.xml will be:

<resources>
  <style name="MainTheme" parent="MainTheme.Base">  </style>
  <!-- Base theme applied no matter what API -->
  <style name="MainTheme.Base" parent="Theme.AppCompat.Light.DarkActionBar">
    <!--If you are using revision 22.1 please use just windowNoTitle. Without android:-->
    <item name="windowNoTitle">true</item>
    <!--We will be using the toolbar so no need to show ActionBar-->
    <item name="windowActionBar">false</item>
    <!-- Set theme colors from http://www.google.com/design/spec/style/color.html#color-color-palette -->
    <!-- colorPrimary is used for the default action bar background -->
    <item name="colorPrimary">#2196F3</item>
    <!-- colorPrimaryDark is used for the status bar -->
    <item name="colorPrimaryDark">#1976D2</item>
    <!-- colorAccent is used as the default value for colorControlActivated         which is used to tint widgets -->
    <item name="colorAccent">#FF4081</item>
    <!-- You can also set colorControlNormal, colorControlActivated         colorControlHighlight and colorSwitchThumbNormal. -->
    <item name="windowActionModeOverlay">true</item>
    <item name="android:datePickerDialogTheme">@style/AppCompatDialogStyle</item>
    <item name="android:textAppearanceButton">@style/mybutton.text</item>
  </style>
  <style name="AppCompatDialogStyle" parent="Theme.AppCompat.Light.Dialog">
    <item name="colorAccent">#FF4081</item>
  </style>
  <style name="myTheme" parent="Theme.AppCompat.NoActionBar">
    <item name="android:textAppearanceButton">@style/mybutton.text</item>
  </style>
  <style name="mybutton.text" parent="Base.TextAppearance.AppCompat.Button">
    <item name="textAllCaps">false</item>
    <item name="android:textAllCaps">false</item>
  </style>
</resources>

USE AN EFFECT

In your Android project create the class ButtonEffect:

[assembly: ResolutionGroupName("MyCompany")]
[assembly: ExportEffect(typeof(Tutorial02.Droid.ButtonEffect), "ButtonEffect")]

namespace Tutorial02.Droid
{
    public class ButtonEffect : PlatformEffect
    {
        protected override void OnAttached()
        {
            try
            {
                var control = Control as Android.Widget.Button;
                control.SetAllCaps(false);
            }
            catch (Exception ex)
            {
                Console.WriteLine("Cannot set property on attached control. Error: ", ex.Message);
            }
        }

        protected override void OnDetached()
        {
        }

        protected override void OnElementPropertyChanged(System.ComponentModel.PropertyChangedEventArgs args)
        {
            base.OnElementPropertyChanged(args);
        }
    }
}

In your PCL/.NetStandard project create the class ButtonEffect:

public class ButtonEffect : RoutingEffect
{
    public ButtonEffect() : base("MyCompany.ButtonEffect")
    {
    }
}

Now you need to change your ContentPage to attach the Effect to your button:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"             
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"             
             xmlns:local="clr-namespace:Tutorial02"             
             x:Class="Tutorial02.MainPage">
    <Button Text="My Text!"            
            VerticalOptions="Center"           
            HorizontalOptions="Center">
        <Button.Effects>
            <local:ButtonEffect />
        </Button.Effects>
    </Button>
</ContentPage>

Conclusion

We have seen three methods to remove the Uppercase from your Android button:

  • Custom Renderers
  • Styles
  • Effects

All the methods do the same thing so it’s up to you to decide which method to use. Remember that Custom Renderers and Effects are very important in Xamarin so it’s important to understand them very well.