Android 自定义控件 IPEditText
2022-06-14 本文已影响0人
sssssss_
自定义的IP输入框
参考自:https://github.com/lanyan520/Idea-EditText
功能分析
- 四个输入框;
- 输入框最多输入3位数,且不能大于255;
- 不满足条件2的时候,自动切换到下一个输入框;
- get方法能快速获取IP地址
类
- AbsEditText
- AbsEditTextGroup
- IPEditText
- IPView
使用
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<com.zhd.screenviewer.ipview.IPView
android:id="@+id/ip_view"
android:layout_width="match_parent"
android:layout_height="40dp"
android:layout_margin="10dp" />
</LinearLayout>
代码
1. AbsEditText
import android.content.Context;
import android.text.InputFilter;
import android.text.method.NumberKeyListener;
import android.util.AttributeSet;
public abstract class AbsEditText extends androidx.appcompat.widget.AppCompatEditText {
public AbsEditText(Context context) {
this(context, null, 0);
}
public AbsEditText(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public AbsEditText(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
setMaxLength();
addInputFilter();
}
/**
* 初始化配置
*/
protected void setMaxLength() {
//setOnKeyListener((OnKeyListener) DigitsKeyListener.getInstance(""));
setFilters(new InputFilter[]{ new InputFilter.LengthFilter(getMaxLength()) });
}
protected void addInputFilter() {
setKeyListener(new NumberKeyListener() {
@Override
protected char[] getAcceptedChars() {
return getInputFilterAcceptedChars();
}
@Override
public int getInputType() {
return getEditTextInputType();
}
});
}
/**
* 输入内容最大长度
* @return
*/
public abstract int getMaxLength();
/**
* 输入内容过滤
* @return
*/
public abstract char[] getInputFilterAcceptedChars();
/**
* 输入内容检查是否ok
* @return
*/
public abstract boolean checkInputValue();
public abstract int getEditTextInputType();
}
2. AbsEditTextGroup
import java.util.ArrayList;
import android.content.Context;
import android.graphics.drawable.ColorDrawable;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;
public abstract class AbsEditTextGroup extends LinearLayout implements TextWatcher {
protected float sp16 = 16.0f;
protected int dp4 = 4;
protected ArrayList<AbsEditText> editTexts = new ArrayList<AbsEditText>();
public AbsEditTextGroup(Context context) {
this(context, null, 0);
}
public AbsEditTextGroup(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public AbsEditTextGroup(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
addViews();
buildListener();
}
protected void addViews() {
for (int i = 0; i < getChildCount(); i++) {
if (i % 2 == 0) {
AbsEditText absEditText = createAbsEditText();
editTexts.add(absEditText);
addView(absEditText);
} else {
addView(createSemicolonTextView());
}
}
}
protected AbsEditText createAbsEditText() {
AbsEditText absEditText = getAbsEditText();
LayoutParams params = new LayoutParams(0, LayoutParams.MATCH_PARENT);
params.weight = 1;
absEditText.setLayoutParams(params);
absEditText.setTextSize(sp16);//sp
absEditText.setTextColor(0xFF888888);
absEditText.setGravity(Gravity.CENTER);
absEditText.setPadding(dp4, dp4, dp4, dp4);
absEditText.setSingleLine();
absEditText.setHint("0");
absEditText.setFocusableInTouchMode(true);
absEditText.setBackgroundDrawable(new ColorDrawable(0xFFFFFFFF));
applyEditTextTheme(absEditText);
return absEditText;
}
protected TextView createSemicolonTextView() {
TextView textView = new TextView(getContext());
LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT);
textView.setLayoutParams(params);
textView.setTextSize(sp16);//sp
textView.setTextColor(0xFF444444);
textView.setText(getSemicolomText());
applySemicolonTextViewTheme(textView);
return textView;
}
protected void buildListener() {
for (int i = 0; i < editTexts.size(); i++) {
editTexts.get(i).addTextChangedListener(this);
if (i != 0) {
editTexts.get(i).setOnKeyListener(new OnDelKeyListener(editTexts.get(i - 1), editTexts.get(i)));
}
}
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
if (s.toString().length() == getDelMaxLength()) {
for (int i = 0; i < editTexts.size() - 1; i++) {
if (editTexts.get(i).hasFocus()) { //hasFocus √ & isFocus ×
editTexts.get(i).clearFocus();
editTexts.get(i + 1).requestFocus();
break;
}
}
}
}
public boolean checkInputValue() {
boolean result = true;
for (int i = 0; i < editTexts.size(); i++) {
if (!editTexts.get(i).checkInputValue()) {
result = false;
break;
}
}
return result;
}
/**
* IP网关子网掩码转byte4个字节
* @return
*/
public byte[] getBytesWithIP() {
byte[] result = new byte[4];
for (int i = 0; i < editTexts.size(); i++) {
int number = Integer.valueOf(editTexts.get(i).getText().toString());
result[i] = (byte) number;
}
return result;
}
/**
* Mac地址转换6字节byte
* @return
*/
public byte[] getBytesWithMac() {
byte[] result = new byte[6];
for (int i = 0; i < editTexts.size(); i++) {
String mac = editTexts.get(i).getText().toString();
byte byteMac = Integer.valueOf(mac, 16).byteValue();
result[i] = byteMac;
}
return result;
}
/**
* 重置自布局的输入控件
*/
public void resetText() {
for (AbsEditText editText : editTexts) {
editText.setText("");
}
}
class OnDelKeyListener implements OnKeyListener {
private AbsEditText clearEditText;
private AbsEditText requestEditText;
public OnDelKeyListener(AbsEditText requestEditText, AbsEditText clearEditText) {
this.requestEditText = requestEditText;
this.clearEditText = clearEditText;
}
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_DEL
&& event.getAction() == KeyEvent.ACTION_DOWN && clearEditText.getSelectionStart() == 0) {
clearEditText.clearFocus();
requestEditText.requestFocus();
requestEditText.setSelection(requestEditText.getText().toString().trim().length());
return true;
}
return false;
}
}
public ArrayList<AbsEditText> getChildEditTextViews() {
return editTexts;
}
public abstract int getChildCount();
public abstract AbsEditText getAbsEditText();
public abstract String getSemicolomText();
public abstract int getDelMaxLength();
public abstract void applySemicolonTextViewTheme(TextView semicolonTextView);
public abstract void applyEditTextTheme(AbsEditText absEditText);
}
3. IPEditText
import android.content.Context;
import android.text.InputType;
import android.util.AttributeSet;
public class IPEditText extends AbsEditText {
public IPEditText(Context context) {
this(context, null, 0);
}
public IPEditText(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public IPEditText(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
public int getMaxLength() {
return 3;
}
@Override
public char[] getInputFilterAcceptedChars() {
return new char[]{ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };
}
@Override
public boolean checkInputValue() {
String textValue = getText().toString().trim();
if (textValue.isEmpty()) {
return false;
} else {
int number = Integer.valueOf(textValue);
return number >= 0 && number <= 255;
}
}
@Override
public int getEditTextInputType() {
return InputType.TYPE_CLASS_NUMBER;
}
}
4. IPView
import android.content.Context;
import android.text.Editable;
import android.util.AttributeSet;
import android.view.Gravity;
import android.widget.TextView;
public class IPView extends AbsEditTextGroup {
public IPView(Context context) {
this(context, null, 0);
}
public IPView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public IPView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
public int getChildCount() {
return 7;
}
@Override
public AbsEditText getAbsEditText() {
return new IPEditText(getContext());
}
@Override
public String getSemicolomText() {
return ".";
}
@Override
public int getDelMaxLength() {
return 3;
}
@Override
public void applySemicolonTextViewTheme(TextView semicolonTextView) {
semicolonTextView.setPadding(0, 0, 0, 5);
semicolonTextView.getPaint().setFakeBoldText(true);
semicolonTextView.setBackgroundColor(0xFFFFFFFF);
semicolonTextView.setGravity(Gravity.BOTTOM);
}
@Override
public void applyEditTextTheme(AbsEditText absEditText) {
}
@Override
public void afterTextChanged(Editable s) {
if (s.toString().length() == getDelMaxLength()) {
for (int i = 0; i < editTexts.size() - 1; i++) {
if (editTexts.get(i).hasFocus()) { //hasFocus √ & isFocus ×
editTexts.get(i).clearFocus();
editTexts.get(i + 1).requestFocus();
String lastEditTextValue = editTexts.get(i).getText().toString();
if (Integer.parseInt(lastEditTextValue) > 255) {
editTexts.get(i).setText(lastEditTextValue.substring(0, 2));
editTexts.get(i + 1).setText(lastEditTextValue.substring(2, 3));
editTexts.get(i + 1).setSelection(1);
}
break;
}
}
}
}
/**
* 设置初始值,例如默认网关:"255\\.255\\.255\\.0" 正则表达式转义字符相关知识
*/
public void setGatewayText(String[] ips) {
if (ips == null) {
ips = new String[]{ "255", "255", "255", "0" };
}
for (int i = 0; i < editTexts.size(); i++) {
editTexts.get(i).setText(ips[i]);
}
}
}