效果图
源码
可设置自定义键盘布局;
可拦截并自定义按键响应(固定功能按键不可更改);
可设置按键位置随机(仅随机字母和数字)
密码输入框可设置显示与不显示密码
/**
* 创建者:TomCat0916
* 创建时间:2020/4/25
* 功能描述:
* 1、重载样式{@link R.style#PassWordEditText}和{@link R.style#RandomKeyboardDialog}可自定义布局中密码框和软键盘样式
* 2、设置{@link #xml}自定义软键盘布局,通过{@link Builder#setCustomKeyDealListener(OnCustomKeyDealListener)}监听配置自定义键盘操作(出固定功能键shift/delete/enter)
* 3、不改变固有控件id情况下重载{@link R.layout#dialog_keyboard},可实现布局自定义
* 示例
* <p>
* RandomKeyboardDialog.builder()
* .isUseStateView(true)
* .setOnInputCompletedListener((value, callback) -> {
* new Handler().postDelayed(() -> callback.onCheckedResult(true), 3000);
* })
* .create(context)
* .show();
* </p>
*/
public class RandomKeyboardDialog extends BaseDialog implements View.OnClickListener, OnInputCompletedListener, OnCheckResultCallback {
private StateView stateView;
private PasswordEditText etInput;
private RandomKeyboard randomKeyboard;
private OnInputCompletedListener listener;
private OnCustomKeyDealListener keyDealListener;
private @XmlRes
int xml = 0;
private String title;
private int passwordLength;
private boolean isVisible;
private boolean isUseStateView;
@Override
public void destroy() {
if (randomKeyboard!=null){
randomKeyboard.onDestroy();
randomKeyboard = null;
}
etInput = null;
listener = null;
stateView = null;
keyDealListener = null;
super.destroy();
}
private RandomKeyboardDialog(@NonNull Context context, Builder builder) {
super(context, builder);
isUseStateView = builder.isUseStateView;
title = builder.title;
if (builder.listener != null) {
listener = builder.listener;
}
keyDealListener = builder.keyDealListener;
xml = builder.xml;
passwordLength = builder.passwordLength;
isVisible = builder.isVisible;
}
@Override
public void initView(View inflate) {
//禁用系统输入法
if (getWindow() != null) {
getWindow().addFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
}
ImageView imgDismiss = findViewById(R.id.img_dismiss);
randomKeyboard = findViewById(R.id.random_keyboard);
TextView tvTitle = findViewById(R.id.tv_title);
if (tvTitle != null) {
tvTitle.setText(title);
}
etInput = findViewById(R.id.et_input);
stateView = findViewById(R.id.state_view);
if (randomKeyboard != null && etInput != null) {
etInput.setOnClickListener(this);
etInput.requestFocus();
etInput.setOnInputCompletedListener(this);
etInput.setSelection(etInput.length());
if (passwordLength > 0) {
etInput.setPasswordLength(passwordLength);
}
etInput.setPasswordVisible(isVisible);
try {
context.getResources().getXml(xml);
randomKeyboard.setCustomKeyboard(xml);
} catch (Resources.NotFoundException e) {
e.printStackTrace();
}
randomKeyboard.setOnCustomKeyDealListener(keyDealListener);
randomKeyboard.bindEditText(etInput);
randomKeyboard.isRandom(true);
randomKeyboard.show();
}
if (imgDismiss != null) {
imgDismiss.setOnClickListener(this);
}
}
@Override
public void initData() {
}
public static Builder builder() {
return new Builder();
}
public static class Builder extends BaseDialog.Builder {
private String title;
private OnInputCompletedListener listener;
private boolean isUseStateView = false;
private @XmlRes
int xml = 0;
private OnCustomKeyDealListener keyDealListener;
private int passwordLength;
private boolean isVisible = true;
@Override
public void destroy() {
listener = null;
keyDealListener = null;
}
public Builder setTitle(String title) {
this.title = title;
return this;
}
public Builder setOnInputCompletedListener(OnInputCompletedListener listener) {
this.listener = listener;
return this;
}
public Builder isUseStateView(boolean isUseStateView) {
this.isUseStateView = isUseStateView;
return this;
}
public Builder setKeyboardLayout(@XmlRes int xml) {
this.xml = xml;
return this;
}
public Builder setCustomKeyDealListener(OnCustomKeyDealListener keyDealListener) {
this.keyDealListener = keyDealListener;
return this;
}
public Builder setPasswordLength(int passwordLength) {
this.passwordLength = passwordLength;
return this;
}
public Builder setPasswordVisible(boolean isVisible) {
this.isVisible = isVisible;
return this;
}
public RandomKeyboardDialog create(Context context) {
setGravity(Gravity.BOTTOM);
setHeight(WindowManager.LayoutParams.MATCH_PARENT);
setWith(WindowManager.LayoutParams.MATCH_PARENT);
setLayoutResId(R.layout.dialog_keyboard);
return new RandomKeyboardDialog(context, this);
}
}
public void setOnInputCompletedListener(OnInputCompletedListener listener) {
this.listener = listener;
}
@Override
public void onClick(View v) {
int id = v.getId();
if (id == R.id.et_input) {
etInput.requestFocus();
etInput.setSelection(etInput.length());
randomKeyboard.show();
} else if (id == R.id.img_dismiss) {
dismiss();
}
}
@Override
public void onComplete(String value, OnCheckResultCallback callback) {
if (listener != null) {
if (isUseStateView && stateView != null) {
stateView.show(StateView.STATE_LOADING);
}
listener.onComplete(value, this);
}
}
@Override
public void onCheckedResult(boolean isDeal) {
if (isUseStateView && stateView != null) {
stateView.hide();
}
if (isDeal) {
dismiss();
}
}
}
其他
- dialog_keyboard.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#33000000">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:background="@color/white"
android:orientation="vertical">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/img_dismiss"
android:layout_width="55dp"
android:layout_height="55dp"
android:paddingTop="10dp"
android:paddingBottom="5dp"
android:paddingLeft="15dp"
android:src="@android:drawable/ic_delete" />
<TextView
android:id="@+id/tv_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:textColor="@color/black"
android:textSize="20sp"
android:textStyle="bold" />
</FrameLayout>
<View
android:layout_width="match_parent"
android:layout_height="1px"
android:background="@color/colorDivider" />
<com.quanyou.libraryview.widget.PasswordEditText
android:id="@+id/et_input"
style="@style/PassWordEditText"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<View
android:layout_width="match_parent"
android:layout_height="1px"
android:background="@color/colorDivider" />
</LinearLayout>
</FrameLayout>
<com.quanyou.libraryview.widget.RandomKeyboard
android:id="@+id/random_keyboard"
style="@style/RandomKeyboardDialog"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom" />
</LinearLayout>
<com.quanyou.baselibrary.widget.StateView
android:id="@+id/state_view"
android:layout_width="match_parent"
android:visibility="gone"
android:layout_height="match_parent" />
</FrameLayout>
- styles.xml
<style name="RandomKeyboardDialog" parent="RandomKeyboardParent">
<item name="android:background">@color/white</item>
<item name="android:keyBackground">@drawable/bg_keyboard_dialog</item>
<item name="android:keyTextColor">@color/black</item>
<item name="android:keyboardLayout">@xml/number_keyboard_dialog_layout</item>
<item name="android:paddingBottom">10dp</item>
</style>
<style name="PassWordEditText">
<item name="android:maxLength">6</item>
<item name="android:background">@android:color/transparent</item>
<item name="borderRadius">5dp</item>
<item name="borderWidth">1dp</item>
<item name="borderSpace">5dp</item>
<item name="android:padding">15dp</item>
<item name="android:layout_marginTop">20dp</item>
<item name="android:layout_marginBottom">20dp</item>
<item name="android:layout_marginLeft">30dp</item>
<item name="android:layout_marginRight">30dp</item>
</style>
- number_keyboard_dialog_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
android:horizontalGap="0.25%p"
android:keyWidth="33%p"
android:keyHeight="50dp">
<Row>
<Key android:keyLabel="1" />
<Key android:keyLabel="2" />
<Key android:keyLabel="3" />
</Row>
<Row>
<Key android:keyLabel="4" />
<Key android:keyLabel="5" />
<Key android:keyLabel="6" />
</Row>
<Row>
<Key android:keyLabel="7" />
<Key android:keyLabel="8" />
<Key android:keyLabel="9" />
</Row>
<Row android:rowEdgeFlags="bottom">
<Key
android:codes="48"
android:horizontalGap="33.25%p"
android:keyLabel="0" />
<Key
android:codes="-5"
android:isModifier="true"
android:isRepeatable="true"
android:keyEdgeFlags="right"
android:keyLabel="delete" />
</Row>
</Keyboard>
相关链接
BaseDialog :https://blog.csdn.net/TomCat0916/article/details/105769678
RandomKeyboard:https://blog.csdn.net/TomCat0916/article/details/105751838
PasswordEditText :https://blog.csdn.net/TomCat0916/article/details/105759569