今天在项目中遇到一个类似微信支付的密码输入框的需求,具体的实现要求如下:
因为这样的一个控件主要实现的密码输入的功能,这大体上和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>
源码下载