Android动态数字输入框
基础view如下:
具体的思路实现:
1:展示textview实现
2: 顶层使用透明的edittext.获取焦点/删除文字等。
public class BaseVerificationCodeView extends RelativeLayout {
private Context mContext;
private OnCodeFinishListener onCodeFinishListener;
//TextView的list
private List<TextView> tvList = new ArrayList<>();
private GoogleEditText editText;
/**
* 输入框数量
*/
private int mEtNumber;
/**
* 输入框类型
*/
private BaseVerificationCodeView.VCInputType mEtInputType;
/**
* 输入框的宽度
*/
private int mEtWidth;
/**
* 输入框的高度
*/
private int mEtHeight;
/**
* 文字颜色
*/
private int mEtTextColor;
/**
* 文字大小
*/
private float mEtTextSize;
/**
* 输入框背景
*/
private int mEtTextBg;
//输入框的间距
private int mEtMargin = 10;
public void setOnCodeFinishListener(OnCodeFinishListener onCodeFinishListener) {
this.onCodeFinishListener = onCodeFinishListener;
}
public int getmEtNumber() {
return mEtNumber;
}
public void setmEtNumber(int mEtNumber) {
this.mEtNumber = mEtNumber;
}
public BaseVerificationCodeView.VCInputType getmEtInputType() {
return mEtInputType;
}
public void setmEtInputType(BaseVerificationCodeView.VCInputType mEtInputType) {
this.mEtInputType = mEtInputType;
}
public int getmEtWidth() {
return mEtWidth;
}
public void setmEtWidth(int mEtWidth) {
this.mEtWidth = mEtWidth;
}
public int getmEtHeight() {
return mEtHeight;
}
public void setmEtHeight(int mEtHeight) {
this.mEtHeight = mEtHeight;
}
public int getmEtTextColor() {
return mEtTextColor;
}
public void setmEtTextColor(int mEtTextColor) {
this.mEtTextColor = mEtTextColor;
}
public float getmEtTextSize() {
return mEtTextSize;
}
public void setmEtTextSize(float mEtTextSize) {
this.mEtTextSize = mEtTextSize;
}
public int getmEtTextBg() {
return mEtTextBg;
}
public void setmEtTextBg(int mEtTextBg) {
this.mEtTextBg = mEtTextBg;
}
public enum VCInputType {
NUMBER,
NUMBERPASSWORD,
TEXT,
TEXTPASSWORD,
}
public BaseVerificationCodeView(Context context) {
this(context, null);
}
public BaseVerificationCodeView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public BaseVerificationCodeView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
this.mContext = context;
@SuppressLint({"Recycle", "CustomViewStyleable"})
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.VerificationCodeView);
mEtNumber = typedArray.getInteger(R.styleable.VerificationCodeView_zwidget_vcv_et_number, 4);
int inputType = typedArray.getInt(R.styleable.VerificationCodeView_zwidget_vcv_et_inputType, VerificationCodeView.VCInputType.NUMBER.ordinal());
mEtInputType = BaseVerificationCodeView.VCInputType.values()[inputType];
mEtWidth = typedArray.getDimensionPixelSize(R.styleable.VerificationCodeView_zwidget_vcv_et_width, 120);
mEtHeight = typedArray.getDimensionPixelSize(R.styleable.VerificationCodeView_zwidget_vcv_et_height, -1);
if (mEtHeight == -1) {
mEtHeight = mEtWidth;
}
mEtTextColor = typedArray.getColor(R.styleable.VerificationCodeView_zwidget_vcv_et_text_color, Color.BLACK);
mEtTextSize = typedArray.getDimensionPixelSize(R.styleable.VerificationCodeView_zwidget_vcv_et_text_size, 16);
mEtTextBg = typedArray.getResourceId(R.styleable.VerificationCodeView_zwidget_vcv_et_bg, R.drawable.zwidget_vcv_et_code_bg);
//释放资源
typedArray.recycle();
initTextView();
initEdit();
}
/**
* 设置TextView
*/
private void initTextView() {
LinearLayout linearLayout = new LinearLayout(mContext);
addView(linearLayout);
LayoutParams llLayoutParams = (LayoutParams) linearLayout.getLayoutParams();
llLayoutParams.width = LayoutParams.MATCH_PARENT;
llLayoutParams.height = LayoutParams.WRAP_CONTENT;
//水平排列
linearLayout.setOrientation(LinearLayout.HORIZONTAL);
//内容居中
linearLayout.setGravity(Gravity.CENTER);
int childHPadding = 14;
for (int i = 0; i < mEtNumber; i++) {
TextView textView = new TextView(mContext);
linearLayout.addView(textView);
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(mEtWidth, mEtHeight);
layoutParams.bottomMargin = childHPadding;
layoutParams.topMargin = childHPadding;
layoutParams.leftMargin = childHPadding;
layoutParams.rightMargin = childHPadding;
layoutParams.gravity = Gravity.CENTER;
textView.setLayoutParams(layoutParams);
textView.setBackgroundResource(mEtTextBg);
textView.setGravity(Gravity.CENTER);
textView.setMaxEms(1);
textView.setMaxLines(1);
textView.setTextSize(mEtTextSize);
textView.setTextColor(mEtTextColor);
switch (mEtInputType) {
case NUMBERPASSWORD:
textView.setInputType(InputType.TYPE_NUMBER_VARIATION_PASSWORD);
break;
case TEXT:
textView.setInputType(InputType.TYPE_CLASS_TEXT);
break;
case TEXTPASSWORD:
textView.setInputType(InputType.TYPE_TEXT_VARIATION_PASSWORD);
break;
default:
textView.setInputType(InputType.TYPE_CLASS_NUMBER);
}
tvList.add(textView);
}
tvSetFocus(0);
}
private void initEdit() {
editText = new GoogleEditText(mContext);
addView(editText);
LayoutParams layoutParams = (LayoutParams) editText.getLayoutParams();
layoutParams.width = layoutParams.MATCH_PARENT;
layoutParams.height = mEtHeight;
editText.setLayoutParams(layoutParams);
//防止横盘小键盘全屏显示
editText.setImeOptions(EditorInfo.IME_FLAG_NO_FULLSCREEN);
//隐藏光标
editText.setCursorVisible(false);
//最大输入长度
editText.setFilters(new InputFilter[]{new InputFilter.LengthFilter(mEtNumber)});
//输入类型为数字
switch (mEtInputType) {
case NUMBERPASSWORD:
editText.setInputType(InputType.TYPE_NUMBER_VARIATION_PASSWORD);
break;
case TEXT:
editText.setInputType(InputType.TYPE_CLASS_TEXT);
break;
case TEXTPASSWORD:
editText.setInputType(InputType.TYPE_TEXT_VARIATION_PASSWORD);
break;
default:
editText.setInputType(InputType.TYPE_CLASS_NUMBER);
}
editText.setTextSize(0);
editText.setBackgroundResource(R.drawable.zwidfet_vcv_et_code_transfer_bg);
editText.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
if (s != null && !TextUtils.isEmpty(s.toString())) {
//如果是最后一位验证码,焦点在最后一个,否者在下一位
if (s.length() == mEtNumber) {
tvSetFocus(mEtNumber - 1);
} else {
tvSetFocus(s.length());
}
//给textView设置数据
for (int i = 0; i < s.length(); i++) {
tvList.get(i).setText(s.toString().substring(i, i + 1));
}
for (int i = s.length(); i < mEtNumber; i++) {
tvList.get(i).setText("");
}
} else {
//一位验证码都没有的情况
tvSetFocus(0);
for (int i = 0; i < mEtNumber; i++) {
tvList.get(i).setText("");
}
}
}
@Override
public void afterTextChanged(Editable s) {
int length = s.length();
if (length == mEtNumber) {
onCodeFinishListener.onComplete(s.toString());
}
}
});
showSystemKeyboard(mContext, editText);
}
private void tvSetFocus(int index) {
tvList.get(index).setClickable(true);
tvList.get(index).setFocusable(true);
tvList.get(index).setBackgroundResource(mEtTextBg);
}
/**
* 显示系统键盘
*
* @param context Context
* @param editText EditText
*/
public static void showSystemKeyboard(Context context, EditText editText) {
editText.requestFocus();
InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
if (imm != null) {
imm.showSoftInput(editText, InputMethodManager.SHOW_FORCED);
}
}
/**
* 隐藏系统键盘
*/
public void hideSystemKeyboard() {
InputMethodManager imm = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
if (imm != null) {
imm.hideSoftInputFromWindow(editText.getWindowToken(), 0);
}
}
/**
* 更新输入框颜色背景及字体大小
*/
public void updateChild() {
int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
View childAt = getChildAt(i);
if (childAt instanceof LinearLayout) {
int childCount1 = ((LinearLayout) childAt).getChildCount();
for (int i1 = 0; i1 < childCount1; i1++) {
View childAt1 = ((LinearLayout) childAt).getChildAt(i1);
if (childAt1 instanceof TextView){
((TextView) childAt1).setTextSize(mEtTextSize);
((TextView) childAt1).setTextColor(mEtTextColor);
childAt1.setBackgroundResource(mEtTextBg);
}
}
}
}
invalidate();
}
/**
* 清空所有输入框内容
*/
public void clearAllText() {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
editText.setText("");
}
}, 100);
}
public interface OnCodeFinishListener {
void onComplete(String content);
}
}
resource如下:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- 自定义验证码输入框-->
<declare-styleable name="VerificationCodeView">
<!--输入框的数量-->
<attr name="zwidget_vcv_et_number" format="integer" />
<!--输入类型-->
<attr name="zwidget_vcv_et_inputType">
<enum name="number" value="0" />
<enum name="numberPassword" value="1" />
<enum name="text" value="2" />
<enum name="textPassword" value="3" />
</attr>
<!--输入框的宽度-->
<attr name="zwidget_vcv_et_width" format="dimension|reference" />
<!--输入框的高度-->
<attr name="zwidget_vcv_et_height" format="dimension|reference" />
<!--输入框文字颜色-->
<attr name="zwidget_vcv_et_text_color" format="color|reference" />
<!--输入框文字大小-->
<attr name="zwidget_vcv_et_text_size" format="dimension|reference" />
<!--输入框背景-->
<attr name="zwidget_vcv_et_bg" format="reference" />
</declare-styleable>
</resources>
遗留问题:
1:无法开启光标,根据光标展示。
2:没有替换背景。
Android动态数字输入框的更多相关文章
- MUI 里js动态添加数字输入框后,增加、减少按钮无效
numbox 的自动初化是在 mui.ready 时完成的mui 页面默认会自动初始化页面中的所有数字输入框,动态构造的 DOM 需要进行手动初始化.比如:您动态创建了一个 ID 为 abc 的数字输 ...
- 动手写个数字输入框1:input[type=number]的遗憾
前言 最近在用Polymer封装纯数字的输入框,开发过程中发现不少坑,也有很多值得研究的地方.本系列打算分4篇来叙述这段可歌可泣的踩坑经历: <动手写个数字输入框1:input[type=nu ...
- 基于Vue的数字输入框组件开发
1.概述 Vue组件开发的API:props.events和slots 2.组件代码 github地址:https://github.com/MengFangui/VueInputNumber 效果: ...
- Android 动态改变高度以及计算长度的EditText
前段时间项目需求,需要做一个有限制长度的输入框并动态显示剩余文字,同时也要动态改变EditText的高度来增加用户体验.现整理出来与大家分享. 先来看看效果图 看了效果就分享一下布局 <Rela ...
- [转载] Android动态加载Dex机制解析
本文转载自: http://blog.csdn.net/wy353208214/article/details/50859422 1.什么是类加载器? 类加载器(class loader)是 Java ...
- [Mobile] 手机浏览器输入框-数字输入框
手机浏览器的输入框,一直都是以web的方式进行开发的,没有关注到用户体验,领导提出了输入框要弹出数字输入框,想来应该有这种技术能实现. 搜索之后发现可以使用type="number&qu ...
- WPF数字输入框和IP地址输入框
数字输入框 简介 在业务中,我们经常需要限制用户的输入,比如限制输入长度,限制只能输入数字等等.限制输入长度WPF内置的TextBox已经帮我们解决了,但是限制输入数字却并未在WPF中内置解决方案.使 ...
- Android 动态加载 (二) 态加载机制 案例二
探秘腾讯Android手机游戏平台之不安装游戏APK直接启动法 重要说明 在实践的过程中大家都会发现资源引用的问题,这里重点声明两点: 1. 资源文件是不能直接inflate的,如果简单的话直接在程序 ...
- Android 动态加载 (一) 态加载机制 案例一
在目前的软硬件环境下,Native App与Web App在用户体验上有着明显的优势,但在实际项目中有些会因为业务的频繁变更而频繁的升级客户端,造成较差的用户体验,而这也恰恰是Web App的优势.本 ...
- android利用数字证书对程序签名
签名的必要性 1. 防止你已安装的应用被恶意的第三方覆盖或替换掉. 2. 开发者的身份标识,签名可以防止抵赖等事件的发生. 开发Android的人这么多,完全有可能大家都把类名,包名起成了一个同 ...
随机推荐
- Storm整合Kafka Java API源码
1.Maven项目的pom.xml源码如下: <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi=&qu ...
- 响应式编程——初识 Flux 和 Mono
by emanjusaka from https://www.emanjusaka.top/archives/4 彼岸花开可奈何 本文欢迎分享与聚合,全文转载请留下原文地址. 前言 Reactor ...
- 20个最佳实践提升Terraform工作流程|Part 1
Terraform 是管理基础设施及代码(IaC)最常用的工具之一,它能使我们安全且可预测地对基础设施应用更改.刚开始上手 Terraform 可能会感觉有些不容易,但很快就能对该工具有基本的了解,随 ...
- Teamcenter RAC 开发之《AbstractRendering》
背景 关于Teamcenter RAC 客制化渲染表单,做一两个有时间做还是可以的,问题是大批量做的时候就会存在很多重复的代码 例如: 1.定义很多 TCProperty,JTextFiled,ite ...
- Spring Boot 目录遍历--表达式注入--代码执行--(CVE-2021-21234)&&(CVE-2022-22963)&&(CVE-2022-22947)&&(CVE-2022-2296)
Spring Boot 目录遍历--表达式注入--代码执行--(CVE-2021-21234)&&(CVE-2022-22963)&&(CVE-2022-22947)& ...
- JAVA实现单链表修改和删除数据节点
JAVA实现单链表修改和删除数据节点 一.修改单链表中的一个节点 ①实现思路 因为带头节点的链表中头节点的next域不能发生改变(始终指向单链表的头节点),否则将找不到该链表.所以我们需要先找一个辅助 ...
- c语言代码练习2(2)
//利用for循环,输出1-10阶乘的和#define _CRT_SECURE_NO_WARNINGS 1 #include <stdio.h> int main( ) { int i = ...
- SpringSecurity-前后端分离教程
1.简介 Spring Security 是 Spring 家族中的一个安全管理框架.相比与另外一个安全框架Shiro,它提供了更丰富的功能,社区资源也比Shiro丰富. 一般来说中大型的项目都是使用 ...
- 将GitBash设置为VS Code的默认终端
这个东西搞了半天,真的无语...网上的东西都太旧了 注意:"terminal.integrated.shell.windows"自2021年4月起已弃用. 1.首先打开设置 2.进 ...
- P8684 [蓝桥杯 2019 省 B] 灵能传输 题解
P8684 [蓝桥杯 2019 省 B] 灵能传输 题解 Part 1 提示 题目传送门 欢迎大家指出错误并私信这个蒟蒻 欢迎大家在下方评论区写出自己的疑问(记得 @ 这个蒟蒻) Part 2 更新日 ...