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的人这么多,完全有可能大家都把类名,包名起成了一个同 ...
随机推荐
- 入门篇-其之二-Java基础知识
目录 对第一个Java程序的思考 外层结构--类 内层结构--main方法 输出语句 注释 单行注释 多行注释 文档注释 文档注释常用标签 使用javadoc命令生成网页风格的文档 阿里巴巴Java开 ...
- 【krpano】 ASP说一说插件
简述 这是一个Asp版krpano说一说案例,运用asp+jquery读写存储入xml文件数据库,结合krpano代码实现的功能:现将案例上传网站供大家学习研究,希望对大家有所帮助. 功能 用户可在网 ...
- 从DevOps实践落地的角度谈谈“流程”和“规范"的反模式
最近在经历的一些事情,让我突发灵感,觉得要写点关于DevOps体系建设过程中的"流程规范",记录下来. 如何解读"流程规范" 谈到DevOps落地,无一例外都会 ...
- Aho-Corasick 算法 AC自动机实现
敏感词过滤在社区发帖.网站检索.短信发送等场景下是很常见的需求,尤其是在高并发场景下如何实现敏感词过滤,都对过滤算法提出了更高的性能要求,Ahocorasick算法能够实现毫秒级的万字过滤匹配,能够很 ...
- Oracle-降低表的高水位线
在应用中存在一系列的表,对表的操作是批量插入又批量删除,最终导致表的水位线很高.高水位线影响全索引扫描的SQL.即影响系统的性能. 现有方法降低表的水位线: 1.降低表的高水位线 select 'al ...
- 【最佳实践】MongoDB导入数据时重建索引
MongoDB一个广为诟病的问题是,大量数据resotore时索引重建非常缓慢,实测5000万的集合如果有3个以上的索引需要恢复,几乎没法成功,而且resotore时如果选择创建索引也会存在索引不生效 ...
- CSP2021游记
题外话 中午十二点半到了考场.没到时间不让进,恰巧发现 lhm 在对面饭店于是去讨论了一下上午 J 组的题,复习了线段树板子( 等到进考场坐好的时候已经两点半了,看考号本来以为我们同机房三个同学会坐一 ...
- 特殊符号传到后端发生变异 & "<>
业务遇到bug,前端传回数据 & ,到后台接收到的数据就是 & 后台接收到的数据就携带了amp;的后缀 网上查找原因,大部分说法是前端传回的数据导致,但是实际并不是,这里是框架的正则过 ...
- animate.css 动画种类(详细)
作者:WangMin 格言:努力做好自己喜欢的每一件事 以下为各种动画类型包含的不同动画效果类,仅供参考.具体可查看animate.css 官网. bounce 弹跳 2. flash 闪烁 3. p ...
- GitHub 官方开源的字体集「GitHub 热点速览」
前几天 GitHub 官方一口气开源了 5 款字体,各有特色,彼此兼容,重要的是代码友好.这不,一开源就获得了 4.5k+ 的 star. 本周除了这个热点之外,当属 OpenAI 又有新动态了,你可 ...