Android 密碼輸入框、驗證碼輸入框,完整版;
阿新 • • 發佈:2018-11-29
接上篇,優化了一下程式碼,新增一些屬性;
"space" //每個輸入框之間的間距;
"strokeWidth" //邊框的高度;
"checkedColor" //已輸入的顏色
"defaultColor" //未輸入的預設顏色
"textLength" //規定輸入長度
"backColor" //輸入框的背景顏色
"textColor" //字型顏色
"circle" //密文密碼 ● 的大小;
"round" //輸入框的圓角弧度
"textSize" //字型大小
"isPwd" //是否密文輸入 預設true
"waitInputColor" //待輸入線的顏色
"isWaitInput" //是否顯示待輸入線 預設false
如何使用:
public class MainActivity extends AppCompatActivity { private PwdEditText p; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); p = findViewById(R.id.p); p.setOnTextChangeListener(new PwdEditText.OnTextChangeListener() { @Override public void onTextChange(String pwd) { if (pwd.length() == p.getTextLength()){ //輸入監聽 Toast.makeText(MainActivity.this,pwd,Toast.LENGTH_SHORT).show(); } } }); findViewById(R.id.btn).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { p.clearText(); //清空輸入內容 } }); } }
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <c.c.b.pwdinputedittext.PwdEditText android:id="@+id/p" android:layout_centerInParent="true" android:layout_width="330dp" android:layout_height="wrap_content" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="清空" android:id="@+id/btn" android:layout_below="@id/p" android:layout_centerHorizontal="true" /> </RelativeLayout>
看程式碼,PwdEditText :
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.support.v7.widget.AppCompatEditText;
import android.text.InputType;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.ViewGroup;
import java.util.ArrayList;
import java.util.List;
public class PwdEditText extends AppCompatEditText {
private Paint sidePaint , backPaint , textPaint;
private Context mC;
private String mText;
private List<RectF> rectFS;
private int StrokeWidth,spzceX ,spzceY,textSize;
private int checkedColor,defaultColor,backColor ,textColor ,waitInputColor;
private int textLength;
private int Circle,Round;
private boolean isPwd , isWaitInput;
public PwdEditText(Context context) {
super(context);
mC = context;
setAttrs( null);
init();
}
public PwdEditText(Context context, AttributeSet attrs) {
super(context, attrs);
mC = context;
setAttrs( attrs);
init();
}
public PwdEditText(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mC = context;
setAttrs( attrs);
init();
}
private void setAttrs(AttributeSet attrs) {
TypedArray t = mC.obtainStyledAttributes(attrs, R.styleable.PwdEditText);
if (t != null) {
textLength = t.getInt(R.styleable.PwdEditText_textLength,6);
spzceX = t.getDimensionPixelSize(R.styleable.PwdEditText_space, (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,3,getResources().getDisplayMetrics()));
spzceY = t.getDimensionPixelSize(R.styleable.PwdEditText_space, (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,3,getResources().getDisplayMetrics()));
StrokeWidth = t.getDimensionPixelSize(R.styleable.PwdEditText_strokeWidth, (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,1,getResources().getDisplayMetrics()));
Round = t.getDimensionPixelSize(R.styleable.PwdEditText_round, (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,3,getResources().getDisplayMetrics()));
Circle = t.getDimensionPixelSize(R.styleable.PwdEditText_circle, (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,7,getResources().getDisplayMetrics()));
textSize = t.getDimensionPixelSize(R.styleable.PwdEditText_textSize, (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,16,getResources().getDisplayMetrics()));
checkedColor = t.getColor(R.styleable.PwdEditText_checkedColor,0xff44ce61);
defaultColor = t.getColor(R.styleable.PwdEditText_defaultColor,0xffd0d0d0);
backColor = t.getColor(R.styleable.PwdEditText_backColor,0xfff1f1f1);
textColor = t.getColor(R.styleable.PwdEditText_textColor,0xFF444444);
waitInputColor = t.getColor(R.styleable.PwdEditText_waitInputColor,0xFF444444);
isPwd = t.getBoolean(R.styleable.PwdEditText_isPwd,true);
isWaitInput = t.getBoolean(R.styleable.PwdEditText_isWaitInput,false);
t.recycle();
}
}
private void init() {
setTextColor(0X00ffffff); //把使用者輸入的內容設定為透明
setInputType(InputType.TYPE_CLASS_NUMBER|InputType.TYPE_NUMBER_VARIATION_NORMAL);
sidePaint = new Paint();
backPaint = new Paint();
textPaint = new Paint();
rectFS = new ArrayList<>();
mText = "" ;
this.setBackgroundDrawable(null);
setLongClickable(false);
setTextIsSelectable(false);
setCursorVisible(false);
}
@Override
protected void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) {
super.onTextChanged(text, start, lengthBefore, lengthAfter);
if (mText == null) {return;}
//如果字數不超過使用者設定的總字數,就賦值給成員變數mText;
// 如果字數大於使用者設定的總字數,就只保留使用者設定的幾位數字,並把游標制動到最後,讓使用者可以刪除;
if (text.toString().length() <= textLength){
mText = text.toString();
}else{
setText(mText);
setSelection(getText().toString().length()); //游標制動到最後
//呼叫setText(mText)之後鍵盤會還原,再次把鍵盤設定為數字鍵盤;
setInputType(InputType.TYPE_CLASS_NUMBER|InputType.TYPE_NUMBER_VARIATION_NORMAL);
}
if (OnTextChangeListener != null) OnTextChangeListener.onTextChange(mText);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
switch (heightMode){
case MeasureSpec.EXACTLY:
heightSize = MeasureSpec.getSize(heightMeasureSpec);
break;
case MeasureSpec.AT_MOST:
heightSize = widthSize/textLength;
break;
}
setMeasuredDimension(widthSize,heightSize);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//邊框畫筆
sidePaint.setAntiAlias(true);//消除鋸齒
sidePaint.setStrokeWidth(StrokeWidth);//設定畫筆的寬度
sidePaint.setStyle(Paint.Style.STROKE);//設定繪製輪廓
sidePaint.setColor(defaultColor);
//背景色畫筆
backPaint.setStyle(Paint.Style.FILL);
backPaint.setColor(backColor);
//文字的畫筆
textPaint.setTextSize(textSize);
textPaint.setStyle(Paint.Style.FILL);
textPaint.setColor(textColor);
int Wide = Math.min(getMeasuredHeight(), getMeasuredWidth() / textLength);
for (int i = 0; i < textLength; i++) {
//區分已輸入和未輸入的邊框顏色
if (mText.length() >= i){
sidePaint.setColor(checkedColor);
}else {
sidePaint.setColor(defaultColor);
}
//RectF的引數(left, top, right, bottom); 畫出每個矩形框並設定間距,間距其實是增加左邊框距離,縮小上下右邊框距離;
RectF rect = new RectF(i * Wide + spzceX, spzceY,i * Wide + Wide - spzceX,Wide - spzceY); //四個值,分別代表4條線,距離起點位置的線
canvas.drawRoundRect(rect,Round,Round,backPaint); //繪製背景色
canvas.drawRoundRect(rect,Round,Round,sidePaint); //繪製邊框;
rectFS.add(rect);
if (isWaitInput && i == mText.length()) { //顯示待輸入的線
Paint l = new Paint();
l.setStrokeWidth(3);
l.setStyle(Paint.Style.FILL);
l.setColor(waitInputColor);
canvas.drawLine(i * Wide + Wide / 2, Wide / 2 - Wide / 5, i * Wide + Wide / 2, Wide / 2 + Wide / 5, l);
}
}
//畫密碼圓點
for (int j = 0; j < mText.length(); j++) {
if (isPwd) {
canvas.drawCircle(rectFS.get(j).centerX(), rectFS.get(j).centerY(), Circle, textPaint);
}else {
canvas.drawText(mText.substring(j,j+1),rectFS.get(j).centerX()-(textSize - spzceX)/2, rectFS.get(j).centerY()+(textSize - spzceY)/2, textPaint);
// Rect textRect = new Rect();
// textPaint.getTextBounds(mText.substring(j, j + 1), 0, 1, textRect);
// canvas.drawText(mText.substring(j, j + 1), rectFS.get(j).left + (rectFS.get(j).right - rectFS.get(j).left) / 2 - textRect.width() / 2,
// rectFS.get(j).top + ((rectFS.get(j).bottom - rectFS.get(j).top) / 2) + textRect.height() / 2, textPaint);
}
}
}
private int dp2px(float dpValue){
float scale=mC.getResources().getDisplayMetrics().density;
return (int)(dpValue*scale+0.5f);
}
/**
* 輸入監聽
*/
interface OnTextChangeListener{
void onTextChange(String pwd);
}
private OnTextChangeListener OnTextChangeListener;
public void setOnTextChangeListener(OnTextChangeListener OnTextChangeListener){
this.OnTextChangeListener = OnTextChangeListener;
}
/**
* 清空所有輸入的內容
*/
public void clearText(){
setText("");
setInputType(InputType.TYPE_CLASS_NUMBER|InputType.TYPE_NUMBER_VARIATION_NORMAL);
}
/**
* 設定密碼框間距
*/
public void setSpace(int space){
spzceX = space;
spzceY = space;
}
/**
* 設定密碼框個數
*/
public void setTextLength(int textLength){
this.textLength = textLength;
}
/**
* 獲得密碼框個數
*/
public int getTextLength(){
return this.textLength;
}
/**
* 設定已輸入密碼框顏色
*/
public void setcheckedColorColor(int checkedColor){
this.checkedColor = checkedColor;
}
/**
* 設定未輸入密碼框顏色
*/
public void setdefaultColorColor(int defaultColor){
this.defaultColor = defaultColor;
}
/**
* 設定密碼框背景色
*/
public void setBackColor(int backColor){
this.backColor = backColor;
}
/**
* 設定密碼圓點的顏色
*/
public void setPwdTextColor(int textColor){
this.textColor = textColor;
}
/**
* 設定密碼框 邊框的寬度
*/
public void setStrokeWidth(int width){
StrokeWidth = width;
}
/**
* 密碼的圓點大小
*/
public void setCircle(int Circle){
this.Circle = Circle;
}
/**
* 密碼邊框的圓角大小
*/
public void setRound(int Round){
this.Round = Round;
}
public int getStrokeWidth() {
return StrokeWidth;
}
public int getSpzceX() {
return spzceX;
}
public int getSpzceY() {
return spzceY;
}
public int getCheckedColor() {
return checkedColor;
}
public int getDefaultColor() {
return defaultColor;
}
public int getBackColor() {
return backColor;
}
public int getTextColor() {
return textColor;
}
public int getCircle() {
return Circle;
}
public int getRound() {
return Round;
}
public int gettextSize() {
return textSize;
}
public void settextSize(int textSize) {
this.textSize = textSize;
}
public boolean isPwd() {
return isPwd;
}
/**
* 是否密文輸入
* @param pwd
*/
public void setPwd(boolean pwd) {
isPwd = pwd;
}
public int getWaitInputColor() {
return waitInputColor;
}
/**\
* 待輸入線的顏色
* @param waitInputColor
*/
public void setWaitInputColor(int waitInputColor) {
this.waitInputColor = waitInputColor;
}
public boolean isWaitInput() {
return isWaitInput;
}
/**
* 是否顯示待輸入的線
* @param waitInput
*/
public void setWaitInput(boolean waitInput) {
isWaitInput = waitInput;
}
}
style中的程式碼:
<declare-styleable name="PwdEditText">
<attr name="space" format="dimension"/>
<attr name="strokeWidth" format="dimension"/>
<attr name="checkedColor" format="color"/>
<attr name="defaultColor" format="color"/>
<attr name="textLength" format="integer"/>
<attr name="backColor" format="color"/>
<attr name="textColor" format="color"/>
<attr name="circle" format="dimension"/>
<attr name="round" format="dimension"/>
<attr name="textSize" format="dimension"/>
<attr name="isPwd" format="boolean"/>
<attr name="waitInputColor" format="color"/>
<attr name="isWaitInput" format="boolean"/>
</declare-styleable>