今天在项目中遇到一个类似微信支付的密码输入框的需求,具体的实现要求如下:
因为这样的一个控件主要实现的密码输入的功能,这大体上和Edittext相似,但不同于EditText的一点就是该控件需要显示六个密码框。对于控件在展示上不同的问题,毫无疑问,需要通过重写onDraw方法来实现。
具体代码如下:
package com.example.pwdeditttextdemo;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.widget.EditText;
/**
*
* 自定义密码输入框
*
* @author zhangke
*
*/
public class PwdEditText extends EditText {
/**
* 间隔
*/
private final int PWD_SPACING = 5;
/**
* 密码大小
*/
private final int PWD_SIZE = 5;
/**
* 密码长度
*/
private final int PWD_LENGTH = 6;
/**
* 上下文
*/
private Context mContext;
/**
* 宽度
*/
private int mWidth;
/**
* 高度
*/
private int mHeight;
/**
* 密码框
*/
private Rect mRect;
/**
* 密码画笔
*/
private Paint mPwdPaint;
/**
* 密码框画笔
*/
private Paint mRectPaint;
/**
* 输入的密码长度
*/
private int mInputLength;
/**
* 输入结束监听
*/
private OnInputFinishListener mOnInputFinishListener;
/**
* 构造方法
*
* @param context
* @param attrs
*/
public PwdEditText(Context context, AttributeSet attrs) {
super(context, attrs);
// 初始化密码画笔
mPwdPaint = new Paint();
mPwdPaint.setColor(Color.BLACK);
mPwdPaint.setStyle(Paint.Style.FILL);
mPwdPaint.setAntiAlias(true);
// 初始化密码框
mRectPaint = new Paint();
mRectPaint.setStyle(Paint.Style.STROKE);
mRectPaint.setColor(Color.LTGRAY);
mRectPaint.setAntiAlias(true);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
mWidth = getWidth();
mHeight = getHeight();
// 这三行代码非常关键,大家可以注释点在看看效果
Paint paint = new Paint();
paint.setColor(Color.WHITE);
canvas.drawRect(0, 0, mWidth, mHeight, paint);
// 计算每个密码框宽度
int rectWidth = (mWidth - PWD_SPACING * (PWD_LENGTH - 1)) / PWD_LENGTH;
// 绘制密码框
for (int i = 0; i < PWD_LENGTH; i++) {
int left = (rectWidth + PWD_SPACING) * i;
int top = 2;
int right = left + rectWidth;
int bottom = mHeight - top;
mRect = new Rect(left, top, right, bottom);
canvas.drawRect(mRect, mRectPaint);
}
// 绘制密码
for (int i = 0; i < mInputLength; i++) {
int cx = rectWidth / 2 + (rectWidth + PWD_SPACING) * i;
int cy = mHeight / 2;
canvas.drawCircle(cx, cy, PWD_SIZE, mPwdPaint);
}
}
@Override
protected void onTextChanged(CharSequence text, int start,
int lengthBefore, int lengthAfter) {
super.onTextChanged(text, start, lengthBefore, lengthAfter);
this.mInputLength = text.toString().length();
invalidate();
if (mInputLength == PWD_LENGTH && mOnInputFinishListener != null) {
mOnInputFinishListener.onInputFinish(text.toString());
}
}
public interface OnInputFinishListener {
/**
* 密码输入结束监听
*
* @param password
*/
void onInputFinish(String password);
}
/**
* 设置输入完成监听
*
* @param onInputFinishListener
*/
public void setOnInputFinishListener(
OnInputFinishListener onInputFinishListener) {
this.mOnInputFinishListener = onInputFinishListener;
}
}
在代码中调用:
public class MainActivity extends Activity {
private PwdEditText mPetPwd;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mPetPwd = (PwdEditText) findViewById(R.id.pet_pwd);
mPetPwd.setOnInputFinishListener(new OnInputFinishListener() {
@Override
public void onInputFinish(String password) {
Toast.makeText(MainActivity.this, password, 1).show();
}
});
}
}
布局文件:
<LinearLayout 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"
android:gravity="center"
android:orientation="vertical" >
<com.example.pwdeditttextdemo.PwdEditText
android:id="@+id/pet_pwd"
android:layout_width="200dp"
android:layout_height="50dp"
android:background="@android:color/transparent"
android:cursorVisible="false"
android:enabled="true"
android:focusable="true"
android:maxLength="6" />
</LinearLayout>
效果图