Workaround for Xamarin MaskedBehavior jumping cursor issue - 12-digit number with spaces after every four of them

Viewed 88

I'm trying to create an Entry for a 12-digit number with spaces after every four digits.

I tried to use StringFormat but it doesn't work completely. From what I've read, it works well for Labels that operate on specified texts, not Entries.

I used MaskedBehavior from Xamarin Community Toolkit

<Entry 
   Margin="25,0,25,0"
   Keyboard="Numeric">
   <Entry.Behaviors>
       <xct:MaskedBehavior Mask="XXXX XXXX XXXX"/>
   </Entry.Behaviors>
</Entry>

but it appears to have an issue with cursor jumping to the end every time when user types something in the middle of an Entry or removing a digit from there. I opened an issue report on XCT GitHub page but haven't received an answer yet: https://github.com/xamarin/XamarinCommunityToolkit/issues/1879

Masked Behavior issue

Since this Mask has an issue, I abandonded this idea for a while and tried to create a Converter:

public class SerialNumberConverter : IValueConverter
{
    /// <summary>
    /// Removes spaces from the serial number before sending the number further to the code.
    /// </summary>
    public object ConvertBack(object value, Type targetType, object parameter,
        System.Globalization.CultureInfo culture)
    {
        return value is string str
            ? str.Replace(" ", "") 
            : null;
    }

    /// <summary>
    /// Adds spaces to the serial number to display it in a more user-friendly way on the layout.
    /// </summary>
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if (!(value is string str))
        {
            return null;
        }

        for (var i = 4; i <= str.Length; i += 4)
        {
            // edge case: space shouldn't be added once user types in the 12th digit of the serial number
            if (i == 14 && str.Length == 14) break;

            str = str.Insert(i, " ");
            i++;
        }

        return str;
    }
}

But it has the same issue.

I tried to operate on Entry.CursorPosition in Converter and custom Renderer, but it behaves weirdly. It works correctly every second time. First time, it does what I want, the second time - it moves to position 0 and then to the end of an Entry. Looking at the logs, I can see the event resposible for implying text changed fires twice then, independently of my code.

Did any of you handle this kind of situation? I even checked my bank mobile application and styling of bank account number works well, so it has to be possible.

The only idea I have right now is to create a Grid with four columns and spacing between them, but that would require creating the whole styling for the control again, so I'm trying to avoid that.

0 Answers
Related