Can anyone come up with a Custom Renderer solution to change the color of the underline in Android?

Viewed 205

I have a Xamarin forms application that uses this code:

<Grid
    HeightRequest="50"
    VerticalOptions="CenterAndExpand"
    x:Class="J.Templates.EntryGrid"
    x:Name="this"
    xmlns ="http://xamarin.com/schemas/2014/form
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" >
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="Auto"/>
        <ColumnDefinition Width="*"/>
        <ColumnDefinition x:Name="lastColumnWidth" Width="150"/>
    </Grid.ColumnDefinitions>
    <Label Grid.Column="0" Text="{Binding Text1, Source={x:Reference this}}"  />
    <Entry Grid.Column="1"
               HorizontalOptions="FillAndExpand"
               HorizontalTextAlignment="End"
               VerticalOptions="FillAndExpand"
               TextColor="{DynamicResource LabelLinkColor}"
               Keyboard="{Binding EntryKeyboardType,  Source={x:Reference this}}"
               Text="{Binding EntryText,  Source={x:Reference this}}"
               FontSize="{DynamicResource LabelTextFontSize}"
               FontFamily="{DynamicResource DefaultFont}"
               BackgroundColor="Transparent"
    </Entry>
</Grid>

The iOS and Android views look like this:

enter image description here

Is there any way I can change the Android underline color and also (if possible) spacing of the gap between the underline and the numbers.

1 Answers

If you wish to remove the underline, then you have to do it in a Custom Renderer.

[assembly: ExportRenderer(typeof(Entry), typeof(CustomEntryRenderer))]
namespace CustomEntryUnderline.Android
{
    public class CustomEntryRenderer : EntryRenderer
    {
        public CustomEntryRenderer(Context context)
            : base(context)
        {
        }

        protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
        {
            base.OnElementChanged(e);

            if (Control != null)
            {
                Control.Background = null;
            }
        }
    }
}

If you wish to change the underline color, you have to create a Color state list resource.

In the Android project, under Resources folder, create a new directory Color. In it, create a xml file, describing the selector drawable. Let's call it editable_selector.xml. Here's how it will look like:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true" android:color="#00ff00"/>
    <item android:state_focused="true" android:color="#ff0000"/>
    <item android:state_active="false" android:color="#0000ff"/>
</selector>

Here, you can change a lot of things, but in the xml selector, I have set the border to be blue by default, green when pressed and red when focused.

Then in your renderer, you'll have to set the native view's BackgroundTintList. We'll be doing this again in the OnElementChanged method.

protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
{
    base.OnElementChanged(e);
    if (Control != null)
    {
        var colorStateList = Context.GetColorStateList(Resource.Color.editable_selector);
        Control.BackgroundTintList = colorStateList;
    }
}

Here's a running gif:

enter image description here

You don't need to change the "gap", just adjust your layout, because currently the issue is not with the default offset, but with the way the layout is being rendered. Changing the offset should be considered a last resort.

However, if you still want to change the bottom padding between the text and the bottom border, again, in the OnElementChanged method, set the Control's padding like this:

Control.SetPadding(0, 0, 0, 120);

Here, I have set only a bottom padding of 120.

NB: It is not considered a good approach to create a renderer that will override all elements. Here, for simplicity, I am exporting the renderers for the built-in Entry type. It is better to wrap the Entry inside your own CustomEntry class in order to not modify the styles globally.

Related