What android:inputType should I use for entering an IP Address and hostname?
JavaAndroidAndroid LayoutAndroid WidgetJava Problem Overview
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?
Java Solutions
Solution 1 - Java
Try using android:inputType="number"
, but also set android:digits="0123456789."
. Works for me.
Solution 2 - Java
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.
Solution 3 - Java
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"/>
Solution 4 - Java
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);
Solution 5 - Java
use this :
<EditText
android:id="@+id/txtIP"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:digits="0123456789."
/>
Solution 6 - Java
<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
Solution 7 - Java
I think your only option is..
EditText android:inputType="text" ... />
You could possible check the Text for 3 dots a IP address contains
Solution 8 - Java
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
Solution 9 - Java
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;
Solution 10 - Java
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.
Solution 11 - Java
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."));
Solution 12 - Java
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
})
Solution 13 - Java
Try using android:inputType="textUri"
. It works especially well when you want hostname or IP address.