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的人这么多,完全有可能大家都把类名,包名起成了一个同 ...
随机推荐
- pygame 入门实例教程 1 - 复古方块赛车游戏
作者自我介绍:大爽歌, b站小UP主 ,直播编程+红警三 ,python1对1辅导老师 . 本教程步骤明确,过程清晰简明,最终代码量250行上下,适合学习pygame的新手. 项目代码已上传到我的gi ...
- 记录一个令人崩溃的tomcat闪退问题
tomcat启动时要加载server.xml文件,xml文件中的注释符要一一对应不能多不能少. 比如 这就是错的 只有这样 才是对的 呜呜呜~~~
- 【krpano】 ASP浏览量插件
简述 这是一个Asp版krpano统计访问量案例,运用asp代码控制增值来实现的功能:现将案例上传网站供大家学习研究,希望对大家有所帮助. 功能 用户进入网页增值或刷新增值. 案例展示 所有文件如下图 ...
- 「codeforces - 1481F」AB Tree
link. 理一下逻辑,主要讲一下我做题时的疑惑和其它题解没提到的细节. 首先容易看到,一个必然不劣的贪心策略是把尽量靠近根的层铺成同样的字符.也许会有疑惑,字符串是否本质不同的判定每个位置地位相等. ...
- VScodeSSH免密登录服务器
参考:配置vscode 远程开发+ 免密登录 背景 我想要让VScode实现SSH免密登录服务器,那么就需要使用ssh keygen 生成的公私钥对,公钥id_rsa.pub放在服务器上,私钥id_r ...
- c语言代码练习--函数
函数: 一,概念: 1,在计算科学中,子程序(英语:Subroutione,procedure,function,rotine,method.subprogram,callable unit),是一个 ...
- 02-RAID技术 学习心得
RAID 术语 扇区:是磁盘中最小的存储单元,向磁盘读写数据时是以扇区为最小单元进行存储 block:block,是由N个扇区组成一个块: 在磁盘相同偏移处横向逻辑分割,就形成了stripee: 一个 ...
- 初识FreeRTOS
FreeRTOS是一个迷你的实时操作系统内核.作为一个轻量级的操作系统,功能包括:任务管理.时间管理.信号量.消息队列.内存管理.记录功能.软件定时器.协程等,可基本满足较小系统的需要. 一.Fr ...
- xtrabackup 2.4 的介绍与使用
抄袭转载的太多,请认准原文链接:xtrabackup的介绍与使用 前言 在网上找到教程都是复制粘贴抄袭的,而且还是陈旧资料,不得不说,当前中文互联网环境真是每况愈下. 如果你在网上找 xtraback ...
- List集合异常:list All elements are null
查询数据库,返回空数据,但是List中显示有一个数据,点开以后显示 All elements are null ObjectUtils.isEmpty 和 List.isEmpty判断都失败,后续会 ...