Android九宫格输入框
Android师哥 人气:0效果
实现
- 绘制宫格分割线
这里我们用一个RectF
类型的数组来装载数据。在onSizeChanged
方法中获取到控件尺寸,经过计算,将81个位置合适的矩形保存到数组中。
- 绘制点击效果
在onTouchEvent
方法中监听手指离开事件,当手指离开,获取到当前点击区域的RectF
,并将状态同样保存到一个数组中。
- 绘制输入内容
输入内容利用onTextChanged
方法获取,同样保存到一个数组中。
- PS
控件中没有考虑UI重建数据保存问题,使用中要注意这点~~~
这三个数组中数据一一对应,在onDraw
中,根据三个数组中数据内容绘制界面。完成我们的自定义View。
源码
/** * 自定义九宫格输入框 * attrs: customTableLineColor 宫格分割线颜色 * attrs: customTableLineWidth 宫格分割线宽度 * attrs: customTablePressColor 宫格选中时背景颜色 * attrs: customTableSpace 大宫格间隔 * attrs: customTableTextColor 宫格输入文字颜色 * attrs: customTableTextSize 宫格输入文字大小 * attrs: customTableAngle 宫格圆角尺寸 * 默认值请查看 {@link CustomEditText#initAttrs(Context, AttributeSet)} */ public class CustomEditText extends AppCompatEditText { private static final String TAG = "CustomEditText"; //宫格位置 private final RectF[] mTableList = new RectF[81]; //宫格状态 private final Boolean[] mTableState = new Boolean[81]; //宫格数据 private final Integer[] mTableListNumber = new Integer[81]; //绘制宫格画笔 private Paint mPaint; //绘制宫格背景画笔 private Paint mBackgroundPaint; //绘制文字画笔 private TextPaint mTextPaint; //手指离开屏幕X轴坐标 private float mTouchX; //手指离开屏幕Y轴坐标 private float mTouchY; //表格内文字尺寸 private float mTextSize; //表格内文字颜色 private int mTextColor; //表格分割线颜色 private int mTableLineColor; //选中对应宫格背景颜色 private int mTablePressColor; //表格分割线宽度 private float mTableLineWidht; //大宫格间隔 private float mTableSpace; //宫格圆角尺寸 private float mTableAngle; public CustomEditText(Context context) { this(context, null); } public CustomEditText(Context context, AttributeSet attrs) { this(context, attrs, R.attr.editTextStyle); } public CustomEditText(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); initAttrs(context, attrs); initSet(); initPaint(); } /** * 初始化自定义属性 */ private void initAttrs(Context context, AttributeSet attrs) { TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CustomEditText); mTextColor = typedArray.getColor(R.styleable.CustomEditText_customTableTextColor, Color.parseColor("#000000")); mTableLineColor = typedArray.getColor(R.styleable.CustomEditText_customTableLineColor, Color.parseColor("#000000")); mTablePressColor = typedArray.getColor(R.styleable.CustomEditText_customTablePressColor, Color.parseColor("#DDDDDD")); mTextSize = typedArray.getDimension(R.styleable.CustomEditText_customTableTextSize, TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 16, getResources().getDisplayMetrics())); mTableLineWidht = typedArray.getDimension(R.styleable.CustomEditText_customTableLineWidth, TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 1, getResources().getDisplayMetrics())); mTableSpace = typedArray.getDimension(R.styleable.CustomEditText_customTableSpace, TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 10, getResources().getDisplayMetrics())); mTableSpace = typedArray.getDimension(R.styleable.CustomEditText_customTableSpace, TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 10, getResources().getDisplayMetrics())); mTableAngle = typedArray.getDimension(R.styleable.CustomEditText_customTableAngle, 0); typedArray.recycle(); } /** * 初始化画笔 */ private void initPaint() { mBackgroundPaint = new Paint(); mBackgroundPaint.setAntiAlias(true); mBackgroundPaint.setStyle(Paint.Style.FILL); mBackgroundPaint.setColor(mTablePressColor); mPaint = new Paint(); mPaint.setAntiAlias(true); mPaint.setColor(mTableLineColor); mPaint.setStrokeWidth(mTableLineWidht); mPaint.setStyle(Paint.Style.STROKE); mTextPaint = new TextPaint(); mTextPaint.setColor(mTextColor); mTextPaint.setTextSize(mTextSize); mTextPaint.setAntiAlias(true); mTextPaint.setTextAlign(Paint.Align.CENTER); } /** * 初始化EditText基础设置 */ private void initSet() { //隐藏光标 setCursorVisible(false); //设置输入类型 setInputType(InputType.TYPE_CLASS_NUMBER); //限制输入一行 setSingleLine(true); } @Override protected void onDraw(Canvas canvas) { for (int i = 0; i < mTableList.length; i++) { RectF rectF = mTableList[i]; if (mTableState[i]) { //绘宫格制背景 canvas.drawRoundRect(rectF, mTableAngle, mTableAngle, mBackgroundPaint); } //绘制宫格分割线 canvas.drawRoundRect(rectF, mTableAngle, mTableAngle, mPaint); Integer integer = mTableListNumber[i]; if (integer != 0) { //测量文字尺寸 Rect measureTextSize = measureTextSize(integer + ""); //绘制输入内容 canvas.drawText(integer + "", rectF.centerX(), rectF.centerY() + measureTextSize.height() / 2.0F, mTextPaint); } } } @Override public boolean onTouchEvent(MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_UP) {//手指离开 mTouchX = event.getX(); mTouchY = event.getY(); //检查输入内容和状态是否对应 for (int i = 0; i < mTableListNumber.length; i++) { Integer integer = mTableListNumber[i]; if (integer == 0) { //背景应该为透明 if (mTableState[i]) { mTableState[i] = false; } } } //设置选中宫格 for (int i = 0; i < mTableList.length; i++) { if (mTableList[i].contains(mTouchX, mTouchY)) { mTableState[i] = true; invalidate(); break; } } } if (event.getAction() == MotionEvent.ACTION_DOWN) { performClick(); } return super.onTouchEvent(event); } @Override public boolean performClick() { return super.performClick(); } @Override protected void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) { super.onTextChanged(text, start, lengthBefore, lengthAfter); String trim = text.toString().trim(); if (!TextUtils.isEmpty(trim) && TextUtils.isDigitsOnly(trim)) { //保存输入内容 if (trim.length() > 1) { trim = trim.substring(trim.length() - 1, trim.length()); } for (int i = 0; i < mTableList.length; i++) { if (mTableList[i].contains(mTouchX, mTouchY)) { mTableListNumber[i] = Integer.parseInt(trim); //修改宫格背景状态 mTableState[i] = true; //清空默认EditText输入内容 CustomEditText.this.setText(""); break; } } } } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); //初始化宫格位置数据 int paddingLeft = getPaddingLeft(); int paddingRight = getPaddingRight(); int paddingTop = getPaddingTop(); int measuredWidth = getMeasuredWidth(); //表格实际显示的宽度 int tableWidht = (int) (measuredWidth - mTableSpace * 2 - paddingLeft - paddingRight); //每个表格的宽度 float singleTableWidth = tableWidht / 3.0F; for (int i = 0; i < 9; i++) { float top; float left; float bottom; float right; left = paddingLeft + (singleTableWidth * (i % 3)) + (mTableSpace * (i % 3)); right = left + singleTableWidth; top = paddingTop + (singleTableWidth * (i / 3)) + (mTableSpace * (i / 3)); bottom = top + singleTableWidth; //最大九个宫格的矩形 RectF rectF = new RectF(left, top, right, bottom); float width = rectF.width(); float singleTableWidthMin = width / 3.0F; for (int j = 0; j < 9; j++) { float topMin; float leftMin; float bottomMin; float rightMin; leftMin = singleTableWidthMin * (j % 3) + rectF.left; rightMin = leftMin + singleTableWidthMin; topMin = singleTableWidthMin * (j / 3) + rectF.top; bottomMin = topMin + singleTableWidthMin; //每个小宫格的矩形 RectF rectFMin = new RectF(leftMin, topMin, rightMin, bottomMin); for (int k = 0; k < mTableList.length; k++) { if (mTableList[k] == null) { mTableList[k] = rectFMin; mTableListNumber[k] = 0; mTableState[k] = false; break; } } } } } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { //强制控件为正方形 super.onMeasure(widthMeasureSpec, widthMeasureSpec); } /** * 测量文字的尺寸 * * @return 一个汉字的矩阵 */ private Rect measureTextSize(String content) { Rect mRect = null; if (!TextUtils.isEmpty(content)) { if (mTextPaint != null) { mRect = new Rect(); mTextPaint.getTextBounds(content, 0, content.length(), mRect); } } return mRect; } }
自定义属性
<resources> <declare-styleable name="CustomEditText"> <attr name="customTableTextSize" format="dimension" /> <attr name="customTableTextColor" format="color" /> <attr name="customTableLineColor" format="color" /> <attr name="customTableLineWidth" format="dimension" /> <attr name="customTableSpace" format="dimension" /> <attr name="customTablePressColor" format="color"/> <attr name="customTableAngle" format="integer"/> </declare-styleable> </resources>
加载全部内容