​ Android 自定义数字键盘(一)​

​ Android 自定义数字键盘(二)随机数字

Demo地址:​​https://github.com/danfengfirst/KeyDemo​

这篇博客是在上面两篇博客的基础上修改的一个相对比较完整的demo,写完前面两篇我尝试使用过用pop弹出界面,但是焦点方面总是有问题,就参考了梁肖的思路,改用了Activity,为了思路清晰,没有给输入框自定义属性,效果演示如下(录的好像有点卡,动画效果跟点击的时候卡了,录制原因,正常运行不卡哈):

Android 自定义数字键盘(三)自定义输入框_android

思路:

主要是三个方面:
1、自定义EidtText输入框,重写onTextChanged()方法来监听文本并进行刷新+圆点绘制
2、注意自定义的EditTextView获取焦点时隐藏键盘,显示自己定义的键盘,还有Editable的使用
3、对自定义键盘的点击事件监听回调,回调中分了两个方法一个插入数据,一个删除数据,通过方法名字应该看得出来。

//对按键的输入与删除事件进行监听
mKeyView.setOnKeyPressListener(new NumKeyView.OnKeyPressListener() {
@Override
public void onInertKey(String text) {
//这里不可以直接使用mEditText来进行append,否则会显示数字
if (editable.length() < 6) {
mPasswordStr.append(text);
editable.append(text);
}
}
@Override
public void onDeleteKey() {
if (editable.length() > 0) {
int length = editable.length();
editable.delete(length - 1, length);
mPasswordStr.delete(length - 1, length);
}
}
});

代码

自定义输入框

代码很少也很容易理解

public class PassWordEdit extends EditText
//控件宽度与高度
private int mWidth;
private int mHeight;
private Paint mPaint;
//输入密码长度
private int mPassWordLength;

public PassWordEdit(Context context) {
this(context, null);
}

public PassWordEdit(Context context, AttributeSet attrs) {
super(context, attrs);
//初始化
mPaint=new Paint();
mPaint.setAntiAlias(true);
mPaint.setColor(getResources().getColor(R.color.deepgray));
mPaint.setStrokeWidth(2);
}

@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//为了绘制矩形边框设置画笔为空心的
mPaint.setStyle(Paint.Style.STROKE);
canvas.drawRect(new RectF(0+mPaint.getStrokeWidth(),0,mWidth-mPaint.getStrokeWidth(),mHeight),mPaint);
mPaint.setStyle(Paint.Style.FILL);
int width=(int)(mWidth/6.0);
//绘制中间竖线
for (int i=1;i<=5;i++){
canvas.drawLine(width*i,0,width*i,mHeight,mPaint);
}
//绘制中间圆点
for (int j=0;j<mPassWordLength;j++){
canvas.drawCircle(width/2+width*j,mHeight/2,5.0f,mPaint);
}
}

@Override
protected void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) {
super.onTextChanged(text, start, lengthBefore, lengthAfter);
//进行监听,文本改变的时候刷新界面
if (text.length()!=mPassWordLength){
mPassWordLength=text.length();
}
invalidate();
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
mWidth = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);
mHeight = getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec);
setMeasuredDimension(mWidth, mHeight);
}
}

Activity调用

注意上面思路中提到的三点就可以

public class KeyDemo extends AppCompatActivity implements View.OnClickListener, View.OnFocusChangeListener
private PassWordEdit mEditText;
private NumKeyView mKeyView;
private Button mButtonEnsure;
private ImageView mImageViewCancle;
private StringBuffer mPasswordStr;

private ToastUtil mToast;

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.keyboard_pop);
init();
}

private void init() {
mEditText = (PassWordEdit) findViewById(R.id.passWordEdit);//自定义密码输入框
mKeyView = (NumKeyView) findViewById(R.id.keyboardview);//自定义键盘
mButtonEnsure = (Button) findViewById(R.id.bt_ensure);//确定按钮
mImageViewCancle = (ImageView) findViewById(R.id.im_cancle);//取消按钮
mEditText.setInputType(InputType.TYPE_NULL);//隐藏键盘
mKeyView.setRandomKeyBoard(true);//设置随机数字键盘
mToast = new ToastUtil(getApplicationContext());
addListener();
mEditText.setTransformationMethod(PasswordTransformationMethod.getInstance());//隐藏文本,不加这行代码会显示输入文本


}

private void addListener() {
mEditText.setOnFocusChangeListener(this);
mButtonEnsure.setOnClickListener(this);
mImageViewCancle.setOnClickListener(this);
mEditText.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
showKeyBoard();
return false;
}
});
final Editable editable = mEditText.getText();
//对按键的输入与删除事件进行监听
mKeyView.setOnKeyPressListener(new NumKeyView.OnKeyPressListener() {
@Override
public void onInertKey(String text) {
//这里不可以直接使用mEditText来进行append,否则会显示数字
if (editable.length() < 6) {
mPasswordStr.append(text);
editable.append(text);
}
}
@Override
public void onDeleteKey() {
if (editable.length() > 0) {
int length = editable.length();
editable.delete(length - 1, length);
mPasswordStr.delete(length - 1, length);
}
}
});
}



@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.bt_ensure:
if (mPasswordStr.length() <= 0) {
mToast.showToastCenter("请输入有效密码");
}
if (mPasswordStr.length() == 6) {
Intent intent = new Intent();
intent.putExtra("data", mPasswordStr.toString());
setResult(RESULT_OK, intent);
finish();
}
break;
case R.id.im_cancle:
finish();
break;
default:
break;
}
}

@Override
public void onFocusChange(View view, boolean hasfocus) {
mPasswordStr = new StringBuffer();
if (hasfocus) {
hideSoftKeyBoard();
showKeyBoard();
} else {
hideKeyBoard();
}
}
public void hideSoftKeyBoard() {
InputMethodManager im = (InputMethodManager) getApplicationContext().getSystemService(INPUT_METHOD_SERVICE);
im.hideSoftInputFromInputMethod(getCurrentFocus().getWindowToken(), InputMethodManager.RESULT_HIDDEN);
}

public void showKeyBoard() {
if (mKeyView != null && (mKeyView.getVisibility() == View.INVISIBLE || mKeyView.getVisibility() == View.GONE)) {
mKeyView.setVisibility(View.VISIBLE);
}
}

public void hideKeyBoard() {
if (mKeyView != null

布局

<?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"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/transparent_half_half_half"
android:gravity="bottom"
android:orientation="vertical">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/white"
android:padding="10dp">

<ImageView
android:id="@+id/im_cancle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:src="@drawable/guanbixiao"

<TextView
android:id="@+id/tv_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginTop="10dp"
android:text="请输入支付密码"
android:textSize="24sp"

<TextView
android:id="@+id/tv_tip"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/tv_title"
android:gravity="center_horizontal"
android:text="您的手机不在常用地区登录,为保障您的资金安全,请输入支付密码"
android:textColor="@color/colorAccent"
android:textSize="22sp"
<包名+PassWordEdit
android:id="@+id/passWordEdit"
android:layout_width="match_parent"
android:layout_height="40dp"
android:layout_marginTop="5dp"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_below="@+id/tv_tip"
android:layout_weight="1"
android:background="#ffffff"
android:maxLength="6"
android:textColor="@color/colorAccent"
<Button
android:id="@+id/bt_ensure"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/passWordEdit"
android:layout_centerHorizontal="true"
android:layout_marginTop="20dp"
android:background="@drawable/btbg"
android:text="确定"

</RelativeLayout>

<包名+NumKeyView
android:id="@+id/keyboardview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:focusable="true"
android:focusableInTouchMode="true"
android:keyBackground="@color/colorAccent"
app:deleteDrawable="@drawable/keyboard_backspace"
app:gbColor="#eeeeee"
</LinearLayout>

其他部分

public class MainActivity extends AppCompatActivity
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void popkeyboard(View view){
Intent intent=new Intent(MainActivity.this,KeyDemo.class);
startActivityForResult(intent,0x11);
overridePendingTransition(R.anim.showanim,R.anim.dismissanim);
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(resultCode==RESULT_OK){
String text=data.getExtras().getString("data");
ToastUtil toastUtil=new

动画(用的之前的)
show

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:fromXDelta="0"
android:fromYDelta="100%"
android:toXDelta="0"
android:toYDelta="0"
android:duration="1000"</translate>

</set>

dismiss

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:toXDelta="0"
android:fromXDelta="0"
android:fromYDelta="0"
android:toYDelta="100%"
android:duration="1000"</translate>
</set>