Android短信验证码组件 Android自定义短信验证码组件
Unknown world 人气:0Android自定义短信验证码组件,供大家参考,具体内容如下
效果图
1.布局实现
因为要禁用光标,所以我用TextView代替了EditText,每一行显示的验证码个数由用户决定,所以我这里用线性布局的权重,对TextView进行控制宽度等分,然后设置选中和未选中当前TextView的底部边框,设置高亮颜色背景
2.接受用户输入
我这里使用了TextView,但是怎么接受用户输入的值呢。这里我直接继承了RelativeLayout,然后添加了一个透明的EditText,覆盖在这几个TextView上面,用户就可以点击唤起键盘输入
3.TextView如何显示值和删除值
我这里设置EditText的TextColor和BackgroundColor为Color.TRANSPARENT 透明,然后监听EditText的addTextChangedListener事件和setOnKeyListener按键删除事件,然后把值添加到TextView上,就能实现了,然后在写一个对外的接口。获取到输入的验证码。
4.添加闪烁的动画
我这里使用了ObjectAnimator,初始化给每个TextView添加动画,然后在输入的时候给当前的TextView启动动画,取消其他TextView动画
具体源码如下:
/** * @author wu_ming_zhi_bei * @date 2021/1/27 15:00 * @Notes */ public class VerificationCodeView extends RelativeLayout { private Context mContext; private RelativeLayout.LayoutParams layoutParams; private int num = 4;//验证码数量 private int codeSize;//字体大小 private int codeColor;//字体颜色 private List<TextView> tvs = new ArrayList<>(); private List<String> codes = new ArrayList<>(); private EditText etCode; private InputMethodManager imm; List<ObjectAnimator> animators = new ArrayList<>(); public VerificationCodeView(Context context) { this(context,null); } public VerificationCodeView(Context context, AttributeSet attrs) { this(context,attrs,0); } public VerificationCodeView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(context,attrs); } private void init(Context context, AttributeSet attrs) { this.mContext = context; imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE); TypedArray a = mContext.obtainStyledAttributes(attrs, R.styleable.VerificationCodeView); num = a.getInteger(R.styleable.VerificationCodeView_num,4); codeSize = a.getDimensionPixelSize(R.styleable.VerificationCodeView_codeSize,18); codeColor = a.getColor(R.styleable.VerificationCodeView_codeColor,getResources().getColor(R.color.theme_color)); //初始化一个大的LinearLayout来存放验证码 LinearLayout codeBox = new LinearLayout(mContext); codeBox.setOrientation(LinearLayout.HORIZONTAL); codeBox.setGravity(Gravity.CENTER); //添加方块 for(int i=0;i<num;i++){ TextView tv = new TextView(mContext); tv.setTextSize(codeSize); tv.setTextColor(codeColor); tv.setGravity(Gravity.CENTER); tv.setPadding(0,0,0,10); LinearLayout.LayoutParams param = new LinearLayout.LayoutParams( LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT, 1); param.gravity = Gravity.CENTER; param.rightMargin = 20; param.leftMargin = 20; param.topMargin = 20; param.bottomMargin = 20; tv.setLayoutParams(param); //默认第一个选中 if(i==0){ tv.setText("|"); tv.setBackground(mContext.getResources().getDrawable(R.drawable.code_border_current_bottom)); }else{ tv.setBackground(mContext.getResources().getDrawable(R.drawable.code_border_bottom)); } codeBox.addView(tv); tvs.add(tv);//添加到数组 } layoutParams = new RelativeLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT); //添加codebox的位置在组件的最上面 layoutParams.addRule(RelativeLayout.ALIGN_PARENT_TOP,TRUE); layoutParams.setMargins(60,0,60,0); codeBox.setLayoutParams(layoutParams); //添加Edit etCode = new EditText(mContext); etCode.setLayoutParams(layoutParams); etCode.setLines(1); etCode.setMaxLines(1); etCode.setTextColor(Color.TRANSPARENT); etCode.setBackgroundColor(Color.TRANSPARENT); etCode.setCursorVisible(false); //添加edit监听 etCode.addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) { } @Override public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) { } @Override public void afterTextChanged(Editable editable) { if(editable != null && editable.length()>0) { etCode.setText("");//清空数据 if(codes.size() < num){ codes.add(editable.toString()); showCode(); } } } }); // 监听验证码删除按键 etCode.setOnKeyListener(new View.OnKeyListener() { @Override public boolean onKey(View view, int keyCode, KeyEvent keyEvent) { if (keyCode == KeyEvent.KEYCODE_DEL && keyEvent.getAction() == KeyEvent.ACTION_DOWN && codes.size()>0) { codes.remove(codes.size()-1); showCode(); return true; } return false; } }); addView(codeBox); addView(etCode); addAnimation();//添加东安湖 setTwinkle();//开启动画 } //显示验证码 private void showCode(){ int size = codes.size();//1 6 for(int i=0;i<num;i++){ if(size>i){ tvs.get(i).setText(codes.get(i));//添加到textview }else if(size==i){ tvs.get(i).setText("|"); }else{ tvs.get(i).setText(""); } } etCode.setFocusable(true); etCode.requestFocus(); etCode.setFocusableInTouchMode(true); etCode.requestFocusFromTouch(); setTwinkle();//动画 callBack();//回调 } private void showColor(){ int size = codes.size(); if(size==0){ tvs.get(0).setBackground(mContext.getResources().getDrawable(R.drawable.code_border_current_bottom)); }else{ for(int i=0;i<tvs.size();i++){ if(i==size-1){ tvs.get(i).setBackground(mContext.getResources().getDrawable(R.drawable.code_border_current_bottom)); }else{ tvs.get(i).setBackground(mContext.getResources().getDrawable(R.drawable.code_border_bottom)); } } } } /** * 回调 */ private void callBack(){ if(onInputListener==null){ return; } if(codes.size()==num){ onInputListener.onSucess(getPhoneCode()); }else{ onInputListener.onInput(); } } //定义回调 public interface OnInputListener{ void onSucess(String code); void onInput(); } private OnInputListener onInputListener; public void setOnInputListener(OnInputListener onInputListener){ this.onInputListener = onInputListener; } /** * 获得手机号验证码 * @return 验证码 */ public String getPhoneCode(){ StringBuilder sb = new StringBuilder(); for (String code : codes) { sb.append(code); } return sb.toString(); } /** * 显示键盘 */ public void showSoftInput(){ //显示软键盘 if(imm!=null && etCode!=null) { etCode.postDelayed(new Runnable() { @Override public void run() { imm.showSoftInput(etCode, 0); } },200); } } /** * 隐藏键盘 */ public void hideSoftInput(){ //显示软键盘 if(imm!=null && etCode!=null) { etCode.postDelayed(new Runnable() { @Override public void run() { imm.hideSoftInputFromWindow(etCode.getWindowToken(), 0); } },200); } } /** * 添加动画 */ private void addAnimation(){ for(int i=0;i<tvs.size();i++){ ObjectAnimator animator = ObjectAnimator.ofInt(tvs.get(i), "TextColor", 0x00000000, 0xfff00000); animator.setDuration(10000); final int index = i; animator.addListener(new Animator.AnimatorListener() { @Override public void onAnimationStart(Animator animator) { } @Override public void onAnimationEnd(Animator animator) { } @Override public void onAnimationCancel(Animator animator) { tvs.get(index).setTextColor(codeColor); } @Override public void onAnimationRepeat(Animator animator) { } }); animator.setInterpolator(new LinearInterpolator()); animator.setRepeatCount(Animation.INFINITE); animators.add(animator); } } /** * 开启动画 */ private void setTwinkle(){ int size = codes.size(); for(int i=0;i<tvs.size();i++){ if(i==size){ animators.get(i).start(); tvs.get(i).setBackground(mContext.getResources().getDrawable(R.drawable.code_border_current_bottom)); }else{ animators.get(i).cancel(); tvs.get(i).setBackground(mContext.getResources().getDrawable(R.drawable.code_border_bottom)); } } } @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); for(int i=0;i<tvs.size();i++){ animators.get(i).cancel(); } } }
加载全部内容