Android中怎么自定义一个验证码输入框
创始人
2024-12-24 20:04:38
0次

xml布局:

                                                                                                                                                                class CustomSmsCodeInputLayout : RelativeLayout, View.OnClickListener {  /**  * 枚举中有两种状态,FOUR四个输入框,SIX6个输入框  */ enum class InputLineNum(var num: Int){  FOUR(4), SIX(6) }  override fun onClick(v: View?) {  when(v?.id){   R.id.tv_get_sms_code->{    clearAllInputValues()    if (onClickSmsCodeTvListener != null) {     onClickSmsCodeTvListener?.onClick(tv_get_sms_code)    }   }  } }  /*启动计时器*/ fun startCountDownTimer() {  cancelCountDownTimer()  /*倒计时60秒,每次执行间隔1秒*/  mCountDownTimerUtil = CountDownTimerUtil(mContext, tv_get_sms_code, 60000, 1000)  mCountDownTimerUtil?.start() }  /*上下文*/ private var mContext: Context /*存放验证码集合*/ var codes: ArrayList? = ArrayList() /*输入相关管理器*/ private var imm: InputMethodManager? = null  private var color_default = Color.parseColor("#999999") private var color_focus = Color.parseColor("#FF9200") private var color_centerLine = Color.parseColor("#FF9200")  /*是否显示中间竖线*/ private var isVisibleCenterLine = true  private var defaultInputNum = InputLineNum.SIX  private var mCountDownTimerUtil: CountDownTimerUtil? = null  constructor(context: Context) : super(context){  mContext = context  initView() }  constructor(context: Context, attrs: AttributeSet) : super(context, attrs){  mContext = context  initView() }  private fun initView() {  imm = mContext.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager?  LayoutInflater.from(mContext).inflate(R.layout.view_sms_code_input_layout, this)  initEvent() }  private fun initEvent() {  //验证码输入  et_code.addTextChangedListener(object : TextWatcher {   override fun beforeTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {}   override fun onTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {}   override fun afterTextChanged(editable: Editable?) {    if (editable != null && editable.trim().isNotEmpty()) {     // 每输入     et_code.setText("")     when(defaultInputNum){      InputLineNum.FOUR -> {       regexMaxInputSize(editable, InputLineNum.FOUR.num)      }      InputLineNum.SIX -> {       regexMaxInputSize(editable, InputLineNum.SIX.num)      }     }     }   }  })  // 监听验证码删除按键  et_code.setOnKeyListener(object : View.OnKeyListener {   override fun onKey(view: View, keyCode: Int, keyEvent: KeyEvent): Boolean {    if (keyCode == KeyEvent.KEYCODE_DEL && keyEvent.action == KeyEvent.ACTION_DOWN && codes?.size!! > 0) {     codes!!.removeAt(codes?.size!! - 1)     //回退的时候如果顶部的提示语显示则隐藏掉     if (tv_view_top_tip.visibility == View.VISIBLE){      tv_view_top_tip.visibility = View.INVISIBLE     }     showCode()     return true    }    return false   }  })  tv_get_sms_code.setOnClickListener(this) }  /*控制可输入的最大长度*/ private fun regexMaxInputSize(editable: Editable, maxSize: Int) {  if (codes?.size!! < maxSize) {   // 过滤掉由空格键引起的字符串出现空长串的问题,使用正则替换规则(\\s*)可以替换掉绝大多数空白字符或空格   codes?.add(editable.toString().replace(Regex("\\s*"), ""))   showCode()  } }  /**  * 显示输入的验证码  */ private fun showCode() {  var code1: String? = ""  var code2: String? = ""  var code3: String? = ""  var code4: String? = ""  var code5: String? = ""  var code6: String? = ""  if (codes?.size!! >= 1) {   code1 = codes?.get(0)  }  if (codes?.size!! >= 2) {   code2 = codes?.get(1)  }  if (codes?.size!! >= 3) {   code3 = codes?.get(2)  }  if (codes?.size!! >= 4) {   code4 = codes?.get(3)  }  if (codes?.size!! >= 5) {   code5 = codes?.get(4)  }  if (codes?.size!! >= 6) {   code6 = codes?.get(5)  }  tv_code1.text = code1  tv_code2.text = code2  tv_code3.text = code3  tv_code4.text = code4  tv_code5.text = code5  tv_code6.text = code6   setColor()//设置高亮颜色  callBack()//回调 }  /**  * 设置高亮颜色  */ private fun setColor() {  v1.setBackgroundColor(color_default)  v2.setBackgroundColor(color_default)  v3.setBackgroundColor(color_default)  v4.setBackgroundColor(color_default)  v5.setBackgroundColor(color_default)  v6.setBackgroundColor(color_default)  if (codes?.size == 0) {   v1.setBackgroundColor(color_focus)   updateCenterLineColor(v1_center_line)  }  if (codes?.size == 1) {   v2.setBackgroundColor(color_focus)   updateCenterLineColor(v2_center_line)  }  if (codes?.size == 2) {   v3.setBackgroundColor(color_focus)   updateCenterLineColor(v3_center_line)  }  if (codes?.size!! == 3) {   v4.setBackgroundColor(color_focus)   updateCenterLineColor(v4_center_line)  }  if (codes?.size == 4) {   v5.setBackgroundColor(color_focus)   updateCenterLineColor(v5_center_line)  }  if (codes?.size!! == 5) {   v6.setBackgroundColor(color_focus)   updateCenterLineColor(v6_center_line)  }  if ((defaultInputNum == InputLineNum.FOUR && codes?.size!! >= 4)   || (defaultInputNum == InputLineNum.SIX && codes?.size!! >= 6)) {   invisibleAllCenterLine()  } }  /**  * 回调  */ private fun callBack() {  if (onInputListener == null) {   return  }  if ((defaultInputNum == InputLineNum.FOUR && codes?.size == 4)   ||(defaultInputNum == InputLineNum.SIX && codes?.size == 6)) {   /*zi自动收起软键盘*/   dismissSoftInput()   onInputListener!!.onSuccess(getPhoneCode())  } else {   onInputListener!!.onInput()  } }  //定义回调 interface OnInputListener {  fun onSuccess(code: String)  fun onInput() }  /**  * 显示键盘  */ fun showSoftInput() {  //显示软键盘  if (imm != null && et_code != null) {   et_code.requestFocus() //需先获得焦点才能主动弹出软键盘   et_code.postDelayed({ imm?.showSoftInput(et_code, InputMethodManager.SHOW_FORCED) }, 200)  } }  /**  * 英藏键盘  */ fun dismissSoftInput() {  et_code.requestFocus()  //某些情况下必须延迟一定时间在执行,不然英藏不了  et_code.postDelayed({ imm?.hideSoftInputFromWindow(et_code.windowToken, 0) }, 200) //强制隐藏键盘 }  /**  * 获得手机号验证码  * @return 验证码  */ fun getPhoneCode(): String {  val sb = StringBuilder()  return if (!codes!!.isEmpty()) {   for (code in codes!!) {    sb.append(code)   }   sb.toString()  }else{   ""  } }  /*更新竖线显示以及颜色*/ private fun updateCenterLineColor(view: View){  if (isVisibleCenterLine) {   invisibleAllCenterLine()   view.visibility = View.VISIBLE  } }  /*英藏所有竖线*/ private fun invisibleAllCenterLine() {  v1_center_line.visibility = View.INVISIBLE  v2_center_line.visibility = View.INVISIBLE  v3_center_line.visibility = View.INVISIBLE  v4_center_line.visibility = View.INVISIBLE  v5_center_line.visibility = View.INVISIBLE  v6_center_line.visibility = View.INVISIBLE }  /*设置顶部提示是否显示*/ fun setTopTipVisible(isVisible: Boolean){  tv_view_top_tip.visibility = if(isVisible) View.VISIBLE else View.INVISIBLE }  /*设置当前项中间竖线是否显示*/ fun setCurrentCenterLineVisible(isVisible: Boolean){  isVisibleCenterLine = isVisible  //显示竖线的话默认显示出第一条  v1_center_line.visibility = if(isVisibleCenterLine) View.VISIBLE else View.INVISIBLE }  /*设置底部获取短信按钮是否显示*/ fun setBottomSmsTvVisible(isVisible: Boolean){  tv_get_sms_code.visibility = if(isVisible) View.VISIBLE else View.GONE }  /*设置顶部提示字样*/ fun setTopTipText(text: String){  tv_view_top_tip.text = text }  /*设置顶部提示字样颜色*/ fun setTopTipTextColor(textColor: Int){  tv_view_top_tip.setTextColor(textColor) }  /*设置当前指定项下环线颜色*/ fun setCurrentIndexLineColor(underlineColor: Int){  color_focus = underlineColor  v1.setBackgroundColor(color_focus) }  /*设置当前指定项的中间线颜色*/ fun setCenterLineColor(centerLineColor: Int){  color_centerLine = centerLineColor  v1_center_line.setBackgroundColor(color_centerLine) }  /*设置不是当前指定项下划线颜色*/ fun setAnotherIndexLineColor(underlineColor: Int){  color_default = underlineColor }  /*设置顶部提示的字样和颜色*/ fun setTopTextAndColor(text: String, textColor: Int){  tv_view_top_tip.text = text  tv_view_top_tip.setTextColor(textColor) }  /*允许的输入类型*/ fun setInputType(type: Int) {  et_code?.inputType = type }  /*更新获取短信按钮状态*/ fun updateGetSmsTvEnable(isEnable: Boolean){  tv_get_sms_code.isEnabled = isEnable  tv_get_sms_code.setTextColor(mContext.resources.getColor(R.color.global_text_color_6c)) }  /*需要展示的输入框数量*/ fun setShowInputNum(num: InputLineNum){  defaultInputNum = num  when(defaultInputNum){   InputLineNum.FOUR -> {    ll5_parent.visibility = View.GONE    ll6_parent.visibility = View.GONE   }   InputLineNum.SIX -> {    ll5_parent.visibility = View.VISIBLE    ll6_parent.visibility = View.VISIBLE   }  } }  /*关闭清除计时器*/ fun cancelCountDownTimer(){  if (mCountDownTimerUtil != null){   mCountDownTimerUtil?.cancel()   mCountDownTimerUtil = null  } }  /**清除所有输入的值*/ fun clearAllInputValues(){  setTopTipVisible(false)  codes?.clear()  showCode() }  /**  * 获取到验证码进行弹窗显示  */ fun showSmsCodeDialogTip(msg: String, title: String){  val msgSplit = msg.toList()  DialogCreator.createTitleDialog(   mContext as Activity,   title,   msg,   DialogViewInfo("知道了"){ _,_ ->    codes?.clear()    msgSplit.forEach { item -> codes?.add(item.toString()) }    showCode()   }  ).subscribe() }  /**  * 验证出错时抖动输入框提示  */ fun startShakeTip(){  val animX = ObjectAnimator.ofFloat(this, "translationX", 0F, 5F, -10F, 0F)  val animY = ObjectAnimator.ofFloat(this, "translationY", 0F, 5F, -10F, 0F)  val animatorSet = AnimatorSet()  animatorSet.playTogether(animX, animY) // 同时执行x、y轴的动画  animatorSet.interpolator = CycleInterpolator(2F)// 执行2次  animatorSet.duration = 500 // 1秒后结束  animatorSet.doOnEnd {   clearAllInputValues()   animatorSet.cancel()  }  animatorSet.start() }  /*输入框监听回调《供外部调用》*/ private var onInputListener: OnInputListener? = null fun setOnInputListener(onInputListener: OnInputListener) {  this.onInputListener = onInputListener }  /*获取验证码点击回调《供外部调用》*/ private var onClickSmsCodeTvListener: OnClickListener? = null fun setOnClickSmsCodeTvListener(onClickSmsCodeTvListener: OnClickListener){  this.onClickSmsCodeTvListener = onClickSmsCodeTvListener } }

主要有两种显示样式,在枚举中定义了4个输入框6个输入框

基本调用代码如下:

//ll_sms_input就是CustomSmsCodeInputLayoutll_sms_input.run {//里边的配置可以自行选择配置   setTopTipVisible(false)   setCurrentCenterLineVisible(true)   setBottomSmsTvVisible(true)   setShowInputNum(CustomSmsCodeInputLayout.InputLineNum.SIX)//这里加载的是六个输入框   setCurrentIndexLineColor(resources.getColor(R.color.global_text_color_grey))   //设置输入类型只能是数字   setInputType(InputType.TYPE_CLASS_NUMBER or InputType.TYPE_NUMBER_FLAG_SIGNED)   showSoftInput()  }ll_sms_input.setOnInputListener()//做输入完成后的监听ll_sms_input.setOnClickSmsCodeTvListener()//点击重新获取按钮的监听

相关内容

热门资讯

空调连续工作多久需要停机休息 空调连续工作的时间取决于多个因素,包括空调的型号、功率、使用环境和维护情况等。一般来说,空调可以连续...
空调哪个符号是除湿的 空调除湿功能通常用一个水滴形状的符号表示。不同品牌和型号的空调遥控器可能会有所差异,但一般来说,除湿...
格力空调多长时间加一次氟利昂 1、一般情况下,空调对氟利昂的使用量是非常小的,所以在空调使用了四年左右的时候再考虑加也没问题。2、...
空调用多长时间需要加氟一次 一般情况下是五年。当出现以下这几种情况时,空调才需要加氟。1、空调的室内机和室外机各有两个接口,当接...
格调生活·C标思享荟:卡萨帝在... 9月12日的郑州龙湖金融岛,夜风轻拂,灯光璀璨。“C标时刻共传奇——卡萨帝思享荟暨20周年品牌盛典郑...
品牌价值破千亿、高端份额持续领... 9月12日,“C标时刻共传奇——卡萨帝思享荟暨20周年品牌盛典郑州站”在郑州龙湖金融岛举办。2026...
空调主板坏了修800还是换新的 空调主板坏了是修还是换新,需要考虑多个因素,以下是一些建议:1. 维修成本:如果维修费用较低,比如 ...
空调开多久需要休息多长时间 问题:空调开多久需要休息多长时间回答:1、在使用空调的过程中,一般空调开7~8个小时左右需要休息2~...
中央空调多长时间清洗一次 1、一般空调开机前清洗一次即可,空调开机中间时段再清洗一次,空调关机时清洗一次,这样比较合理。2、空...
中央空调氟利昂多久加一次 看空调制热和制冷程度,很多人的观点认为氟利昂必须一年放一次,其实这个观点是错误的,理解上面有点偏差,...