栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 移动开发 > Android

Android实现自定义验证码输入框效果(实例代码)

Android 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Android实现自定义验证码输入框效果(实例代码)

这里提一下,这个当时也是在网上看到一个博主写的代码改了下用在我么项目中的验证码输入框。博主的地址不记得了这里只能顺带标注一下。。。

效果图如下:

就是这个酱紫

直入主题,代码如下:

xml布局:



 
 
  
   
    
     
     
    
 
    
   
 
   
    
     
     
    
 
    
   
   
    
     
     
    
 
    
   
   
 
    
     
 
     
    
    
   
   
 
    
     
 
     
    
    
   
   
 
    
     
 
     
    
    
   
  
 
  
 
 
 
 

class CustomSmsCodeInputLayout : RelativeLayout, View.onClickListener {
 
 
 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()
  
  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)) {
   
   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) //强制隐藏键盘
 }
 
 
 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就是CustomSmsCodeInputLayout
ll_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()//点击重新获取按钮的监听

总结

以上所述是小编给大家介绍的Android实现自定义验证码输入框效果,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对考高分网网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/154541.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号