27

I am creating a Xamarin.Forms application on Android and I am trying to change the colour of the line below my Xamarin.Forms Entry control.

I have an Entry control like so:

<Entry Text="new cool street"/>

enter image description here

I would like to change the colour of the line below this Entry from the default white to more of a purple to match my theme.

Idealy it would be better to do using Android Styles as it would apply to all controls inheriting from Entry if possible

Is this possible to do?

JKennedy
  • 18,150
  • 17
  • 114
  • 198
  • User android styles. `@android:color/yourcolour` – Akash Amin Jul 05 '16 at 15:34
  • @AkashAmin The `colorAccent` is only used when the `TextBox` is focused. I am looking to change the line colour when the `TextBox` is unfocused – JKennedy Jul 05 '16 at 15:53
  • Possible duplicate of [How to change Border Color of Entry in Xamarin.Forms](http://stackoverflow.com/questions/37822668/how-to-change-border-color-of-entry-in-xamarin-forms) – Rodrigo Elias Jul 05 '16 at 17:33

10 Answers10

45

you can use custom renderer that will affect all entries,

here's for android:

[assembly: ExportRenderer(typeof(Entry), typeof(MyEntryRenderer))]
namespace Android.MyRenderers
{
    public class MyEntryRenderer : EntryRenderer
    {
        protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
        {
            base.OnElementChanged(e);

            if (Control == null || e.NewElement == null) return;

            if (Build.VERSION.SdkInt >= BuildVersionCodes.Lollipop)
                Control.BackgroundTintList = ColorStateList.ValueOf(Color.White);
            else
                Control.Background.SetColorFilter(Color.White, PorterDuff.Mode.SrcAtop);
         }    
    }
}

and iOS:

[assembly: ExportRenderer (typeof(Entry), typeof(MyEntryRenderer))]
namespace iOS.MyRenderers
{
    public class MyEntryRenderer : EntryRenderer
    {
        private CALayer _line;

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

            if (Control == null || e.NewElement == null)
                return;

            Control.BorderStyle = UITextBorderStyle.None;

            _line = new CALayer {
                BorderColor = UIColor.FromRGB(174, 174, 174).CGColor,
                BackgroundColor = UIColor.FromRGB(174, 174, 174).CGColor,
                Frame = new CGRect (0, Frame.Height / 2, Frame.Width * 2, 1f)
            };

            Control.Layer.AddSublayer (_line);
        }
    }
}

not sure about Windows solution on this

root
  • 2,327
  • 1
  • 22
  • 18
28

I had the same problem and just changing the colorAccent value in styles.xml (in Xamarin.Android project) will change the colour of the cursor and the bottom border of an Entry field.

<item name="colorAccent">#BA55D3</item>
Curiosity
  • 1,753
  • 3
  • 25
  • 46
10

Since I have the content pages with one background color and dialogs with another, using Styles to specify the bottom bar color is totally the wrong answer. And since the OP only asked about Android, this is just Android...

I use a custom renderer to set the bottom bar color the same as the text color. Have to both ElementChanged and PropertyChanged.

[assembly: ExportRenderer(typeof(Xamarin.Forms.Entry), typeof(CustomEntryRenderer))]
namespace XamFormsConnect.Droid
{
    public class CustomEntryRenderer : EntryRenderer
    {
        protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.Entry> e)
        {
            base.OnElementChanged(e);

            if (Control != null && e.NewElement != null)
            {
                var entry = (Xamarin.Forms.Entry)e.NewElement;
                if (Build.VERSION.SdkInt >= BuildVersionCodes.Lollipop)
                    Control.BackgroundTintList = ColorStateList.ValueOf(entry.TextColor.ToAndroid());
                else
                    Control.Background.SetColorFilter(entry.TextColor.ToAndroid(), PorterDuff.Mode.SrcAtop);
            }
        }

        protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            base.OnElementPropertyChanged(sender, e);

            if (e.PropertyName == "TextColor")
            {
                var entry = (Xamarin.Forms.Entry)sender;
                if (Build.VERSION.SdkInt >= BuildVersionCodes.Lollipop)
                    Control.BackgroundTintList = ColorStateList.ValueOf(entry.TextColor.ToAndroid());
                else
                    Control.Background.SetColorFilter(entry.TextColor.ToAndroid(), PorterDuff.Mode.SrcAtop);
            }
        }
    }
}
djunod
  • 4,876
  • 2
  • 34
  • 28
  • 4
    I like how this answer uses the TextColor property instead of hard-coding "White" like the accepted answer. – CodeGrue Jan 15 '18 at 21:17
