As a Xamarin Forms developer sometimes all you need is a way to ensure that users of your application only enter specific characters into Entry views. For me, it was to restrict the entry to numeric characters and a single decimal.

The Entry view has a Keyboard property which allows you to define a Numeric keyboard, which works great on Android, however, for iOS, it only partially works. When running the application on an iOS phone it does only show the numeric keyboard however it doesn’t restrict the decimals, an issue I wanted to solve when entering the data.

The easiest way was to achieve my EntryView restriction was to create an Effect. Here is the routing effect code:

public class EntryNumberRestriction : RoutingEffect
{
    public EntryNumberRestriction() : base("RSK.EntryNumberRestriction")
{
}
}

Nothing interesting here but there is definitely scope to extend this to have a bindable property to define your restricted character set. For now, let’s keep it simple.

As Android worked out-the-box I did not create an effect, however, you could achieve other restrictions by using an Input Filter and applying it to the EditText control like this:

editText.SetFilters(new IInputFilter[] { new DecimalFilter(2)});

Here is the iOS effect code:

public class EntryNumberRestrictionIos : PlatformEffect
    {
        protected override void OnAttached()
        {
            if (Control is UITextField textField)
            {
                textField.ShouldChangeCharacters = (field, range, replacementString) =>
                {
                    var boolIsNumber = Regex.IsMatch(replacementString, @"[0-9.]");
                    if (boolIsNumber)
                    {
                        if (replacementString.Contains("."))
                        {
                            var countdots = field.Text.ToCharArray().Count(x => x == '.');
                            if (countdots >= 1)
                            {
                                return false;
                            }
                        }
                        return true;
                    }
                    return false;
                };
            }
        }
        protected override void OnDetached()
        {
        }
    }

Let's take a walk over the code. This effect is only useful for UITextField views so I have ensured that any other view type is ignored.

The best way in iOS to restrict what is entered into a UITextFiled is to use a UITextFiledChange delegate. From the delegate, we can get access to the UITextField and the value being entered before it is committed to the UITextField. Returning True from the delegate informs iOS to commit the new character and if it is False, to throw it away.

As you can see I use a regular expression to restrict the new value to be a number or a decimal then from there I then proceed to ensure that only 1 decimal exists in the UITextField. Text value, throwing away all other decimals.

Thank you for reading! If you have any questions regarding EntryView in Xamarin please don't hesitate to email me: chris.myhill@rocksolidknowledge.com

About the author