类似解锁或者支付密码输入框
先看效果图
1.实现原理:自定义view+EditText,上层为自定义view,用来绘制EditText的内容,输入内容的长短,可通过相关属性设置。
2.先上源代码
public class PasswordInputView extends View {
private Paint mTextPaint;//绘制Text输入内容的画笔
private int mTextColor = Color.BLACK;//字体颜色
private Paint mBorderPaint;//边框背景颜色
private int mBorderColor = Color.BLUE;
private float mBorderWidth = 4;//边框大小
private int mBackgroundColor = Color.WHITE;//背景色
private Paint mDividerPaint;//分割线
private float mDividerWidth = 2;//分割线宽度
private int mDividerColor = Color.BLUE;//分割线颜色
private float mBorderRadius = 45;//绘制圆角角度
private float mTextWidth;
private float mTextHeight;
private float mTextSize = 16;
private int mNum = 4;//输入内容长度
private EditText mInputView;//设置EditText用于获取焦点弹出键盘
public EditText getInputView() {
return mInputView;
}
public void setInputView(EditText mInputView) {
if (mInputView == null){
return;
}
this.mInputView = mInputView;
mInputView.setFilters(new InputFilter[]{new InputFilter.LengthFilter(mNum)});
mInputView.addTextChangedListener(textWatcher);
}
//谈键盘
private void forceInputViewGetFocus() {
if (mInputView == null){
return;
}
mInputView.setFocusable(true);
mInputView.setFocusableInTouchMode(true);
mInputView.requestFocus();
InputMethodManager imm = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
imm.showSoftInput(mInputView, InputMethodManager.SHOW_IMPLICIT);
}
private OnClickListener mOnClickListener = new OnClickListener() {
@Override
public void onClick(View v) {
forceInputViewGetFocus();
}
};
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) {
invalidate();//内容发生改变时重新绘制
}
@Override
public void afterTextChanged(Editable s) {
}
};
public PasswordInputView(Context context) {
super(context);
init(null, 0);
}
public PasswordInputView(Context context, AttributeSet attrs) {
super(context, attrs);
init(attrs, 0);
}
public PasswordInputView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(attrs, defStyle);
}
public int getTextColor() {
return mTextColor;
}
public void setTextColor(int mTextColor) {
this.mTextColor = mTextColor;
invalidate();
}
public void setBackgroundColor(int mBackgroundColor) {
this.mBackgroundColor = mBackgroundColor;
invalidate();
}
public int getBackgroundColor() {
return mBackgroundColor;
}
public int getBorderColor() {
return mBorderColor;
}
public void setBorderColor(int mBorderColor) {
this.mBorderColor = mBorderColor;
mBorderPaint.setColor(mBorderColor);
invalidate();
}
public float getBorderWidth() {
return mBorderWidth;
}
public void setBorderWidth(float mBorderWidth) {
this.mBorderWidth = mBorderWidth;
invalidate();
}
public float getDividerWidth() {
return mDividerWidth;
}
public void setDividerWidth(float mDividerWidth) {
this.mDividerWidth = mDividerWidth;
invalidate();
}
public int getDividerColor() {
return mDividerColor;
}
public void setDividerColor(int mDividerColor) {
this.mDividerColor = mDividerColor;
invalidate();
}
public float getBorderRadius() {
return mBorderRadius;
}
public void setBorderRadius(float mBorderRadius) {
this.mBorderRadius = mBorderRadius;
invalidate();
}
public int getNum() {
return mNum;
}
public void setNum(int mNum) {
this.mNum = mNum;
if (mInputView == null){
return;
}
mInputView.setFilters(new InputFilter[]{new InputFilter.LengthFilter(mNum)});
invalidate();
}
private void init(AttributeSet attrs, int defStyle) {
// Load attributes
final TypedArray a = getContext().obtainStyledAttributes(
attrs, R.styleable.PasswordInputView, defStyle, 0);
mTextColor = a.getColor(
R.styleable.PasswordInputView_borderColor,
mTextColor);
mBorderColor = a.getColor(
R.styleable.PasswordInputView_borderColor,
mBorderColor);
mBackgroundColor = a.getColor(
R.styleable.PasswordInputView_backGroundColor,
mBackgroundColor);
mDividerColor = a.getColor(
R.styleable.PasswordInputView_borderColor,
mDividerColor);
// Use getDimensionPixelSize or getDimensionPixelOffset when dealing with
// values that should fall on pixel boundaries.
mDividerWidth = a.getDimension(
R.styleable.PasswordInputView_dividerW,
mDividerWidth);
mBorderWidth = a.getDimension(
R.styleable.PasswordInputView_borderW,
mBorderWidth);
mBorderRadius= a.getDimension(
R.styleable.PasswordInputView_borderRadius,
mBorderRadius);
a.recycle();
// Set up a default TextPaint object
mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
setTextSize(mTextSize);
mBorderPaint= new Paint();
mBorderPaint.setColor(mBorderColor);
mBorderPaint.setFlags(Paint.ANTI_ALIAS_FLAG);
mDividerPaint= new Paint();
mBorderPaint.setFlags(Paint.ANTI_ALIAS_FLAG);
mDividerPaint.setColor(mDividerColor);
setOnClickListener(mOnClickListener);
}
@Override
protected void onDraw(Canvas canvas) {
int width = getWidth();
int height = getHeight();
RectF rect = new RectF(0,0,width,height);
//背景
mBorderPaint.setColor(mBackgroundColor);
canvas.drawRoundRect(rect, mBorderRadius, mBorderRadius, mBorderPaint);
//外边框
mBorderPaint.setStrokeWidth(mBorderWidth);
mBorderPaint.setColor(mBorderColor);
mBorderPaint.setStyle(Paint.Style.STROKE);
canvas.drawRoundRect(rect,mBorderRadius,mBorderRadius,mBorderPaint);
// 分割线
mDividerPaint.setStrokeWidth(mDividerWidth);
for (int i = 1; i < mNum; i++) {
canvas.drawLine(width/mNum*i,0+mBorderWidth/2,width/mNum*i,height-mBorderWidth/2,mDividerPaint);
}
//绘制内容
if (mInputView !=null){
if (!TextUtils.isEmpty(mInputView.getText())){
String text = mInputView.getText().toString();
// Draw the text.
for (int i = 0; i < Math.min(text.length(),mNum); i++) {
String s= text.substring(i,i+1);
mTextWidth = mTextPaint.measureText(s);
Paint.FontMetrics fontMetrics = mTextPaint.getFontMetrics();
mTextHeight = fontMetrics.bottom;
canvas.drawText(s,
width/mNum*i+width/mNum/2-mTextWidth/2,
height/ 2 +mTextHeight,
mTextPaint);
}
}
}
}
private void setTextSize(float size) {
Context c = getContext();
Resources r;
if (c == null)
r = Resources.getSystem();
else
r = c.getResources();
if (size != mTextPaint.getTextSize()) {
mTextPaint.setTextSize(TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_SP, size, r.getDisplayMetrics()));
requestLayout();
invalidate();
}
}
}
3.相关用法
xml
<FrameLayout
android:layout_width="244dp"
android:layout_height="45dp"
android:layout_marginTop="100dp"
android:layout_centerHorizontal="true">
<EditText
android:id="@+id/edit"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@null"
android:cursorVisible="false"
android:inputType="number"/>
<com.example.administrator.myproject.view.PasswordInputView
android:id="@+id/text"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</FrameLayout>
自定义属性文件
<resources>
<declare-styleable name="PasswordInputView">
<attr name="textColor" format="color" />
<attr name="dividerW" format="dimension" />
<attr name="borderW" format="dimension" />
<attr name="borderColor" format="color" />
<attr name="backGroundColor" format="color" />
<attr name="dividerColor" format="color" />
<attr name="borderRadius" format="dimension" />
</declare-styleable>
</resources>
Java代码
mInputView = (EditText) findViewById(R.id.edit);
mCodeView = (PasswordInputView) findViewById(R.id.text);
mCodeView.setInputView(mInputView);
mCodeView.setBorderRadius(20);