6

I'm developing an app with multiple input[type=numer] elements. Android only for now.

The built-in numeric keyboard has two problems:

 * it's inconsistent (different on different versions of Android)
 * it has unnecessary keys (space, dash, comma and "next") which add confusion.

I'd like to have a keyboard with just numbers, comma and backspace. Is that possible?

Edit Oct 3, 2013. A third problem appeared and it's by far the worst. It looks like Samsung decided to skip the decimal character (".") from their numeric keyboard, at least the one that pops when input[type=numer] gets the focus in the browser. It seems all Galaxy S4 devices are affected (I've seen it on the S4 Mini, I don't have access to many Samsung devices... all I see are Nexus lovers :-)). I couldn't find much about the issue in Google, but I've seen Galaxy S4 users complain about it in 2012 (I've tried it on one S3 a few weeks ago and it was OK).

Long story short, after a careful consideration I decided to implement my own keyboard in html/javascript (Samsung is too important, I'm getting bad reviews just because of it and I don't think I can do anything to fix it). I'm in the process of rewriting my app, I'll try to remember and tell the story when I'm done.

Edit Dec 3, 2013. My current solution (still in alpha stage, the app rewrite takes me way longer than I expected) is a keyboard implemented entirely in javascript. I used regular <span> elements instead of <input> to prevent OS keyboard from popping out. As an added benefit, I get to control everything about the keyboard, so I added a few arithmetical keys (x, -, *, /, ( and )) and the user can type in expressions, for example "3x(2+5.5)" instead of "15". I'll link to the app when it's ready (still at least a few more weeks).

muszek
  • 437
  • 6
  • 15

2 Answers2

1

Sure it is.

First, configure your activity to never show the keyboard (try android:windowSoftInputMode = "stateAlwaysHidden"). You may have some problems if EditText insists on pulling it up, but you can make a mock EditText based on TextView to go around that, or inherit EditText and override some methods. There are multiple guide on that, like here: Close/hide the Android Soft Keyboard

Second, create your own UI-keyboard element, with any buttons you want in however layout you want, and catch button presses on this keyboard, for each press, append the appropriate character to the EditText/TextView's displayed text.

That said, users may not like it. As much as you hate that keyboards look differently for each device, each user is used to his own keyboard, and expects to see it when editing text. I urge you to reconsider.

Community
  • 1
  • 1
Steelight
  • 3,267
  • 1
  • 18
  • 17
1

Thanks for the update. Here is how I'm implementing it. It might be similar to how you are doing it. I'd be curious what issues you've run into so far.

I haven't moved this to production yet so still testing but it seems to work well so far. I've removed some validations from the code below to make it much shorter...

Basically the keyboard is 1 line on the iPad and 2 lines on the phone. It supports any input field with the class "keyboard" and highlights the entire ".keyboard-item" so it is clear to the user which field they are updating.

    <div id="stuff">
        <ul>
            <li> <label for="name">Name</label> </li>
            <li> <input type="text" id="name" class="required"/> </li>
        </ul>
        <ul class="keyboard-item">
            <li> <label for="number">#</label> </li>
            <li> <input type="text" id="number" class="keyboard required" pattern="[0-9]*" readonly="readonly" onkeypress="dosomething(this)"/> </li>
        </ul>
    </div>

    <div class="mobile-number-keyboard">
        <div class="mobile-number-keyboard1"> <span style="padding-left: 20px;">0</span> <span>1</span> <span>2</span> <span>3</span> <span>4</span> <span style="padding-right: 20px;">5</span> </div>
        <div class="mobile-number-keyboard2"> <span style="padding-left: 20px;">6</span> <span>7</span> <span>8</span> <span>9</span> <span style="width: 8px;">.</span> <span style="padding-right: 20px;"><</span> </div>
    </div>

<style>
    .mobile-number-keyboard { width: 101%; height: 40px; margin: auto; margin-bottom: 20px; }
    body.phone .mobile-number-keyboard { height: 80px; }
    .mobile-number-keyboard span { float: left; padding: 8px 22px; border: 1px outset White; cursor: pointer; background-color: #4F81BD; color: White; }
    .mobile-number-keyboard span:hover { background-color: #87CEFA; }
    .mobile-number-keyboard span:active { border-style: inset; background-color: #00E5EE; }
    body.phone .mobile-number-keyboard2 { clear: both; height: 40px; }
    .keyboard-focus { background: #FFC1C1; border: 1px solid red; }
    .keyboard-item-focus { background: #00E5EE; }
</style>

<script>
    function initCustomKeyboard(jContainer) {
            jContainer.find('input, select, textarea').click(function() {
                $('.keyboard-focus').removeClass('keyboard-focus');
                $('.keyboard-item-focus').removeClass('keyboard-item-focus');

                var me = $(this);

                if (me.hasClass('keyboard')) {
                    me.addClass('keyboard-focus');
                    var parent = me.parent();

                    if (parent.hasClass('keyboard-item')) {
                        parent.addClass('keyboard-item-focus');
                    } else {
                        parent = parent.parent();

                        if (parent.hasClass('keyboard-item')) {
                            parent.addClass('keyboard-item-focus');
                        } else {
                            parent = parent.parent();

                            if (parent.hasClass('keyboard-item')) {
                                parent.addClass('keyboard-item-focus');
                            }
                        }
                    }
                }
            });

            jContainer.find('.mobile-number-keyboard').find('span').click(function() {
                var me = $(this);
                var val = me.text();
                var box = jContainer.find('.keyboard-focus');

                var bval = box.val();
                var blen = bval.length

                if (box.length > 0) {
                    if (val === '<') {
                        if (blen === 0) { return; }

                        if (blen > 1 && bval.substring(blen-2, blen-1) === ' ') {
                            box.val( bval.substring(0, blen - 2) );
                        } else {
                            box.val( bval.substring(0, blen - 1) );
                        }

                        var whichCode = 8;
                    } else {
                        var max = box.attr('maxlength');
                        var whichCode = val.charCodeAt(0);

                        if (max === undefined || parseInt(max) > blen) {
                            box.val(bval + val);
                        } else {
                            return;
                        }
                    }

                    var ev = $.Event('keydown');
                    ev.which = whichCode;
                    box.trigger(ev);

                    ev = $.Event('keypress');
                    ev.which = whichCode;
                    box.trigger(ev);

                ev = $.Event('keyup');
                    ev.which = whichCode;
                    box.trigger(ev);
                }
            });
        }

    $(function() { initCustomKeyboard('#stuff'); }
</script>
SemanticZen
  • 1,061
  • 13
  • 21