5

UPDATE : Xamarin.Forms 2.5

I've trying the top rated solution and an error occurs : “Context is obsolete as of version 2.5. Please use a local context instead”.

After some quick search :

The code need to be updated :

using <YOUR_APP_NAME>.Droid;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
using Android.Content;
using Android.OS;
using Android.Content.Res;
using Android.Graphics;

[assembly: ExportRenderer(typeof(Entry), typeof(MyRenderers))]
namespace Android.MyRenderers
{
    public class MyRenderers : EntryRenderer
    {

        public MyRenderers(Context context) : base(Android.App.Application.Context)
        {

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

            if (Control == null || e.NewElement == null) return;

            if (Build.VERSION.SdkInt >= BuildVersionCodes.Lollipop)
                Control.BackgroundTintList = ColorStateList.ValueOf(Android.Graphics.Color.Ivory);
            else
                Control.Background.SetColorFilter(Android.Graphics.Color.Ivory, PorterDuff.Mode.SrcAtop);
        }
    }
}

For who need the update.

PaulCrp
  • 624
  • 1
  • 8
  • 19
2

simple: edit your res/values/colors.xml as: #303F9F

You can place any hex color code in place of#303F9F

<color name="colorPrimaryDark">#303F9F</color>
Ram Koti
  • 2,203
  • 7
  • 26
  • 36
  • Where do I implement this color to apply it to my `Entry`? So far this is just defining a new Color – JKennedy Jul 05 '16 at 15:56
  • see [https://developer.xamarin.com/guides/android/user_interface/material_theme/](https://developer.xamarin.com/guides/android/user_interface/material_theme/) for more info on what I mean – JKennedy Jul 05 '16 at 16:08
2

If anyone is experiencing the width or y position misbehaving with root's iOS custom renderer, I found a solution.

  1. Include the entry and two more variables as class fields:
private CustomEntry _entry;
private double _yPos;
private double _width;
  1. Assign the value in OnElementChanged:
if (e.NewElement != null)
    _entry = e.NewElement as CustomEntry;
  1. In OnElementPropertyChanged, include the following:
if (e.PropertyName == "Width")
{
    _width = _entry.Width;
}
else if (e.PropertyName == "Height")
{
    _yPos = _entry.Height;
}
_line.Frame = new CGRect(0, _yPos, _width, 1f);
mahclark
  • 305
  • 1
  • 2
  • 10
0

If you are using Xamarin Forms, go to Mobile.Droid, Resources, values and on the "Your Colur", it will work.

0

Another simple visual solution that you can use is just to hide this line:

<Grid>
   <Entry Placeholder="Your Entry"/>
   <BoxView BackgroundColor="White" HeightRequest="10"/>
</Grid>

You can improve it by creating your own component instead of using hardcoded color.

Bb23
  • 1
  • 3
0

Change the entry cursor & underline color from pink in android. This can be achieved simply by adding <item name="colorControlActivated">#007bff</item> to your styles.xml file, which resides in Resources/values folder in the Xamarin forms Android project.

Note: this approach will apply the changes to every element within your app. If that is not desired, use the custom renderer approach.

Can reference this answer from xamarin forums

chri3g91
  • 1,196
  • 14
  • 16
0

Above solution is obsolete. This one here is the recommended one. (Also with all the neccissary usings. Can be confusing sometimes...)

using System;
using System.ComponentModel;
using Android.Content;
using Android.Content.Res;
using InteriorCircle.Droid.CustomComp;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;

[assembly: ExportRenderer(typeof(Entry), typeof(CustomEntry))]
namespace InteriorCircle.Droid.CustomComp
{
    public class CustomEntry : EntryRenderer
    {
        public CustomEntry(Context context) : base(context)
        {

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

            if (Control == null || e.NewElement == null) return;

            Control.BackgroundTintList = Android.Content.Res.ColorStateList.ValueOf(Android.Graphics.Color.Black);
        }

        protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            base.OnElementPropertyChanged(sender, e);
            if (e.PropertyName == Entry.TextProperty.PropertyName)
            {
                if (Control.Text.Length > 6)  //this is your condition(For example, here is the length of the text content)
                {
                    Control.BackgroundTintList = ColorStateList.ValueOf(Android.Graphics.Color.Red);
                }
                else
                {
                    Control.BackgroundTintList = ColorStateList.ValueOf(Android.Graphics.Color.Black);
                }
            }
        }

    }
}
innom
  • 770
  • 4
  • 19