60

I am building a small Android app where the user will enter an IP address or a hostname into an EditText widget. 90% of the time they will be entering an IP address, the rest of the time - a hostname.

So naturally, I want to make it easy for them to enter an IP address, but the ability to switch to alpha numerics for hostname entry is important.

I can't seem to find a good inputType. The numberDecimal initially seemed like a good shot, but it only allows one dot.

Ideally, I'd like to start with a standard keyboard that had the ?123 button pressed.

How do I get there?

Josh Correia
  • 3,807
  • 3
  • 33
  • 50
AngryHacker
  • 59,598
  • 102
  • 325
  • 594

13 Answers13

68

Try using android:inputType="number", but also set android:digits="0123456789.". Works for me.

stjns
  • 1,420
  • 13
  • 16
  • 1
    Just read the question again and noticed that the you wanted to be able to enter a hostname as well. My answer won't work for that, but it will bring up the standard "number" keyboard and allow for multiple dots. – stjns Feb 04 '14 at 15:25
  • You _can_ add lower and upper case letters and a hyphen to `digits`, but it is a bit messy. It _will_ work, though. – stjns Feb 04 '14 at 15:33
  • 5
    Using Android 6.0, `number` didn't show me the dot while `numberDecimal` did. – Eido95 Nov 16 '16 at 18:15
  • For typing "192.168.1.111", either `number` or `numberDecimal` with `digits` didn't work on my Samsung Note 9 (Android 9.0). It just doesn't allow me to type the second dot. I use `Patterns.IP_ADDRESS.matcher("192.168.1.111").matches()` to validate the input in my code. – Sam Chen Jan 10 '20 at 16:28
47

If you use inputType="phone" you gain access to a cut down keyboard containing Numbers and a Period character - this doesn't restrict the input with regards to the amount of Periods you can enter.

Please see this answer for validation while being entered.

Community
  • 1
  • 1
Graeme
  • 25,714
  • 24
  • 124
  • 186
  • Thanks I think this is a good answer. It's so annoying to be brought up with a keyboard for a field that only requires numbers such as an IP Address. Validation is key obviously but you've even provided a link for that! Kudos. – Evan McEwen Apr 04 '13 at 21:00
  • 4
    On Android Marshmallow 23 the period button on the keyboard has been replaced by * and #. Therefore inputType="phone" should not be used for IP address input fields. Use android:inputType="numberDecimal" and android:digits="0123456789." instead as suggested in other questions – Giorgio Apr 18 '16 at 09:57
  • Use `Patterns` work for me, `number` and `numberDecimal` with `digits` didn't work. – Sam Chen Jan 10 '20 at 16:23
  • This still allows the user to input `*#(/),` unfortunately. – Josh Correia Jul 17 '20 at 19:40
29

This works perfectly keyboard with numbers and decimal by adding android:inputType="number|numberDecimal" and android:digits="0123456789."

Example

 <EditText
    android:id="@+id/ip_address"
    android:inputType="number|numberDecimal"
    android:digits="0123456789."
    android:layout_width="match_parent"
    android:layout_height="wrap_content"/>
Munish Kapoor
  • 3,141
  • 2
  • 26
  • 41
17

You can use your own input filter for that

final EditText text = new EditText(ServerSettings.this);
InputFilter[] filters = new InputFilter[1];
filters[0] = new InputFilter() {
    @Override
    public CharSequence filter(CharSequence source, int start,
            int end, Spanned dest, int dstart, int dend) {
        if (end > start) {
            String destTxt = dest.toString();
            String resultingTxt = destTxt.substring(0, dstart) +
            source.subSequence(start, end) +
            destTxt.substring(dend);
            if (!resultingTxt.matches ("^\\d{1,3}(\\." +
                    "(\\d{1,3}(\\.(\\d{1,3}(\\.(\\d{1,3})?)?)?)?)?)?")) { 
                return "";
            } else {
                String[] splits = resultingTxt.split("\\.");
                for (int i=0; i<splits.length; i++) {
                    if (Integer.valueOf(splits[i]) > 255) {
                        return "";
                    }
                }
            }
        }
    return null;
    }
};
text.setFilters(filters);
Gary
  • 13,303
  • 18
  • 49
  • 71
SKT
  • 1,821
  • 1
  • 20
  • 32
  • Thanks for this. This answer was exactly what I needed. – bastecklein Dec 16 '16 at 20:12
  • Not working with spannables, since the whole input gets replaced with an empty string in some cases. See Łukasz Sromeks answer at https://stackoverflow.com/questions/3349121/how-do-i-use-inputfilter-to-limit-characters-in-an-edittext-in-android – Fruchtzwerg Oct 07 '20 at 15:17
6

use this :

<EditText
    android:id="@+id/txtIP"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:digits="0123456789."
 />
