一个字符带下滑线的EditText
效果样式:
这个比较特别的editText是公司的一个新的需求,我也是在网上找了一下,然后看到了一篇博客然后修改成自己需要的样式。这种一般的思路就是在onDraw()方法绘制editText的特别的样式,如果输入里面的值是*这种特殊字符就只用直接绘制,如果需要输入进去的值则可以在onTextChanged方法中获取每一次更改editText值,在onDraw方法里一个个的绘制。
自定义的editText
package com.kkrs.selfedit; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.RectF; import android.text.InputFilter; import android.text.TextUtils; import android.util.AttributeSet; import android.util.Log; import android.widget.EditText; import static android.graphics.Paint.ANTI_ALIAS_FLAG; /** * Created by zd on 2018/11/27. */ public class InputView extends EditText { private Context mContext; /** * 第一个圆开始绘制的圆心坐标 */ private float startX; private float startY; private float cX; int psdType = 0; /** * 实心圆的半径 */ private int radius = 10; /** * view的高度 */ private int height; private int width; /** * 当前输入密码位数 */ private int textLength = 0; private int bottomLineLength; /** * 最大输入位数 */ private int maxCount = 6; /** * 圆的颜色 默认BLACK */ private int circleColor = Color.BLACK; /** * 底部线的颜色 默认GRAY */ private int bottomLineColor = Color.GRAY; /** * 分割线开始的坐标x */ private int divideLineWStartX; /** * 分割线的宽度 默认2 */ private int divideLineWidth = 2; /** * 竖直分割线的颜色 */ private int divideLineColor = Color.GRAY; private int focusedColor = Color.BLUE; private RectF rectF = new RectF(); private RectF focusedRecF = new RectF(); private String texts = ""; /** * 矩形边框的圆角 */ private int rectAngle = 0; /** * 圆的画笔 */ private Paint circlePaint; /** * 底部线的画笔 */ private Paint bottomLinePaint; /** * 需要对比的密码 一般为上次输入的 */ private String mComparePassword = null; /** * 当前输入的位置索引 */ private int position = 0; private onPasswordListener mListener; public InputView(Context context, AttributeSet attrs) { super(context, attrs); mContext = context; getAtt(attrs); initPaint(); this.setBackgroundColor(Color.TRANSPARENT); this.setCursorVisible(false); this.setFilters(new InputFilter[]{new InputFilter.LengthFilter(maxCount)}); } private void getAtt(AttributeSet attrs) { TypedArray typedArray = mContext.obtainStyledAttributes(attrs, R.styleable.PayPsdInputView); maxCount = typedArray.getInt(R.styleable.PayPsdInputView_maxCount, maxCount); circleColor = typedArray.getColor(R.styleable.PayPsdInputView_circleColor, circleColor); bottomLineColor = typedArray.getColor(R.styleable.PayPsdInputView_bottomLineColor, bottomLineColor); radius = typedArray.getDimensionPixelOffset(R.styleable.PayPsdInputView_radius, radius); divideLineWidth = typedArray.getDimensionPixelSize(R.styleable.PayPsdInputView_divideLineWidth, divideLineWidth); divideLineColor = typedArray.getColor(R.styleable.PayPsdInputView_divideLineColor, divideLineColor); psdType = typedArray.getInt(R.styleable.PayPsdInputView_psdType, psdType); rectAngle = typedArray.getDimensionPixelOffset(R.styleable.PayPsdInputView_rectAngle, rectAngle); focusedColor = typedArray.getColor(R.styleable.PayPsdInputView_focusedColor, focusedColor); typedArray.recycle(); } /** * 初始化画笔 */ private void initPaint() { circlePaint = getPaint(5, Paint.Style.FILL, circleColor); bottomLinePaint = getPaint(2, Paint.Style.FILL, bottomLineColor); } /** * 设置画笔 * * @param strokeWidth 画笔宽度 * @param style 画笔风格 * @param color 画笔颜色 * @return */ private Paint getPaint(int strokeWidth, Paint.Style style, int color) { Paint paint = new Paint(ANTI_ALIAS_FLAG); paint.setStrokeWidth(strokeWidth); paint.setStyle(style); paint.setColor(color); paint.setAntiAlias(true); paint.setTextSize(40); return paint; } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); height = h; width = w; divideLineWStartX = w / maxCount; startX = w / maxCount / 2; startY = h / 2; bottomLineLength = w / (maxCount + 2); rectF.set(0, 0, width, height); } @Override protected void onDraw(Canvas canvas) { //不删除的画会默认绘制输入的文字 // super.onDraw(canvas); drawBottomBorder(canvas); switch (psdType){ case 0: char[] cc; cc=texts.toCharArray(); for (int i = 0; i < cc.length; i++) { Log.e("sys","cc="+cc[i]); canvas.drawText(cc[i]+"",startX + i * 2 * startX, startY,circlePaint); } break; case 1: drawPsdCircle(canvas); break; } } /** * 画密码实心圆 * * @param canvas */ private void drawPsdCircle(Canvas canvas) { for (int i = 0; i < textLength; i++) { canvas.drawCircle(startX + i * 2 * startX, startY, radius, circlePaint); } } /** * 画底部显示的分割线 * * @param canvas */ private void drawBottomBorder(Canvas canvas) { for (int i = 0; i < maxCount; i++) { cX = startX + i * 2 * startX; canvas.drawLine(cX - bottomLineLength / 2, height, cX + bottomLineLength / 2, height, bottomLinePaint); } } @Override protected void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) { super.onTextChanged(text, start, lengthBefore, lengthAfter); this.position = start + lengthAfter; textLength = text.toString().length(); texts = text.toString(); Log.e("onTextChanged",text.toString()); if (textLength == maxCount) { if (mListener != null) { if (TextUtils.isEmpty(mComparePassword)) { mListener.inputFinished(getPasswordString()); } else { if (TextUtils.equals(mComparePassword, getPasswordString())) { mListener.onEqual(getPasswordString()); } else { mListener.onDifference(mComparePassword, getPasswordString()); } } } } invalidate(); } @Override protected void onSelectionChanged(int selStart, int selEnd) { super.onSelectionChanged(selStart, selEnd); //保证光标始终在最后 if (selStart == selEnd) { setSelection(getText().length()); } } /** * 获取输入的密码 * * @return */ public String getPasswordString() { return getText().toString().trim(); } public void setComparePassword(String comparePassword, onPasswordListener listener) { mComparePassword = comparePassword; mListener = listener; } public void setComparePassword(onPasswordListener listener) { mListener = listener; } public void setComparePassword(String psd) { mComparePassword = psd; } /** * 清空密码 */ public void cleanPsd() { setText(""); } /** * 密码比较监听 */ public interface onPasswordListener { void onDifference(String oldPsd, String newPsd); void onEqual(String psd); void inputFinished(String inputPsd); } }
在xml的用法:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" xmlns:psd="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <com.kkrs.selfedit.InputView android:id="@+id/pwd" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="10dp" android:layout_marginTop="20dp" android:inputType="number" psd:maxCount="6" psd:psdType="pwd"/> <com.kkrs.selfedit.InputView android:id="@+id/phone" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="10dp" android:layout_marginTop="20dp" android:inputType="number" psd:maxCount="11" psd:psdType="phone"/> </LinearLayout>
github:https://github.com/tempest1/SelfEdit