How to limit EditText length to 6 integers and 3 decimal places in C#(MonoDroid)?

581 Views Asked by At

Hello, I'm new here, don't be so hard, I'm creating a project in Xamarin.Andriod using c #.

I am trying to do a validation of an EditText in Xamarin.Android (C # / MonoDroid).

The condition that I must fulfill is as follows: 'It allows entering 6 integers and 3 decimal places, in a range from 0 to 999999.999'

I have found some possible solutions in java (I don't know much and I have not been able to implement them in C #) and they are the following:

TextWatcher with Java

InputFilter with Java

I don't know how to apply it in C #, if someone could explain or give me a simple example but in C #.

this is my EditText:

                    ```<EditText
                        android:id="@+id/etVolume"
                        android:layout_width="@dimen/value_zero"
                        android:hint="Volumen"
                        android:textColor="@color/grisPrimario"
                        android:layout_height="fill_parent"
                        android:layout_weight="5"
                        android:textSize="@dimen/fluidListItem_text_size"
                        android:inputType="numberDecimal"
                        android:maxLength ="9"
                        android:textColorHint="@android:color/darker_gray"
                        android:backgroundTint="@color/grisPrimario"
                        android:gravity="bottom"
                        android:layout_marginBottom="-3dp"
                        android:layout_marginRight="@dimen/fluidListItemMarginRight"/>```

and my fragment is defined this EditText like this:

Volume = itemAdministeredFluid.FindViewById<EditText>(Resource.Id.etVolume);

etVolume.setFilters(new Android.Text.IInputFilter[] {new DecimalDigitsInputFilter(6,3)});

but i don't understand how to implement the method.

I saw that with java they use "TextWatcher" and "InputFilter" but I don't understand how to change it to C#

I appreciate any help I've spent days on this.

Thank you very much for the help.

3

There are 3 best solutions below

1
On BEST ANSWER

It allows entering 6 integers and 3 decimal places, in a range from 0 to 999999.999'

I create IInputFilter that you can take a look:

 public class DecimalDigitsInputFilter : Java.Lang.Object, IInputFilter
{
    private double _min = 0;
    private double _max = 0;

    public DecimalDigitsInputFilter(double min, double max)
    {
        _min = min;
        _max = max;
    }

    public ICharSequence FilterFormatted(ICharSequence source, int start, int end, ISpanned dest, int dstart, int dend)
    {
        try
        {
            string val = dest.ToString().Insert(dstart, source.ToString());
            if (val.Contains("."))
            {
                string[] array = val.Split(".");
                string value1 = array[0].ToString();
                string value2 = array[1].ToString();

                if (value1.Length > 6|| value1=="")
                {                      
                }
                else
                {
                    if(value2!="" && value2.Length<=3)
                    {
                        double input = double.Parse(val);
                        if (IsInRange(_min, _max, input))
                            return null;

                    }
                    else if(value2=="")
                    {
                        if(IsInRange(_min,_max,double.Parse(value1)))
                        {
                            return null;
                        }
                    }                      
                }
            }
            else
            {
               if(val.Length<=6)
                {
                    double input = double.Parse(val);
                    if (IsInRange(_min, _max, input))
                        return null;
                }                                   
            }                 

        }
        catch (System.Exception ex)
        {
            Console.WriteLine("FilterFormatted Error: " + ex.Message);
        }

        return new Java.Lang.String(string.Empty);


    }
    private bool IsInRange(double min, double max, double input)
    {
        return max > min ? input >= min && input <= max : input >= max && input <= min;
    }
}

 edittext1 = FindViewById<EditText>(Resource.Id.editText1);
 edittext1.SetFilters(new Android.Text.IInputFilter[] {new DecimalDigitsInputFilter(0,999999.999) });
2
On

It is better to do that in code, add a function to check inside TextWatcher. Since this will be called whenever the user types something.

In that function, you can check your condition and display an error message if the condition does not satisfy.

editText.addTextChangedListener(new TextWatcher() {
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {

    // call checkNumber() function here

}

@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {

    // TODO Auto-generated method stub
}

@Override
public void afterTextChanged(Editable s) {

    // TODO Auto-generated method stub
}
});

In C#

public class TextWatcher : Java.Lang.Object, ITextWatcher
{
public void AfterTextChanged(IEditable s)
{
    //
}

public void BeforeTextChanged(ICharSequence s, int start, int count, int after)
{
    //
}

public void OnTextChanged(ICharSequence s, int start, int before, int count)
{
    //
}

}

Add the listener to your EditText

editText.AddTextChangedListener(new TextWatcher());
0
On

It solves it as follows using InputFilter:

In the Fragment:

public EditText Volume;
Volume = itemAdministeredFluid.FindViewById<EditText>(Resource.Id.etVolume);
Volume.SetFilters(new IInputFilter[] { new DecimalDigitsInputFilter(6, 3) });
public class DecimalDigitsInputFilter : Java.Lang.Object, IInputFilter
    {
        string regexStr = string.Empty;

        public DecimalDigitsInputFilter(int digitsBeforeZero, int digitsAfterZero)
        {
            regexStr = "^[0-9]{0," + (digitsBeforeZero) + "}([.][0-9]{0," + (digitsAfterZero - 1) + "})?$";
        }

        public Java.Lang.ICharSequence FilterFormatted(Java.Lang.ICharSequence source, int start, int end, ISpanned dest, int dstart, int dend)
        {
            Regex regex = new Regex(regexStr);

            if (regex.IsMatch(dest.ToString()) || dest.ToString().Equals(""))
            {
                if (dest.ToString().Length < 6 && source.ToString() != ".")
                {
                    return new Java.Lang.String(source.ToString());
                }
                else if (source.ToString() == ".")
                {
                    return new Java.Lang.String(source.ToString());
                }
                else if (dest.ToString().Length >= 7 && dest.ToString().Length <= 10)
                {
                    return new Java.Lang.String(source.ToString());
                }
                else
                {
                    return new Java.Lang.String(string.Empty);

                }
            }

            return new Java.Lang.String(string.Empty);
        }
    }

In the AXML

                        <EditText
                            android:id="@+id/etVolume"
                            android:layout_width="@dimen/value_zero"
                            android:hint="Volumen"
                            android:textColor="@color/grisPrimario"
                            android:layout_height="fill_parent"
                            android:layout_weight="5"
                            android:textSize="@dimen/fluidListItem_text_size"
                            android:inputType="numberDecimal"
                            android:maxLength ="10"
                            android:textColorHint="@android:color/darker_gray"
                            android:backgroundTint="@color/grisPrimario"
                            android:gravity="bottom"
                            android:layout_marginBottom="-3dp"
                            android:layout_marginRight="@dimen/fluidListItemMarginRight"/>

This response can be improved and the filters removed by modifying and building the ReGex better.

it works completely. does not allow entering more values after entering the 6 decimal places, the condition only allows entering the point (.) and then the 3 decimal places.

I think it can be cleaner if you create a better RegEx.

revising I am left with a condition that to change the integers the entire value must be deleted.

If you have a cleaner answer I hope to see it to implement it.