Skip to content

Instantly share code, notes, and snippets.

@wagenheimer
Last active February 4, 2025 22:02
Show Gist options
  • Select an option

  • Save wagenheimer/fab8835a872da49d232ba86992017b48 to your computer and use it in GitHub Desktop.

Select an option

Save wagenheimer/fab8835a872da49d232ba86992017b48 to your computer and use it in GitHub Desktop.
Samsung Keyboard Decimal Fix for Xamarin.Forms (Android)

Xamarin.Forms Custom Renderer for Samsung Keyboard Decimal Handling

A culture-aware solution to enforce proper decimal separators (./,), specifically addressing Samsung keyboard limitations in Xamarin.Forms Android apps.

Key Features:

  • Auto-detects Samsung keyboards using package name/device manufacturer
  • Replaces unwanted decimal separators based on system culture
  • Preserves cursor position during text modifications
  • Input validation for single decimal points
  • Compatible with Keyboard.Numeric and Keyboard.Default

Tested on Samsung devices with One UI 4.1+/Android 12+. Works with both physical/virtual keyboards.

Problem Statement :

Samsung keyboards often show . instead of , for decimal inputs in regions using comma-separated decimals. This renderer:

  • Detects Samsung keyboard/device combinations
  • Automatically converts between separators
  • Maintains native keyboard performance

Usage

<Entry Keyboard="Numeric" /> <!-- Works automatically! -->

Implementation Highlights

// Culture-aware decimal handling
private string decimalSeparator = CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator;
private string alternativeSeparator = decimalSeparator == "." ? "," : ".";

// Samsung detection logic
private bool IsSamsungKeyboard()
{
    // Combines package name checks and manufacturer fallback
    return packageName.Contains("samsung") || 
           Android.OS.Build.Manufacturer?.Contains("Samsung") == true;
}

// Input sanitization
Control.KeyListener = DigitsKeyListener.GetInstance($"0123456789{decimalSeparator}-");

Compatibility

  • Xamarin.Forms 5.0+
  • Android API 21+
  • Tested on Galaxy S20/S22/Note series

Related Resources

  1. Xamarin.Forms Custom Keyboard Example
  2. Android Keycode Reference
  3. CultureInfo Documentation

using System;
using System.Globalization;
using System.Linq;
using Android.Content;
using Android.Provider;
using Android.Text;
using Android.Text.Method;
using Android.Views.InputMethods;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
using TextChangedEventArgs = Android.Text.TextChangedEventArgs;
[assembly: ExportRenderer(typeof(Entry), typeof(CustomNumericEntryRenderer))]
public class CustomNumericEntryRenderer : EntryRenderer
{
public CustomNumericEntryRenderer(Context context) : base(context)
{
}
protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
{
base.OnElementChanged(e);
if (e.NewElement == null || Control == null || Context == null)
return;
// Check if input type is numeric
if (Control.InputType != Keyboard.Numeric.ToInputType())
return;
// Check for Samsung keyboard
if (IsSamsungKeyboard())
{
// Get the current culture's decimal separator
string decimalSeparator = CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator;
string acceptedCharacters = "0123456789" + decimalSeparator + "-";
// Configure key listener to accept specific characters
Control.KeyListener = DigitsKeyListener.GetInstance(acceptedCharacters);
// Set input type to numeric with decimal support
Control.InputType = InputTypes.ClassNumber |
InputTypes.NumberFlagDecimal |
InputTypes.NumberFlagSigned;
// Ensure event handler is attached only once
Control.TextChanged -= OnTextChanged;
Control.TextChanged += OnTextChanged;
}
}
private bool IsSamsungKeyboard()
{
try
{
var inputMethodManager = (InputMethodManager) Context.GetSystemService(Context.InputMethodService);
// Obter o ID do método de entrada atual
string currentInputMethodId = Settings.Secure.GetString(
Context.ContentResolver,
Settings.Secure.DefaultInputMethod);
if (!string.IsNullOrEmpty(currentInputMethodId))
{
// Obter informações do método de entrada
var inputMethodInfo = inputMethodManager.EnabledInputMethodList
.FirstOrDefault(imi => imi.Id == currentInputMethodId);
if (inputMethodInfo != null)
{
string packageName = inputMethodInfo.PackageName?.ToLower();
return packageName.Contains("samsung") || packageName.Contains("sec");
}
}
// Fallback para fabricante
return Android.OS.Build.Manufacturer?.ToLower().Contains("samsung") == true;
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"Keyboard detection error: {ex.Message}");
return false;
}
}
private void OnTextChanged(object sender, TextChangedEventArgs e)
{
var control = (Android.Widget.EditText) sender;
// Store current cursor position
int cursorPosition = control.SelectionStart;
// Remove event to prevent recursion
control.TextChanged -= OnTextChanged;
try
{
string newText = control.Text;
string decimalSeparator = CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator;
string alternativeSeparator = decimalSeparator == "." ? "," : ".";
// Replace alternative decimal separator with the current culture's decimal separator
if (newText.Contains(alternativeSeparator))
{
newText = newText.Replace(alternativeSeparator, decimalSeparator);
}
// Limit to a single decimal separator
int separatorIndex = newText.IndexOf(decimalSeparator);
if (separatorIndex != -1)
{
// Keep only the first decimal separator
string beforeSeparator = newText.Substring(0, separatorIndex + 1);
string afterSeparator = newText.Substring(separatorIndex + 1).Replace(decimalSeparator, string.Empty);
newText = beforeSeparator + afterSeparator;
}
// Update text if modified
if (control.Text != newText)
{
control.Text = newText;
// Reposition cursor
control.SetSelection(Math.Min(cursorPosition, newText.Length));
}
else if (cursorPosition > newText.Length)
{
control.SetSelection(newText.Length);
}
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"Error in OnTextChanged: {ex.Message}");
}
finally
{
// Reattach the event handler
control.TextChanged += OnTextChanged;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment