Skip to content

Commit 6ffe1c3

Browse files
author
0xZhangKe
committed
add InputNumberView
0 parents  commit 6ffe1c3

File tree

3 files changed

+310
-0
lines changed

3 files changed

+310
-0
lines changed

NumberInputView/NumberInputView.java

+259
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,259 @@
1+
package com.zhangke.window;
2+
3+
import android.content.Context;
4+
import android.content.res.TypedArray;
5+
import android.graphics.Canvas;
6+
import android.graphics.Paint;
7+
import android.graphics.RectF;
8+
import android.support.annotation.AttrRes;
9+
import android.support.annotation.NonNull;
10+
import android.support.annotation.Nullable;
11+
import android.support.v7.widget.AppCompatEditText;
12+
import android.support.v7.widget.AppCompatTextView;
13+
import android.text.Editable;
14+
import android.text.InputType;
15+
import android.text.TextPaint;
16+
import android.text.TextUtils;
17+
import android.text.TextWatcher;
18+
import android.util.AttributeSet;
19+
import android.view.KeyEvent;
20+
import android.view.MotionEvent;
21+
import android.view.View;
22+
import android.view.inputmethod.EditorInfo;
23+
import android.view.inputmethod.InputConnection;
24+
import android.view.inputmethod.InputMethodManager;
25+
import android.widget.TextView;
26+
27+
import java.util.List;
28+
29+
30+
/**
31+
* @author 张可
32+
* @version 1.0
33+
* @date 2017.03.27
34+
*/
35+
public class NumberInputView extends View {
36+
37+
/**
38+
* 输入框个数
39+
*/
40+
private int count = 4;
41+
/**
42+
* 每个框大小
43+
*/
44+
private int boxSize;
45+
/**
46+
* 文本大小
47+
*/
48+
private int textSize;
49+
/**
50+
* 文本颜色
51+
*/
52+
private int textColor;
53+
/**
54+
* padding
55+
*/
56+
private int padding;
57+
58+
/**
59+
* 当前已输入的文本
60+
*/
61+
private StringBuilder currentNumber = new StringBuilder();
62+
63+
private InputMethodManager inputMethodManager;
64+
private Paint boxPaint = new Paint();
65+
private TextPaint textPaint = new TextPaint();
66+
67+
private float textBaseY = 0f;
68+
69+
public NumberInputView(@NonNull Context context) {
70+
super(context);
71+
init();
72+
}
73+
74+
public NumberInputView(@NonNull Context context, @Nullable AttributeSet attrs) {
75+
super(context, attrs);
76+
if (null != attrs) {
77+
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.NumberInputView);
78+
count = a.getInteger(R.styleable.NumberInputView_box_count, 4);
79+
a.recycle();
80+
}
81+
init();
82+
}
83+
84+
public NumberInputView(@NonNull Context context, @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) {
85+
super(context, attrs, defStyleAttr);
86+
if (null != attrs) {
87+
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.NumberInputView);
88+
count = a.getInteger(R.styleable.NumberInputView_box_count, 4);
89+
a.recycle();
90+
}
91+
init();
92+
}
93+
94+
private void init() {
95+
boxSize = UiTools.dip2px(getContext(), 50);
96+
padding = UiTools.dip2px(getContext(), 5);
97+
textSize = UiTools.sp2px(getContext(), 20);
98+
textColor = getContext().getResources().getColor(R.color.text_black);
99+
List l;
100+
101+
boxPaint.setAntiAlias(true);
102+
boxPaint.setColor(getContext().getResources().getColor(R.color.text_black));
103+
boxPaint.setStyle(Paint.Style.STROKE);
104+
105+
textPaint.setTextSize(textSize);
106+
textPaint.setColor(textColor);
107+
textPaint.setTextAlign(Paint.Align.CENTER);
108+
Paint.FontMetrics fontMetrics = textPaint.getFontMetrics();
109+
float fontHeight = fontMetrics.bottom - fontMetrics.top;
110+
111+
inputMethodManager = (InputMethodManager) getContext()
112+
.getSystemService(Context.INPUT_METHOD_SERVICE);
113+
114+
setFocusableInTouchMode(true);
115+
showInputMethod();
116+
setBackground(null);
117+
}
118+
119+
@Override
120+
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
121+
int width;
122+
int height;
123+
width = count * boxSize + padding * 2;
124+
height = boxSize + padding * 2;
125+
setMeasuredDimension(width, height);
126+
}
127+
128+
@Override
129+
protected void onDraw(Canvas canvas) {
130+
drawFrame(canvas);
131+
132+
Paint.FontMetrics fontMetrics = textPaint.getFontMetrics();
133+
float fontHeight = fontMetrics.bottom - fontMetrics.top;
134+
if (textBaseY == 0)
135+
textBaseY = getHeight() - (getHeight() - fontHeight) / 2 - fontMetrics.bottom;
136+
int y = (int) textBaseY;
137+
138+
if (!TextUtils.isEmpty(currentNumber)) {
139+
if (currentNumber.length() > count) {
140+
currentNumber.delete(count, currentNumber.length() - 1);
141+
}
142+
for (int i = 0; i < currentNumber.length(); i++) {
143+
canvas.drawText("" + currentNumber.charAt(i),
144+
padding + boxSize * i + (boxSize / 2),
145+
y,
146+
textPaint);
147+
}
148+
}
149+
150+
}
151+
152+
/**
153+
* 绘制边框
154+
*
155+
* @param canvas
156+
*/
157+
private void drawFrame(Canvas canvas) {
158+
RectF oval = new RectF(padding,
159+
padding,
160+
getWidth() - padding,
161+
getHeight() - padding);
162+
canvas.drawRoundRect(oval, 10, 10, boxPaint);
163+
164+
for (int i = 1; i < count; i++) {
165+
canvas.drawLine(padding + boxSize * i,
166+
padding,
167+
padding + boxSize * i,
168+
padding + boxSize,
169+
boxPaint);
170+
}
171+
}
172+
173+
@Override
174+
public boolean onTouchEvent(MotionEvent event) {
175+
showInputMethod();
176+
return super.onTouchEvent(event);
177+
}
178+
179+
@Override
180+
public boolean onKeyDown(int keyCode, KeyEvent event) {
181+
//接收按键事件,67是删除键(backspace),7-16就是0-9
182+
if (keyCode == 67 && currentNumber.length() > 0) {
183+
currentNumber.deleteCharAt(currentNumber.length() - 1);
184+
//重新绘图
185+
invalidate();
186+
} else if (keyCode >= 7 && keyCode <= 16 && currentNumber.length() < count) {
187+
currentNumber.append(keyCode - 7);
188+
invalidate();
189+
}
190+
return super.onKeyDown(keyCode, event);
191+
}
192+
193+
@Override
194+
public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
195+
outAttrs.inputType = InputType.TYPE_CLASS_NUMBER;//定义软键盘样式为数字键盘
196+
return super.onCreateInputConnection(outAttrs);
197+
}
198+
199+
/**
200+
* 获取当前已输入文本
201+
*
202+
* @return
203+
*/
204+
public String getCurrentNumber() {
205+
return currentNumber.toString();
206+
}
207+
208+
/**
209+
* 设置当前显示验证码
210+
*
211+
* @param currentNumber
212+
*/
213+
public void setCurrentNumber(String currentNumber) {
214+
if (!TextUtils.isEmpty(this.currentNumber)) {
215+
this.currentNumber.delete(0, currentNumber.length() - 1);
216+
}
217+
if (!TextUtils.isEmpty(currentNumber)) {
218+
if (currentNumber.length() > count) {
219+
currentNumber.substring(0, count);
220+
}
221+
this.currentNumber.append(currentNumber);
222+
}
223+
post(new Runnable() {
224+
@Override
225+
public void run() {
226+
invalidate();
227+
}
228+
});
229+
}
230+
231+
/**
232+
* 打开输入法
233+
*/
234+
private void showInputMethod() {
235+
postDelayed(new Runnable() {
236+
@Override
237+
public void run() {
238+
inputMethodManager.viewClicked(NumberInputView.this);
239+
inputMethodManager.showSoftInput(NumberInputView.this,
240+
InputMethodManager.SHOW_FORCED);
241+
}
242+
}, 100);
243+
}
244+
245+
/**
246+
* 关闭输入法
247+
*/
248+
private void closeInputMethod() {
249+
post(new Runnable() {
250+
@Override
251+
public void run() {
252+
if (inputMethodManager.isActive()) {
253+
inputMethodManager.hideSoftInputFromInputMethod(NumberInputView.this.getWindowToken(),
254+
0);
255+
}
256+
}
257+
});
258+
}
259+
}

