前言
首先,我们来看看实现的是怎么样的效果:
如果我们拿到这样的UI,想到的布局应该是用4个EditText包在横向的LinearLayout里面,但今天要讲的View,所以我们决定用一个自定义的EditText 画出来。
学到什么?
功能需求
思路
完全重画一个EditText,就包含了测量布局和重新绘制这两个关键步骤。好了,到这里理一下整体的思路:
开始动手
准备开始了,果断继承一个AppCompatEditText 来初始化基本参数先:
/** * 验证码输入框,重写EditText的绘制方法实现。 * @author RAE */ public class CodeEditText extends AppCompatEditText { // 验证码文本颜色 private int mTextColor; // 输入的最大长度 private int mMaxLength = 4; // 边框宽度 private int mStrokeWidth; // 边框高度 private int mStrokeHeight; // 边框之间的距离 private int mStrokePadding = 20; // 用矩形来保存方框的位置、大小信息 private final Rect mRect = new Rect(); // 方框的背景 private Drawable mStrokeDrawable; /** * 构造方法 * */ public CodeEditText(Context context, AttributeSet attrs) { super(context, attrs); TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CodeEditText); int indexCount = typedArray.getIndexCount(); for (int i = 0; i= 0) { setFilters(new InputFilter[]{new InputFilter.LengthFilter(maxLength)}); } else { setFilters(new InputFilter[0]); } } }
开始测量布局
初始化完了就要开始测量布局了,计算公式为:
输入框宽度 = 边框宽度 * 数量 + 边框间距 *(数量-1)
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); // 当前输入框的宽高信息 int width = getMeasuredWidth(); int height = getMeasuredHeight(); int widthMode = MeasureSpec.getMode(widthMeasureSpec); int heightMode = MeasureSpec.getMode(heightMeasureSpec); // 判断高度是否小于推荐高度 if (height
画家登场
来到最重要的步骤了,重画输入框!来一步步看代码注释:
@Override protected void onDraw(Canvas canvas) { // 在画支持设置文本颜色,把系统化的文本透明掉,相当于覆盖 mTextColor = getCurrentTextColor(); setTextColor(Color.TRANSPARENT); // 系统画的方法 super.onDraw(canvas); // 重新设置文本颜色 setTextColor(mTextColor); // 重绘背景颜色 drawStrokeBackground(canvas); // 重绘文本 drawText(canvas); }
绘制背景方框
/** * 绘制方框 */ private void drawStrokeBackground(Canvas canvas) { // 下面绘制方框背景颜色 // 确定反馈位置 mRect.left = 0; mRect.top = 0; mRect.right = mStrokeWidth; mRect.bottom = mStrokeHeight; int count = canvas.getSaveCount(); // 当前画布保存的状态 canvas.save(); // 保存画布 for (int i = 0; i
一般画布的移动canvas.translate(x,y)会结合canvas.save();来使用。
1、调用canvas.save();保存当前画布的状态,用PS来解析就是按下ctrl +s键,然后帮你新建一个新的图层。你之后画的内容不会影响到之前画的内容,要回到之前的状态就调用canvas.restoreToCount(count)来还原。
2、把画布的位置移到下一个位置canvas.translate(x,y),下图所示,你会发现方框在画布中的位置没有发生变化而是画布距离发生了变化。这就是画布平移的效果了。
画验证码文字
/** * 重绘文本 */ private void drawText(Canvas canvas) { int count = canvas.getSaveCount(); canvas.translate(0, 0); int length = getEditableText().length(); for (int i = 0; i
监听文本变化回调自动完成方法
@Override protected void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) { super.onTextChanged(text, start, lengthBefore, lengthAfter); // 当前文本长度 int textLength = getEditableText().length(); if (textLength == mMaxLength) { hideSoftInput(); if (mOnInputFinishListener != null) { mOnInputFinishListener.onTextFinish(getEditableText().toString(), mMaxLength); } } }
查看完整的源码
到这里你能大概理解画布的概念了,本文完。
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对的支持。