How to do fractions in an Android editText. Inputfilter? Custom IME?

883 views Asked by At

I'm trying to write code for an editText which can accept imperial values { ie. 1 , 3/4 , 1 1/3}. So far, with a lot of help from StackOverflow, I have it just about nailed. But there are three things missing.

android:inputType="number" or numberSigned, numberDecimal, phone etc

none of these display the / key I need to enter data and the QWERTY keyboard is too cumbersome for a single keypress. I'm amazed there isn't a keyboard for this, what do the yanks do? Can I override and replace a single key on the stock keyboard, do I have to implement my own keyboard for this seemingly simple task?

I am also struggling with the logic which prevents the first character being a space or /. I can allow one of each in a given string no problem, I just can't prevent it being the first key. Additionally, when you enter a value - like "1 5/9" - if you backspace to the /, the flags are not reset, so you are prohibited from entering another /.

Code for the InputFilter is as follows:

imperial_filter = new InputFilter() {

        boolean canEnterSpace = true, canEnterSlash = true;
        public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {

            if (imperial_editText.getText().toString().equals("")) {

                canEnterSpace = true;
                canEnterSlash = true;

            }

            StringBuilder builder = new StringBuilder();

            for (int i = start; i < end; i++) {

                char currentChar = source.charAt(i);

                if (Character.isDigit(currentChar) || (Character.isWhitespace(currentChar) && canEnterSpace && canEnterSlash) || (currentChar == '/' && canEnterSlash)) {

                    builder.append(currentChar);

                    if (Character.isWhitespace(currentChar)) canEnterSpace = false;
                    if (currentChar == '/') canEnterSlash = false;

                }

            }

            return builder.toString();

        }

    };

And this one is a little more complex, slightly adapted from code already on StackOverflow:

public float testImperialString(String testString) {

    boolean goodInput = true, goodInputSpace = true, containsSpace = false;

    float result = 0, whole = 0;
    String fractions = "";

    if (testString.contains(" ")) {

        containsSpace = true;
        String pieces[] = testString.split(" ");

        try {

            whole = Float.parseFloat(pieces[0]);
            fractions = pieces[1];

        } catch (Exception e) {

            goodInputSpace = false;

        }

    } else fractions = testString;

    if (fractions.contains("/")) {

        //possible division
        String pieces[] = fractions.split("/");

        if (pieces.length != 2) {

            goodInput = false;

        } else {

            try {

                float numerator = Float.parseFloat(pieces[0]);
                float denominator = Float.parseFloat(pieces[1]);
                result = numerator / denominator;

            } catch (Exception e) {

                goodInput = false;

            }

        }

    }

    if (!testString.contains(" ") && !(result > 0)) {

        try {

            result = Float.parseFloat(testString);

        } catch (Exception e) {

            goodInput = false;

        }

    }

    Log.d(TAG, "Contains Space = " + containsSpace + " Good Input = " + goodInput + " Good InputSpace = " + goodInputSpace);

    return whole + result;

}

I run that result through a method which converts imperial measurements into a metric equivalent, that I can perform maths functions with.

TL:DR

  1. I need a number keyboard with a / symbol
  2. I need to prevent a space or / as the first letter of an input
  3. I need to re-allow a space or / input, if a previous occurrence in a string was deleted.
0

There are 0 answers