[英]IP address textbox in Android?
我對 Android 完全陌生。
我想放入一個文本框,用戶可以在其中輸入 IP 地址……但是如何限制用戶只能輸入數字? ...我如何驗證?
是否有現成的 ip-address-textbox “在那里”我可以使用?
謝謝!
魔力
我發現有效的是將EditText
設置為使用android:inputType="phone"
,因此輸入僅限於數字、句點和少數其他字符。 但是,這只會讓您輸入 IPV4 地址,因為它只是數字。 為了驗證,您必須獲取輸入文本並手動解析它。
至於現成的輸入小部件,我還沒有遇到過。
除了 Erich 所說的,您還可以使用 android:digits="0123456789。" 禁止除數字和小數點以外的任何內容。
您可以使用:
EditText ipAddress = (EditText)findViewById(R.id.ip_address);
InputFilter[] filters = new InputFilter[1];
filters[0] = new InputFilter() {
@Override
public CharSequence filter(CharSequence source, int start, int end,
android.text.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;
}
};
ipAddress.setFilters(filters);
對於驗證, regular-expressions.info有一個很好的正則表達式字符串,您可以用來測試有效 (0-255) 范圍內的 IP:
\\b(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).(25[0-5]|2[0] -4][0-9]|[01]?[0-9][0-9]?).(25[0-5]|2[0-4][0-9]|[01]? [0-9][0-9]?).(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\乙
我認為,這是現有解決方案中最完整的(至少我已經找到了)。 我能想象到的唯一改進是實現一個新的KeyListener
來更好地限制輸入,但我不相信這實際上是可能的,因為 IME 是如何處理布局和其他東西的。
public class IPAddressText extends EditText {
public IPAddressText(Context context) {
super(context);
setInputType(InputType.TYPE_CLASS_PHONE);
setFilters(new InputFilter[] { new InputFilter(){
@Override
public CharSequence filter(CharSequence source, int start, int end, android.text.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;
}
}
});
addTextChangedListener(new TextWatcher(){
boolean deleting = false;
int lastCount = 0;
@Override
public void afterTextChanged(Editable s) {
if (!deleting) {
String working = s.toString();
String[] split = working.split("\\.");
String string = split[split.length - 1];
if (string.length() == 3 || string.equalsIgnoreCase("0")
|| (string.length() == 2 && Character.getNumericValue(string.charAt(0)) > 1)) {
s.append('.');
return;
}
}
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
if (lastCount < count) {
deleting = false;
}
else {
deleting = true;
}
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
// Nothing happens here
}
});
}
}
因為它是我最終使用的,所以這里有一個EditTextPreference
版本:
public class IPAddressPreference extends EditTextPreference {
public IPAddressPreference(Context context) {
super(context);
getEditText().setInputType(InputType.TYPE_CLASS_PHONE);
getEditText().setFilters(new InputFilter[] { new InputFilter(){
@Override
public CharSequence filter(CharSequence source, int start, int end, android.text.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;
}
}
});
getEditText().addTextChangedListener(new TextWatcher(){
boolean deleting = false;
int lastCount = 0;
@Override
public void afterTextChanged(Editable s) {
if (!deleting) {
String working = s.toString();
String[] split = working.split("\\.");
String string = split[split.length - 1];
if (string.length() == 3 || string.equalsIgnoreCase("0")
|| (string.length() == 2 && Character.getNumericValue(string.charAt(0)) > 1)) {
s.append('.');
return;
}
}
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
if (lastCount < count) {
deleting = false;
}
else {
deleting = true;
}
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
// Nothing happens here
}
});
}
}
我正在使用這個 TextWatcher:
public class IPTextWatcher implements TextWatcher
{
private static String LOG_TAG = "IPTextWatcher";
private EditText editText;
private BarcodeTextWatcher.ChangeListener listener = null;
public IPTextWatcher( EditText editText )
{
this.editText = editText;
}
private static final String IPADDRESS_PATTERN =
"^([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." +
"([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." +
"([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." +
"([01]?\\d\\d?|2[0-4]\\d|25[0-5])$";
@Override
public void afterTextChanged( Editable s )
{
Log.v( LOG_TAG, s.toString() );
if( !s.toString().matches( IPADDRESS_PATTERN ) )
{
String ip = format( s.toString() );
editText.removeTextChangedListener( this );
editText.setText( ip );
editText.setTextKeepState( ip );
Selection.setSelection( editText.getText(), ip.length() );
editText.addTextChangedListener( this );
if( listener != null )
listener.onChange();
}
}
public static String format( String value )
{
String userInput = "" + value.replaceAll( "[^\\d\\.]", "" );
StringBuilder ipBuilder = new StringBuilder();
String[] address = userInput.split("\\.");
String glue = null;
for( String part : address )
{
if( glue != null ) ipBuilder.append( glue );
int p = Integer.valueOf( part );
if( p >= 256 )
{
int i = 1;
do
{
p = Integer.valueOf( part.substring( 0, part.length() -i ) );
i++;
}
while( p >= 256 );
}
ipBuilder.append( p );
glue = ".";
}
if( userInput.charAt( userInput.length()-1 ) == '.' )
ipBuilder.append( "." );
return ipBuilder.toString();
}
@Override
public void onTextChanged( CharSequence s, int start, int before, int count )
{
}
@Override
public void beforeTextChanged( CharSequence s, int start, int count, int after )
{
}
}
<EditText
android:id="@+id/ip_address"
android:inputType="number|numberDecimal"
android:digits="0123456789."
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
為我工作
基於NathanOliver 和 enneract 的代碼,我在 kotlin 中編寫了一個變體,在刪除一個點時插入一個點。
class IpAddressEditText : AppCompatEditText {
constructor(context: Context) : super(context) {
init()
}
constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {
init()
}
constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {
init()
}
private fun init() {
// phone input type to show the numeric keyboard in all kinds of devices
inputType = InputType.TYPE_CLASS_PHONE
// restrict the input of the characters specified in string bellow
keyListener = DigitsKeyListener.getInstance("0123456789.")
// InputFilter decides what can be typed
filters = arrayOf(InputFilter { source, start, end, dest, dstart, dend ->
if (end > start) {
val inputString = dest.toString()
val substring = inputString.substring(0, dstart) + source.subSequence(start, end) + inputString.substring(dend)
if (!substring.matches("^\\d{1,3}(\\.(\\d{1,3}(\\.(\\d{1,3}(\\.(\\d{1,3})?)?)?)?)?)?".toRegex())) {
// do not allow the input of:
// segments with more than 3 characters and less than 1;
// segments != 4;
return@InputFilter ""
} else {
val splits = substring.split("\\.".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
for (i in splits.indices) {
// don't allow a segment with a value more than 255
if (Integer.valueOf(splits[i]) > 255) {
return@InputFilter ""
}
}
}
}
null
})
// TextWatcher notifies what was typed
addTextChangedListener(object : TextWatcher {
var isDeleting = false
var lastCount = 0
override fun afterTextChanged(editable: Editable) {
if (!isDeleting) {
val inputString = editable.toString()
val segmentList = inputString.split("\\.".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
val lastSegment = segmentList[segmentList.size - 1]
// each segment of the ip can have max size of 3 characters and a max value of 255
if (lastSegment.length == 3 || lastSegment.length == 2 && Integer.parseInt(lastSegment) > 25) {
// add a dot automatically if the conditions met
editable.append('.')
return
}
} else {
// add a dot in the same position where it was deleted
editable.insert(selectionStart, ".")
}
}
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
isDeleting = lastCount >= count
}
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {
// do nothing
}
})
}
}
這是通過顯示只有數字和一個點的軟鍵盤來限制用戶只能輸入數字和點的代碼(但允許您輸入多個點)。
etIpAddress.setInputType(InputType.TYPE_CLASS_NUMBER);
etIpAddress.setInputType(InputType.TYPE_NUMBER_FLAG_DECIMAL);
etIpAddress.setKeyListener(DigitsKeyListener.getInstance(false,false));
etIpAddress.setKeyListener(DigitsKeyListener.getInstance("0123456789."));
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.