在日常開發(fā)中有時需要實(shí)現(xiàn)在一個輸入框中輸入字并且同步顯示已輸入字符的長度鳖宾,以方便查看此輸入框最大能輸入多少字符怠噪,現(xiàn)在已輸入多少字符。實(shí)現(xiàn)效果如下:
1516330704071mz效果圖.gif
主要實(shí)現(xiàn)步驟及相關(guān)代碼:
1.首先創(chuàng)建一個類繼承EditText,實(shí)現(xiàn)構(gòu)造方法议纯;
2.定義相關(guān)屬性:在《項(xiàng)目名稱》\src\main\res\values\attrs.xml文件中:
<declare-styleable name="WordsNumEditText">
<attr name="numTextGravity" format="enum">
<enum name="left" value="1" />
<enum name="right" value="2" />
</attr>
<attr name="numTextSize" format="dimension" />
<attr name="numTextColor" format="color" />
3.初始化設(shè)置的相關(guān)屬性:
/**
* @param context
* @param attrs 初始化屬性
*/
private void initAttribute(Context context, AttributeSet attrs) {
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.WordsNumEditText);
try {
mNumTextSize = (int) ta.getDimension(R.styleable.WordsNumEditText_numTextSize, DensityUtils.sp2px(context, 12));//字體大小
mNumTextColor = ta.getColor(R.styleable.WordsNumEditText_numTextColor, Color.parseColor("#b1b1b1"));//字體顏色
grivity = ta.getInt(R.styleable.WordsNumEditText_numTextGravity, grivity);//顯示的位置崩溪,left從左向右擴(kuò)展浅役,right從右向左擴(kuò)展顯示,
maxLength = getMaxLength();//獲取設(shè)置的最大顯示字?jǐn)?shù)
paddingLeft = getPaddingLeft();
paddingRight = getPaddingRight();
bottom = DensityUtils.dip2px(context, 10);
setPadding(getPaddingLeft(), getPaddingTop(), getPaddingRight(), getPaddingBottom() + DensityUtils.dip2px(context, 10));
} finally {
ta.recycle();
}
initPaint();//初始化畫筆
}
其中獲取editText的maxLength屬性值的方法詳情如下:
/**
* @return length
* 獲取editText的MaxLength的屬性值
*/
public int getMaxLength() {
int length = 0;
try {
InputFilter[] inputFilters = this.getFilters();
for (InputFilter filter : inputFilters) {
Class<?> c = filter.getClass();
if (c.getName().equals("android.text.InputFilter$LengthFilter")) {
Field[] f = c.getDeclaredFields();
for (Field field : f) {
if (field.getName().equals("mMax")) {
field.setAccessible(true);
length = (Integer) field.get(filter);
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return length;
}
3.初始化畫筆伶唯,需根據(jù)設(shè)置的grivity屬性確定畫筆滑動的方向:
/**
* 創(chuàng)建一個畫筆
*
* @param paintColor 畫筆顏色
* @param textSize 文字大小
* @param style 畫筆樣式
* @param roundWidth 畫筆寬度
* @return
*/
private Paint createLeftPaint(int paintColor, int textSize, Paint.Style style, int roundWidth) {
Paint paint = new Paint();
paint.setColor(paintColor);
paint.setAntiAlias(true);
paint.setStrokeWidth(roundWidth);
paint.setDither(true);
paint.setTextSize(textSize);
paint.setTextAlign(Paint.Align.LEFT);//這是grivity為left的時候觉既,若grivity是right,則設(shè)置為 Paint.Align.RIGHT
paint.setStyle(style);
paint.setStrokeCap(Paint.Cap.ROUND);
paint.setStrokeJoin(Paint.Join.ROUND);
return paint;
}
4.在onDraw()中實(shí)現(xiàn)畫“數(shù)字”的邏輯:
/**
* @param canvas 畫輸入框中 字?jǐn)?shù)/最大字?jǐn)?shù)
*/
private void drawNumberText(Canvas canvas) {
int length = getText().length();
String str = length + "/" + maxLength;
int x = 0;
if (grivity == GRAVITY_LEFT) {
x = 0 + paddingLeft;
} else {
x = width - paddingRight;
}
int y = height - bottom;
canvas.drawText(str, x, y, textPaint);
}
其中width和height需要在onMeasure()中實(shí)時計(jì)算:
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
width = w;
height = h;
}
最后附上完整代碼及demo地址(名稱有些繁瑣,莫見怪哈):https://github.com/ErieCorner/DesplayInputCharacterLengthEdittextModule.git
public class DeplayInputCharacterLenghtEditText extends EditText {
public DeplayInputCharacterLenghtEditText(Context context) {
super(context);
initAttribute(context, null);
}
public DeplayInputCharacterLenghtEditText(Context context, AttributeSet attrs) {
super(context, attrs);
initAttribute(context, attrs);
}
public DeplayInputCharacterLenghtEditText(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initAttribute(context, attrs);
}
private int mNumTextColor = Color.parseColor("#b1b1b1");
private int mNumTextSize = 12;
public final static int GRAVITY_LEFT = 1;//字?jǐn)?shù)顯示在左邊瞪讼,當(dāng)數(shù)字位數(shù)增多時向右擴(kuò)展
public final static int GRAVITY_RIGHT = 2;//字?jǐn)?shù)顯示在右邊钧椰,當(dāng)數(shù)字位數(shù)增多時向左擴(kuò)展
private int grivity = GRAVITY_RIGHT;
private Context context;
private Paint textPaint;
private int width;
private int height;
private int maxLength;
private int paddingLeft = 0;
private int paddingRight = 0;
private int bottom = 0;
/**
* 初始化畫筆
*/
private void initPaint() {
if (grivity == GRAVITY_LEFT) {
textPaint = createLeftPaint(mNumTextColor, mNumTextSize, Paint.Style.FILL, 2);
} else {
textPaint = createRightPaint(mNumTextColor, mNumTextSize, Paint.Style.FILL, 2);
}
}
/**
* @param context
* @param attrs 初始化屬性
*/
private void initAttribute(Context context, AttributeSet attrs) {
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.DeplayInputCharacterLenghtEditText);
try {
mNumTextSize = (int) ta.getDimension(R.styleable.DeplayInputCharacterLenghtEditText_numTextSize, DensityUtils.sp2px(context, 12));
mNumTextColor = ta.getColor(R.styleable.DeplayInputCharacterLenghtEditText_numTextColor, Color.parseColor("#b1b1b1"));
grivity = ta.getInt(R.styleable.DeplayInputCharacterLenghtEditText_numTextGravity, grivity);
maxLength = getMaxLength();
} finally {
ta.recycle();
}
paddingLeft = getPaddingLeft();
paddingRight = getPaddingRight();
bottom = DensityUtils.dip2px(context, 10);
setPadding(getPaddingLeft(), getPaddingTop(), getPaddingRight(), getPaddingBottom() + DensityUtils.dip2px(context, 10));
initPaint();
}
/**
* 判斷是否為emoji表情
*
* @param codePoint 要校驗(yàn)的字符
* @return 是否為表情
*/
private boolean isEmojiCharacter(char codePoint) {
return !((codePoint == 0x0) || (codePoint == 0x9) || (codePoint == 0xA) ||
(codePoint == 0xD) || ((codePoint >= 0x20) && codePoint <= 0xD7FF)) ||
((codePoint >= 0xE000) && (codePoint <= 0xFFFD));
}
/**
* 創(chuàng)建一個畫筆
*
* @param paintColor 畫筆顏色
* @param textSize 文字大小
* @param style 畫筆樣式
* @param roundWidth 畫筆寬度
* @return
*/
private Paint createLeftPaint(int paintColor, int textSize, Paint.Style style, int roundWidth) {
Paint paint = new Paint();
paint.setColor(paintColor);
paint.setAntiAlias(true);
paint.setStrokeWidth(roundWidth);
paint.setDither(true);
paint.setTextSize(textSize);
paint.setTextAlign(Paint.Align.LEFT);
paint.setStyle(style);
paint.setStrokeCap(Paint.Cap.ROUND);
paint.setStrokeJoin(Paint.Join.ROUND);
return paint;
}
/**
* 創(chuàng)建一個畫筆
*
* @param paintColor 畫筆顏色
* @param textSize 文字大小
* @param style 畫筆樣式
* @param roundWidth 畫筆寬度
* @return
*/
private Paint createRightPaint(int paintColor, int textSize, Paint.Style style, int roundWidth) {
Paint paint = new Paint();
paint.setColor(paintColor);
paint.setAntiAlias(true);
paint.setStrokeWidth(roundWidth);
paint.setDither(true);
paint.setTextSize(textSize);
paint.setTextAlign(Paint.Align.RIGHT);
paint.setStyle(style);
paint.setStrokeCap(Paint.Cap.ROUND);
paint.setStrokeJoin(Paint.Join.ROUND);
return paint;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
drawNumberText(canvas);
}
/**
* @param canvas 畫輸入框中 字?jǐn)?shù)/最大字?jǐn)?shù)
*/
private void drawNumberText(Canvas canvas) {
int length = getText().length();
String str = length + "/" + maxLength;
int x = 0;
if (grivity == GRAVITY_LEFT) {
x = 0 + paddingLeft;
} else {
x = width - paddingRight;
}
int y = height - bottom;
canvas.drawText(str, x, y, textPaint);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
width = w;
height = h;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
@Override
protected void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) {
super.onTextChanged(text, start, lengthBefore, lengthAfter);
postInvalidate();
}
/**
* @return length
* 獲取editText的MaxLength的屬性值
*/
public int getMaxLength() {
int length = 0;
try {
InputFilter[] inputFilters = this.getFilters();
for (InputFilter filter : inputFilters) {
Class<?> c = filter.getClass();
if (c.getName().equals("android.text.InputFilter$LengthFilter")) {
Field[] f = c.getDeclaredFields();
for (Field field : f) {
if (field.getName().equals("mMax")) {
field.setAccessible(true);
length = (Integer) field.get(filter);
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return length;
}
}