NumberInputView/UiTools.java

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package com.zhangke.window;
2+
3+
import android.content.Context;
4+
5+
/**
6+
* Created by ZhangKe at 2017/3/27
7+
*/
8+
public class UiTools {
9+
/**
10+
* 根据手机的分辨率从 dp 的单位 转成为 px(像素)
11+
*/
12+
public static int dip2px(Context context, float dpValue) {
13+
final float scale = context.getResources().getDisplayMetrics().density;
14+
return (int) (dpValue * scale + 0.5f);
15+
}
16+
17+
/**
18+
* 根据手机的分辨率从 px(像素) 的单位 转成为 dp
19+
*/
20+
public static int px2dip(Context context, float pxValue) {
21+
final float scale = context.getResources().getDisplayMetrics().density;
22+
return (int) (pxValue / scale + 0.5f);
23+
}
24+
25+
/**
26+
* 将sp值转换为px值,保证文字大小不变
27+
*
28+
* @param spValue
29+
* @param spValue
30+
* (DisplayMetrics类中属性scaledDensity)
31+
* @return
32+
*/
33+
public static int sp2px(Context context, float spValue) {
34+
final float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
35+
return (int) (spValue * fontScale + 0.5f);
36+
}
37+
}

NumberInputView/styles.xml

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<resources>
2+
3+
<!-- Base application theme. -->
4+
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
5+
<!-- Customize your theme here. -->
6+
<item name="colorPrimary">@color/colorPrimary</item>
7+
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
8+
<item name="colorAccent">@color/colorAccent</item>
9+
</style>
10+
11+
<declare-styleable name="NumberInputView">
12+
<attr name="box_count" format="integer"/>
13+
</declare-styleable>
14+
</resources>

0 commit comments

Comments
 (0)