ultra.deep
  • 1,699
  • 1
  • 19
  • 23
5
<EditText
    android:id="@+id/ip_address"
    android:inputType="number|numberDecimal"
    android:digits="0123456789."
    android:layout_width="match_parent"
    android:layout_height="wrap_content"/>

worked for me

saurabh yadav
  • 567
  • 6
  • 14
1

Maybe if you use 2 radiobutton, one shows an edittext for host, the other one shows 4 numeric edittext for IP, then, once the user submit data you concat all 4 edittext values with dots between them, something like this, edittext1.getText() + "." + edittext2.getText() + "." edittext3.getText() + "." edittext4.getText() so you can obtain a validated IP address like that but obviously it will imply more work.

crit_
  • 33
  • 8
  • 2
    Good golly I hate when apps try to make entering an IP address "easier". Guess what, if I know what an IP address is, I can probably find the "." button. – gladed Jan 06 '16 at 00:06
  • @gladed Well, the idea was in order to facilitate IP validation and make user input easier – crit_ Feb 21 '16 at 16:24
  • 1
    You can easily validate a string against Patterns.IP_ADDRESS. For the user, tapping back and forth between different fields in an IP address is never easier. Have you ever seen a phone dialer with separate area-code/3-digit-prefix/4-digit-suffix fields? Or an email widget with different fields for name/domain? Please just don't. – gladed Feb 22 '16 at 18:59
1

Here is the code that allows you to display a soft keyboard with only numbers and a dot (but allows you to enter multiple dots).

etIpAddress.setInputType(InputType.TYPE_CLASS_NUMBER);
etIpAddress.setInputType(InputType.TYPE_NUMBER_FLAG_DECIMAL);
etIpAddress.setKeyListener(DigitsKeyListener.getInstance(false,false));
etIpAddress.setKeyListener(DigitsKeyListener.getInstance("0123456789."));
1

I think your only option is..

EditText android:inputType="text" ... />

You could possible check the Text for 3 dots a IP address contains

coder_For_Life22
  • 26,645
  • 20
  • 86
  • 118
  • User wants same text box need to handle host name and IP, number may constrian it to only number. Even IP he can't enter because of DOTS. – kosa Dec 28 '11 at 22:21
  • "number" won't let you switch to letters and won't let u enter a dot. – AngryHacker Dec 28 '11 at 22:22
  • I think your only option is Text. You can then check the IP address for consistency to make sure the decimals are in place. – coder_For_Life22 Dec 28 '11 at 22:25
1

I think you need to use TextWatcher for validation, register it with TextView.addTextChangedListener() method and use Pattern.DOMAIN_NAME and Pattern.IP_ADDRESS (Android 2.2+).

See:
Android: How can I validate EditText input?
Validating IP in android

Community
  • 1
  • 1
user802421
  • 7,465
  • 5
  • 40
  • 63
  • This is validation - I got that part. I am only concerned right now with making it easy on the user and not having the user tap extra keys. – AngryHacker Dec 28 '11 at 22:46
1

You can extend the DigitsKeyListener (source) and change the filter() function (validation that will check either ip pattern or a string hostname) and getInputType() to return InputType.TYPE_CLASS_PHONE;

Tom van der Woerdt
  • 29,532
  • 7
  • 72
  • 105
Jana
  • 5,516
  • 5
  • 23
  • 29
0

SKTs answer is working pretty well until the InputFilter passes Spannables. Spannables are tricky to handle which is described for example ins answers of this question. In this case, returning "" for invalid input will replace the whole text by an empty string. I've adapted the solution also to handle this case. Here is the code, differing the types, in Kotlin:

val ipAddressFilters = arrayOf(InputFilter { source, start, end, dest, dstart, dend ->
    if (end > start) {
        val toCheck = if (source is Spannable) {
            source.toString()
        } else {
            val destString = dest.toString()
            destString.substring(0, dstart) + source.subSequence(start, end) + destString.substring(dend)
        }
        if (!toCheck.matches("^\\d{1,3}(\\.(\\d{1,3}(\\.(\\d{1,3}(\\.(\\d{1,3})?)?)?)?)?)?".toRegex())) {
            return@InputFilter if (source is Spannable) { dest } else { "" }
        } else {
            val splits = toCheck.split("\\.".toRegex()).toTypedArray()
            for (i in splits.indices) {
                if (splits[i] != "" && Integer.valueOf(splits[i]) > 255) {
                    return@InputFilter if (source is Spannable) { dest } else { "" }
                }
            }
        }
    }
    null
})
Fruchtzwerg
  • 10,999
  • 12
  • 40
  • 49
-1

Try using android:inputType="textUri". It works especially well when you want hostname or IP address.

Stephen Kennedy
  • 20,585
  • 22
  • 95
  • 108
Sabaat Ahmad
  • 522
  • 1
  • 5
  • 10