【问题标题】:Xamarin Forms Entry: Use comma as decimal separatorXamarin 表单条目:使用逗号作为小数分隔符
【发布时间】:2018-08-09 10:01:56
【问题描述】:

我想在带有数字键盘的 Xamarin Forms 条目中使用逗号作为小数分隔符。我将文化设置为CultureInfo.DefaultThreadCurrentCulture = new CultureInfo("de-DE");,并且, 显示在键盘上,但该条目仅接受. 作为分隔符,并且仅在我使用电话键盘时才有效。这似乎是一个Andoid Bug。 Xamarin Forms 有解决方案吗?

【问题讨论】:

    标签: xamarin xamarin.forms


    【解决方案1】:

    有。

    为了让它正常工作,我建议您执行以下操作:

    在您的共享代码中创建一个名为“NumericInput”的新类,从 Entry 派生:

    public class NumericInput : Entry
    {
        public static BindableProperty AllowNegativeProperty = BindableProperty.Create("AllowNegative", typeof(bool), typeof(NumericInput), false, BindingMode.TwoWay);
        public static BindableProperty AllowFractionProperty = BindableProperty.Create("AllowFraction", typeof(bool), typeof(NumericInput), false, BindingMode.TwoWay);
    
        public NumericInput()
        {
            this.Keyboard = Keyboard.Numeric;
        }
    
        public bool AllowNegative
        {
            get { return (bool)GetValue(AllowNegativeProperty); }
            set { SetValue(AllowNegativeProperty, value); }
        }
    
        public bool AllowFraction
        {
            get { return (bool)GetValue(AllowFractionProperty); }
            set { SetValue(AllowFractionProperty, value); }
        }
    }
    

    然后在你的 android 项目中为它创建一个自定义渲染器:

    [assembly: ExportRenderer(typeof(NumericInput), typeof(NumericInputRenderer))]
    namespace MyApp.Droid.Renderer
    {
    public class NumericInputRenderer : EntryRenderer
    {
        public NumericInputRenderer(Context context) : base(context)
        {
    
        }
    
        private EditText _native = null;
    
        protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
        {
            base.OnElementChanged(e);
    
            if (e.NewElement == null)
                return;
    
            _native = Control as EditText;
            _native.InputType = Android.Text.InputTypes.ClassNumber;
            if ((e.NewElement as NumericInput).AllowNegative == true)
                _native.InputType |= InputTypes.NumberFlagSigned;
            if ((e.NewElement as NumericInput).AllowFraction == true)
            {
                _native.InputType |= InputTypes.NumberFlagDecimal;
                _native.KeyListener = DigitsKeyListener.GetInstance(string.Format("1234567890{0}", System.Globalization.CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator));
            }
            if (e.NewElement.FontFamily != null)
            {
                var font = Typeface.CreateFromAsset(Android.App.Application.Context.Assets, e.NewElement.FontFamily);
                _native.Typeface = font;
            }
        }
    
        protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            base.OnElementPropertyChanged(sender, e);
            if (_native == null)
                return;
    
            if (e.PropertyName == NumericInput.AllowNegativeProperty.PropertyName)
            {
                if ((sender as NumericInput).AllowNegative == true)
                {
                    // Add Signed flag
                    _native.InputType |= InputTypes.NumberFlagSigned;
                }
                else
                {
                    // Remove Signed flag
                    _native.InputType &= ~InputTypes.NumberFlagSigned;
                }
            }
            if (e.PropertyName == NumericInput.AllowFractionProperty.PropertyName)
            {
                if ((sender as NumericInput).AllowFraction == true)
                {
                    // Add Decimal flag
                    _native.InputType |= InputTypes.NumberFlagDecimal;
                    _native.KeyListener = DigitsKeyListener.GetInstance(string.Format("1234567890{0}", System.Globalization.CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator));
                }
                else
                {
                    // Remove Decimal flag
                    _native.InputType &= ~InputTypes.NumberFlagDecimal;
                    _native.KeyListener = DigitsKeyListener.GetInstance(string.Format("1234567890"));
                }
            }
        }
    }
    }
    

    这将创建一个条目元素,它会根据设备的当前文化设置自动使用正确的小数分隔符。

    由于该类允许进行一些详细设置,因此我还应该添加 iOS 渲染器:

    [assembly: ExportRenderer(typeof(NumericInput), typeof(NumericInputRenderer))]
    namespace MyApp.iOS.Renderer
    {
    public class NumericInputRenderer : EntryRenderer
    {
        private UITextField _native = null;
    
        protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
        {
            base.OnElementChanged(e);
    
            if (e.NewElement == null)
                return;
    
            _native = Control as UITextField;
    
            _native.KeyboardType = UIKeyboardType.NumberPad;
    
            if ((e.NewElement as NumericInput).AllowNegative == true && (e.NewElement as NumericInput).AllowFraction == true)
            {
                _native.KeyboardType = UIKeyboardType.NumbersAndPunctuation;
            } 
            else if ((e.NewElement as NumericInput).AllowNegative == true)
            {
                _native.KeyboardType = UIKeyboardType.NumbersAndPunctuation;
            }
            else if ((e.NewElement as NumericInput).AllowFraction == true)
            {
                _native.KeyboardType = UIKeyboardType.DecimalPad;
            }
            else
            {
                _native.KeyboardType = UIKeyboardType.NumberPad;
            }
            if (e.NewElement.FontFamily != null)
            {
                e.NewElement.FontFamily = e.NewElement.FontFamily.Replace(".ttf", "");
            }
        }
    
        protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            base.OnElementPropertyChanged(sender, e);
            if (_native == null)
                return;
        }
    }
    }
    

    但是请记住,一些供应商已经实施了自定义软键盘(我在看着你,三星!),甚至不显示逗号作为小数分隔符。在这种情况下,唯一的解决方案是安装另一个键盘,例如 SwiftKey 或 Gboard。但是,如果显示逗号,您应该可以将它与上面的代码一起使用。

    【讨论】:

    • 逗号显示在键盘上。但是我仍然不能将它用作此解决方案的分隔符。例如,如果我想输入1,5,我可以输入1,,但是当我输入5 时,数字会被格式化为15System.Globalization.CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator 正确设置为逗号。
    • 所以您输入的文本是“1,5”,对吧?那么由于混合设置,您可能会遇到解析问题。检索结果时,请尝试为双重解析指定当前区域性:double.Parse(myEntry.Text, CultureInfo.CurrentCulture)。如果由于一些有趣的系统区域设置,double.parse 将双精度格式解释为非德语,那么如果您输入“1,5”,您将“正确”地从解析中得到 15。反之亦然,如果我在德国手机上解析“1.5”,我也会从中得到 15。
    • 我添加了一个十进制转换器来解决解析问题。现在您的解决方案工作正常。非常感谢!
    • 太棒了!只需添加一个词:用户可能仍使用剪贴板粘贴十进制字符串,如“1,5”。我建议将用户输入绑定到字符串属性并在属性的设置器中使用 int.TryParse 来检查输入的值是否真的是正确的整数。
    猜你喜欢
    • 1970-01-01
    • 2014-07-16
    • 1970-01-01
    • 1970-01-01
    • 2013-11-03
    • 2016-02-10
    • 1970-01-01
    • 2017-09-30
    • 1970-01-01
    相关资源
    最近更新 更多