Use Comma as decimal separator for android EditText with MvvmCross

I'm developing an application for Android using Xamarin with MvvmCross. I have an EditText defined this way:

<EditText
            local:MvxBind="Text PorcentagemDesconto"
            android:inputType="number|numberDecimal"
            android:nextFocusDown="@+id/valorDesconto"
            android:layout_width="1dp"
            android:layout_weight="0.3"
            android:layout_height="wrap_content"
            android:hint="%"
            android:focusableInTouchMode="true" />

When I click on the EditText, the keyboard don't gives me the option to insert a Comma, only a Dot to use as decimal separator. The problem here is that when I insert the number 2.22 for example, the Binding assumes that the value is 222, because my device is using the pt-BR locale, that uses commas for decimals and dots for thousands.

I already did the following to solve the problem:

Created a ValueConverter that replaces the dot for the comma

public class DecimalValueConverter : MvxValueConverter
{
    public override object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return value;
    }

    public override object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        var strValue = value?.ToString();
        if (string.IsNullOrEmpty(strValue))
            return null;

        strValue = strValue.Replace(".", ",");

        return strValue;
    }
}

but this way, as soon as the user enters the first decimal digit, the cursor moves to the start of the EditText, so, I also used the TextChanged event of the EditText to set the selection on the end of the input to solve that.

var porcentagemDesconto = v.FindViewById<EditText>(Resource.Id.porcentagemDesconto);
porcentagemDesconto.TextChanged += (s, e) =>
{
    Activity.RunOnUiThread(() =>
    {
        if (porcentagemDesconto.Text != null)
        {
            porcentagemDesconto.SetSelection(porcentagemDesconto.Text.Length);
        }
    });
};

But to be honest, I did not like this solution. I would need to either write the event code for ALL my EditTexts that accespt decimals, or create a custom view that does that.

I find very hard to belive that I would need to create a custom view and a ValueConverter just to use a comma as a decimal separator, so, I'm wondering if there's a better way to solve my problem.

EDIT:

I've also already tried to use the android:digits="0123456789,-", but this way the comma don't appear on the keyboard, only the dot. The only difference is that this way, when I click the dot, nothing happens.

Upvotes: 1

Views: 4977

Answers (1)

Sven-Michael St&#252;be
Sven-Michael St&#252;be

Reputation: 14760

That's an Android bug that is unfixed since 2009.

You have to set android:digits.

<EditText
    local:MvxBind="Text PorcentagemDesconto"
    android:inputType="number|numberDecimal"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:hint="%"
    android:digits="0123456789,-"
    android:focusableInTouchMode="true" />

If you want to deploy your app for different countries, you have to use a string resource android:digits="@string/localized_digits with

values-de/strings.xml e.g. german

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="localized_digits">0123456789,-</string>
</resources>

values/strings.xml default

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="localized_digits">0123456789.-</string>
</resources>

Or use a more generic approach and set it via code:

// extension method
public static class EditTextExtension
{
    public static void FixDigits(this EditText text)
    {
        var decimalSign = CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator;
        var digits = $"0123456789{decimalSign}-";
        text.KeyListener = DigitsKeyListener.GetInstance(digits);
    }
}

// usage
FindViewById<EditText>(Resource.Id.txtNumber).FixDigits();

Or you add thr functionality of the extension method FixDigits() to your custom EditText class.

Upvotes: 4

Related Questions