驗證碼輸入框,滿足剪切板內容自動填充,看效果
原本做法是6個EditText,後來發現,這樣寫最大問題是,無法滿足粘貼功能,驗證碼短信 一般都帶“複製”,如果犧牲掉了驗證碼粘貼功能 確實有點操蛋。
先聊聊思路:
1.首先想到 寫一個EditText,然後setBackground()爲6個框,字間距剛好讓每個數字處於框中間;然而字間距的方法沒找到合適的,此路不通。
2.我打開滴滴,美團,結果大廠的複製粘貼各種花式bug啪啪打臉。
3.功夫不負有心人,終於找到一個支持粘貼的app—建設銀行,儘管被我測出了bug,也給我思路,讓我看出了端倪。
看到上圖我猜想,藍色水滴中間纔是全部編輯框字體,於是我剪切,結果正如我所料,框內字體被清除了,並且無論我點擊最後一個框,光標始終在第二個框裏跳動。
於是,我有思路了,所有的框就是TextView,而真正的編輯框內容是透明的。爲了點擊最後一個框也能喚起軟鍵盤,需要讓EditText的寬度與六個框一樣寬;
建行app 有個缺點就是 光標可以遊走,怎麼避免呢,EditText.setTextSize(0.01f);
上代碼吧:
/**
* Created by @author iblade.Wang on 2019/4/4.
* 驗證碼輸入框
* EditText字號極小,且顏色透明
*/
public class VerCodeInputView extends FrameLayout {
/**
* 輸入框個數
*/
private int inputNum;
/**
* 輸入框寬度
*/
private int inputWidth;
private int inputHeight;
/**
* 輸入框之間的間隔
*/
private int childPadding;
/**
* 輸入框背景
*/
private int editTextBg;
/**
* 文本顏色
*/
private int textColor;
/**
* 文本字體大小
*/
private int textSize;
/**
* 輸入類型
*/
private int inputType;
public VerCodeInputView(Context context) {
this(context, null);
}
public VerCodeInputView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public VerCodeInputView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
TypedArray ta = context.getTheme().obtainStyledAttributes(attrs, R.styleable.VerCodeInputView, defStyleAttr, 0);
inputNum = ta.getInteger(R.styleable.VerCodeInputView_inputNum, 6);
inputWidth = ta.getDimensionPixelSize(R.styleable.VerCodeInputView_inputWidth, DensityUtil.dip2px(context, 43));
inputHeight = inputWidth;
childPadding = ta.getDimensionPixelSize(R.styleable.VerCodeInputView_inputPadding, DensityUtil.dip2px(context, 7.5f));
textColor = ta.getColor(R.styleable.VerCodeInputView_inputTxtColor, Color.parseColor("#333333"));
textSize = ta.getDimensionPixelSize(R.styleable.VerCodeInputView_inputTxtSize, 24);
editTextBg = ta.getResourceId(R.styleable.VerCodeInputView_inputBg, R.drawable.bg_edit_vercode);
inputType = ta.getInt(R.styleable.VerCodeInputView_inputType, InputType.TYPE_CLASS_NUMBER);
ta.recycle();
this.initViews();
}
private List<TextView> textViewList;
private EditText editText;
private void initViews() {
textViewList = new ArrayList<>(inputNum);
LinearLayout llTextViewRoot = new LinearLayout(getContext());
LayoutParams layoutParams = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
llTextViewRoot.setLayoutParams(layoutParams);
llTextViewRoot.setOrientation(LinearLayout.HORIZONTAL);
addView(llTextViewRoot);
for (int i = 0; i < inputNum; i++) {
TextView textView = new TextView(getContext());
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(inputWidth, inputHeight);
if (i != inputNum - 1) {//最後一個textView 不設置margin
params.rightMargin = childPadding;
}
params.gravity = Gravity.CENTER;
textView.setLayoutParams(params);
textView.setTextColor(textColor);
textView.setTextSize(textSize);
textView.setGravity(Gravity.CENTER);
textView.setFilters(new InputFilter[]{new InputFilter.LengthFilter(1)});
textView.setInputType(inputType);
textView.setBackgroundResource(editTextBg);
textView.setId(i);
llTextViewRoot.addView(textView);
textViewList.add(textView);
}
editText = new EditText(getContext());
LayoutParams layoutParam2 = new LayoutParams(LayoutParams.MATCH_PARENT, inputHeight);
editText.setLayoutParams(layoutParam2);
editText.setTextSize(0.1f);
editText.setCursorVisible(false);
editText.setFilters(new InputFilter[]{new InputFilter.LengthFilter(inputNum)});
//屏蔽長按
editText.setLongClickable(false);
editText.setTextColor(ContextCompat.getColor(getContext(), R.color.transparent));
editText.setBackground(null);
editText.addTextChangedListener(textWatcher);
addView(editText);
initListener();
}
private void initListener() {
//屏蔽雙擊: 好多手機雙擊會出現 選擇 剪切 粘貼 的選項卡,
new GestureDetector(getContext(), new GestureDetector.SimpleOnGestureListener() {
@Override
public boolean onDoubleTap(MotionEvent e) {
return true;
}
});
}
private TextWatcher textWatcher = new TextWatcher() {
@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 editable) {
String inputContent = editText.getText().toString();
if (listener != null && inputContent.length() >= inputNum) {
listener.onComplete(inputContent);
}
for (int i = 0, len = textViewList.size(); i < len; i++) {
TextView textView = textViewList.get(i);
if (i < inputContent.length()) {
textView.setText(String.valueOf(inputContent.charAt(i)));
} else {
textView.setText("");
}
}
}
};
private boolean isAuto = false;
/**
* 設置寬高自適應,單個框的寬度平分父佈局總寬度
*/
public void setAutoWidth() {
isAuto = true;
requestLayout();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int width = getMeasuredWidth();
if (isAuto && width != 0) {
isAuto = false;
resetWH(width);
}
}
private void resetWH(int w) {
int paddings = childPadding * (inputNum - 1);
inputWidth = (w - paddings) / (inputNum);
inputHeight = inputWidth;
for (int i = 0, len = textViewList.size(); i < len; i++) {
View child = textViewList.get(i);
child.getLayoutParams().height = inputHeight;
child.getLayoutParams().width = inputWidth;
}
editText.getLayoutParams().height = inputHeight;
}
/**
* 獲取編輯框內容
*
* @return 編輯框內容
*/
public String getEditContent() {
return editText.getText().toString();
}
public OnCompleteListener listener;
public void setOnCompleteListener(OnCompleteListener listener) {
this.listener = listener;
}
public interface OnCompleteListener {
/**
* 完成驗證碼的填寫
*
* @param content 填寫內容
*/
void onComplete(String content);
}
}
如何調用:
/**
* @author YlWang
*/
public class MainActivity extends AppCompatActivity {
private VerCodeInputView codeInputCard;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
}
private void initView() {
codeInputCard = findViewById(R.id.edit);
codeInputCard.setAutoWidth();
codeInputCard.setOnCompleteListener(new VerCodeInputView.OnCompleteListener() {
@Override
public void onComplete(String content) {
Toast.makeText(MainActivity.this, "您輸入了:" + content, Toast.LENGTH_LONG).show();
}
});
}
}
最近發現有同行也做了類似需求:https://www.jianshu.com/p/3238a5afc21c