π Seamless UX with Auto-Formatting π
Have you ever struggled with users entering messy credit card numbers? Say no more! Implement a custom MAUI Behavior that formats credit card numbers dynamically as users type. π¦π³
How It Works
β
Automatically insert spaces every 4 digits (e.g., 1234 5678 9012 3456).
β
Maintains correct cursor position while typing or deleting.
β
Removes non-numeric characters automatically.
β
Enhances user experience with clean and readable input.
Code Implementation
`public class CardNumberFormatterBehavior : Behavior
{
private bool _isUpdating = false;
protected override void OnAttachedTo(Entry entry)
{
entry.TextChanged += OnEntryTextChanged;
base.OnAttachedTo(entry);
}
protected override void OnDetachingFrom(Entry entry)
{
entry.TextChanged -= OnEntryTextChanged;
base.OnDetachingFrom(entry);
}
private void OnEntryTextChanged(object sender, TextChangedEventArgs args)
{
if (_isUpdating || !(sender is Entry entry))
return;
_isUpdating = true;
try
{
int cursorPosition = entry.CursorPosition;
if (string.IsNullOrEmpty(args.NewTextValue))
{
entry.Text = string.Empty;
entry.CursorPosition = 0;
return;
}
int oldSpacesBeforeCursor = 0;
if (!string.IsNullOrEmpty(args.OldTextValue) && cursorPosition <= args.OldTextValue.Length)
{
oldSpacesBeforeCursor = args.OldTextValue.Substring(0, cursorPosition).Count(c => c == ' ');
}
int oldDigitsBeforeCursor = cursorPosition - oldSpacesBeforeCursor;
string cleanText = new string(args.NewTextValue.Where(char.IsDigit).ToArray());
string formattedText = FormatCardNumber(cleanText);
entry.Text = formattedText;
int newCursorPosition;
if (args.NewTextValue.Length > args.OldTextValue?.Length)
{
int spacesInFormattedTextUpToDigits = 0;
int digitCount = 0;
for (int i = 0; i < formattedText.Length && digitCount < oldDigitsBeforeCursor + 1; i++)
{
if (formattedText[i] == ' ')
{
spacesInFormattedTextUpToDigits++;
}
else
{
digitCount++;
}
}
newCursorPosition = oldDigitsBeforeCursor + spacesInFormattedTextUpToDigits + 1;
}
else
{
int spacesInFormattedTextUpToDigits = 0;
int digitCount = 0;
for (int i = 0; i < formattedText.Length && digitCount < oldDigitsBeforeCursor; i++)
{
if (formattedText[i] == ' ')
{
spacesInFormattedTextUpToDigits++;
}
else
{
digitCount++;
}
}
newCursorPosition = oldDigitsBeforeCursor + spacesInFormattedTextUpToDigits;
}
newCursorPosition = Math.Max(0, Math.Min(formattedText.Length, newCursorPosition));
entry.CursorPosition = newCursorPosition;
}
finally
{
_isUpdating = false;
}
}
private string FormatCardNumber(string cardNumber)
{
if (string.IsNullOrEmpty(cardNumber))
return string.Empty;
StringBuilder result = new StringBuilder();
for (int i = 0; i < cardNumber.Length; i++)
{
if (i > 0 && i % 4 == 0)
result.Append(" ");
result.Append(cardNumber[i]);
}
return result.ToString();
}
}`
How to Use It in Your MAUI App
Simply attach the behavior to an Entry in XAML:
<Entry Placeholder="Enter card number">
<Entry.Behaviors>
<local:CardNumberFormatterBehavior />
</Entry.Behaviors>
</Entry>
Why Use This?
π Improves data consistency.
π― Reduces user input errors.
π§ Works seamlessly in .NET MAUI apps.
Would you add any improvements to this behavior? Drop your thoughts below! β¬οΈπ¬
Top comments (0)