|
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; |
|
} |
|
} |
|
} |