您好,登錄后才能下訂單哦!
這期內(nèi)容當(dāng)中小編將會(huì)給大家?guī)碛嘘P(guān)Android中怎么自定義一個(gè)驗(yàn)證碼輸入框,文章內(nèi)容豐富且以專業(yè)的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。
xml布局:
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:gravity="end" > <TextView android:id="@+id/tv_view_top_tip" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="5dp" android:textColor="@color/img_code_text_error_color" android:textSize="12sp" android:text="error" /> <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <LinearLayout android:id="@+id/ll_code" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:baselineAligned="false"> <LinearLayout android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:orientation="vertical" android:layout_marginRight="5dp"> <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="6dp" > <TextView android:id="@+id/tv_code1" android:layout_width="match_parent" android:layout_height="wrap_content" android:textColor="@color/global_text_color_10" android:textSize="24sp" android:textStyle="bold" android:background="@null" android:layout_centerInParent="true" android:gravity="center"/> <View android:id="@+id/v1_center_line" android:layout_width="1.5dp" android:layout_height="16dp" android:visibility="invisible" android:layout_centerInParent="true" android:background="@color/mainColor" /> </RelativeLayout> <View android:id="@+id/v1" android:layout_width="match_parent" android:layout_height="1dp" android:background="@color/mainColor" /> </LinearLayout> <LinearLayout android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:orientation="vertical" android:layout_marginRight="5dp" android:layout_marginLeft="5dp"> <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="6dp" > <TextView android:id="@+id/tv_code2" android:layout_width="match_parent" android:layout_height="wrap_content" android:textColor="@color/global_text_color_10" android:textSize="24sp" android:textStyle="bold" android:background="@null" android:layout_centerInParent="true" android:gravity="center"/> <View android:id="@+id/v2_center_line" android:layout_width="1.5dp" android:layout_height="16dp" android:visibility="invisible" android:layout_centerInParent="true" android:background="@color/mainColor" /> </RelativeLayout> <View android:id="@+id/v2" android:layout_width="match_parent" android:layout_height="1dp" android:background="@color/global_text_color_grey" /> </LinearLayout> <LinearLayout android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:orientation="vertical" android:layout_marginRight="5dp" android:layout_marginLeft="5dp"> <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="6dp" > <TextView android:id="@+id/tv_code3" android:layout_width="match_parent" android:layout_height="wrap_content" android:textColor="@color/global_text_color_10" android:textSize="24sp" android:textStyle="bold" android:background="@null" android:layout_centerInParent="true" android:gravity="center"/> <View android:id="@+id/v3_center_line" android:layout_width="1.5dp" android:layout_height="16dp" android:visibility="invisible" android:layout_centerInParent="true" android:background="@color/mainColor"/> </RelativeLayout> <View android:id="@+id/v3" android:layout_width="match_parent" android:layout_height="1dp" android:background="@color/global_text_color_grey" /> </LinearLayout> <LinearLayout android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:orientation="vertical" android:layout_marginRight="5dp" android:layout_marginLeft="5dp"> <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="6dp" > <TextView android:id="@+id/tv_code4" android:layout_width="match_parent" android:layout_height="wrap_content" android:textColor="@color/global_text_color_10" android:background="@null" android:textStyle="bold" android:textSize="24sp" android:layout_centerInParent="true" android:gravity="center"/> <View android:id="@+id/v4_center_line" android:layout_width="1.5dp" android:layout_height="16dp" android:visibility="invisible" android:layout_centerInParent="true" android:background="@color/mainColor" /> </RelativeLayout> <View android:id="@+id/v4" android:layout_width="match_parent" android:layout_height="1dp" android:background="@color/global_text_color_grey" /> </LinearLayout> <LinearLayout android:id="@+id/ll5_parent" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:orientation="vertical" android:layout_marginRight="5dp" android:layout_marginLeft="5dp"> <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="6dp" > <TextView android:id="@+id/tv_code5" android:layout_width="match_parent" android:layout_height="wrap_content" android:textColor="@color/global_text_color_10" android:background="@null" android:textStyle="bold" android:textSize="24sp" android:layout_centerInParent="true" android:gravity="center"/> <View android:id="@+id/v5_center_line" android:layout_width="1.5dp" android:layout_height="16dp" android:visibility="invisible" android:layout_centerInParent="true" android:background="@color/mainColor" /> </RelativeLayout> <View android:id="@+id/v5" android:layout_width="match_parent" android:layout_height="1dp" android:background="@color/global_text_color_grey" /> </LinearLayout> <LinearLayout android:id="@+id/ll6_parent" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:orientation="vertical" android:layout_marginLeft="5dp"> <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="6dp" > <TextView android:id="@+id/tv_code6" android:layout_width="match_parent" android:layout_height="wrap_content" android:textColor="@color/global_text_color_10" android:background="@null" android:textStyle="bold" android:textSize="24sp" android:layout_centerInParent="true" android:gravity="center"/> <View android:id="@+id/v6_center_line" android:layout_width="1.5dp" android:layout_height="16dp" android:visibility="invisible" android:layout_centerInParent="true" android:background="@color/mainColor" /> </RelativeLayout> <View android:id="@+id/v6" android:layout_width="match_parent" android:layout_height="1dp" android:background="@color/global_text_color_grey" /> </LinearLayout> </LinearLayout> <EditText android:id="@+id/et_code" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignTop="@+id/ll_code" android:layout_alignBottom="@+id/ll_code" android:background="@android:color/transparent" android:textColor="@android:color/transparent" android:cursorVisible="false" android:inputType="number"/> </RelativeLayout> <TextView android:id="@+id/tv_get_sms_code" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="9.5dp" android:paddingBottom="10dp" android:textColor="@color/text_color_pressed_selector" android:textSize="12sp" android:text="@string/resend_verify_code" /> </LinearLayout>class CustomSmsCodeInputLayout : RelativeLayout, View.OnClickListener { /** * 枚舉中有兩種狀態(tài),F(xiàn)OUR四個(gè)輸入框,SIX6個(gè)輸入框 */ 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) } } } } /*啟動(dòng)計(jì)時(shí)器*/ fun startCountDownTimer() { cancelCountDownTimer() /*倒計(jì)時(shí)60秒,每次執(zhí)行間隔1秒*/ mCountDownTimerUtil = CountDownTimerUtil(mContext, tv_get_sms_code, 60000, 1000) mCountDownTimerUtil?.start() } /*上下文*/ private var mContext: Context /*存放驗(yàn)證碼集合*/ var codes: ArrayList<String>? = ArrayList() /*輸入相關(guān)管理器*/ 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() { //驗(yàn)證碼輸入 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) } } } } }) // 監(jiān)聽驗(yàn)證碼刪除按鍵 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) //回退的時(shí)候如果頂部的提示語顯示則隱藏掉 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) } /*控制可輸入的最大長(zhǎng)度*/ private fun regexMaxInputSize(editable: Editable, maxSize: Int) { if (codes?.size!! < maxSize) { // 過濾掉由空格鍵引起的字符串出現(xiàn)空長(zhǎng)串的問題,使用正則替換規(guī)則(\\s*)可以替換掉絕大多數(shù)空白字符或空格 codes?.add(editable.toString().replace(Regex("\\s*"), "")) showCode() } } /** * 顯示輸入的驗(yàn)證碼 */ 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()//設(shè)置高亮顏色 callBack()//回調(diào) } /** * 設(shè)置高亮顏色 */ 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() } } /** * 回調(diào) */ private fun callBack() { if (onInputListener == null) { return } if ((defaultInputNum == InputLineNum.FOUR && codes?.size == 4) ||(defaultInputNum == InputLineNum.SIX && codes?.size == 6)) { /*zi自動(dòng)收起軟鍵盤*/ dismissSoftInput() onInputListener!!.onSuccess(getPhoneCode()) } else { onInputListener!!.onInput() } } //定義回調(diào) interface OnInputListener { fun onSuccess(code: String) fun onInput() } /** * 顯示鍵盤 */ fun showSoftInput() { //顯示軟鍵盤 if (imm != null && et_code != null) { et_code.requestFocus() //需先獲得焦點(diǎn)才能主動(dòng)彈出軟鍵盤 et_code.postDelayed({ imm?.showSoftInput(et_code, InputMethodManager.SHOW_FORCED) }, 200) } } /** * 英藏鍵盤 */ fun dismissSoftInput() { et_code.requestFocus() //某些情況下必須延遲一定時(shí)間在執(zhí)行,不然英藏不了 et_code.postDelayed({ imm?.hideSoftInputFromWindow(et_code.windowToken, 0) }, 200) //強(qiáng)制隱藏鍵盤 } /** * 獲得手機(jī)號(hào)驗(yàn)證碼 * @return 驗(yàn)證碼 */ 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 } /*設(shè)置頂部提示是否顯示*/ fun setTopTipVisible(isVisible: Boolean){ tv_view_top_tip.visibility = if(isVisible) View.VISIBLE else View.INVISIBLE } /*設(shè)置當(dāng)前項(xiàng)中間豎線是否顯示*/ fun setCurrentCenterLineVisible(isVisible: Boolean){ isVisibleCenterLine = isVisible //顯示豎線的話默認(rèn)顯示出第一條 v1_center_line.visibility = if(isVisibleCenterLine) View.VISIBLE else View.INVISIBLE } /*設(shè)置底部獲取短信按鈕是否顯示*/ fun setBottomSmsTvVisible(isVisible: Boolean){ tv_get_sms_code.visibility = if(isVisible) View.VISIBLE else View.GONE } /*設(shè)置頂部提示字樣*/ fun setTopTipText(text: String){ tv_view_top_tip.text = text } /*設(shè)置頂部提示字樣顏色*/ fun setTopTipTextColor(textColor: Int){ tv_view_top_tip.setTextColor(textColor) } /*設(shè)置當(dāng)前指定項(xiàng)下環(huán)線顏色*/ fun setCurrentIndexLineColor(underlineColor: Int){ color_focus = underlineColor v1.setBackgroundColor(color_focus) } /*設(shè)置當(dāng)前指定項(xiàng)的中間線顏色*/ fun setCenterLineColor(centerLineColor: Int){ color_centerLine = centerLineColor v1_center_line.setBackgroundColor(color_centerLine) } /*設(shè)置不是當(dāng)前指定項(xiàng)下劃線顏色*/ fun setAnotherIndexLineColor(underlineColor: Int){ color_default = underlineColor } /*設(shè)置頂部提示的字樣和顏色*/ 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 } /*更新獲取短信按鈕狀態(tài)*/ fun updateGetSmsTvEnable(isEnable: Boolean){ tv_get_sms_code.isEnabled = isEnable tv_get_sms_code.setTextColor(mContext.resources.getColor(R.color.global_text_color_6c)) } /*需要展示的輸入框數(shù)量*/ 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 } } } /*關(guān)閉清除計(jì)時(shí)器*/ fun cancelCountDownTimer(){ if (mCountDownTimerUtil != null){ mCountDownTimerUtil?.cancel() mCountDownTimerUtil = null } } /**清除所有輸入的值*/ fun clearAllInputValues(){ setTopTipVisible(false) codes?.clear() showCode() } /** * 獲取到驗(yàn)證碼進(jìn)行彈窗顯示 */ 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() } /** * 驗(yàn)證出錯(cuò)時(shí)抖動(dòng)輸入框提示 */ 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) // 同時(shí)執(zhí)行x、y軸的動(dòng)畫 animatorSet.interpolator = CycleInterpolator(2F)// 執(zhí)行2次 animatorSet.duration = 500 // 1秒后結(jié)束 animatorSet.doOnEnd { clearAllInputValues() animatorSet.cancel() } animatorSet.start() } /*輸入框監(jiān)聽回調(diào)《供外部調(diào)用》*/ private var onInputListener: OnInputListener? = null fun setOnInputListener(onInputListener: OnInputListener) { this.onInputListener = onInputListener } /*獲取驗(yàn)證碼點(diǎn)擊回調(diào)《供外部調(diào)用》*/ private var onClickSmsCodeTvListener: OnClickListener? = null fun setOnClickSmsCodeTvListener(onClickSmsCodeTvListener: OnClickListener){ this.onClickSmsCodeTvListener = onClickSmsCodeTvListener } }
主要有兩種顯示樣式,在枚舉中定義了4個(gè)輸入框6個(gè)輸入框
基本調(diào)用代碼如下:
//ll_sms_input就是CustomSmsCodeInputLayoutll_sms_input.run {//里邊的配置可以自行選擇配置 setTopTipVisible(false) setCurrentCenterLineVisible(true) setBottomSmsTvVisible(true) setShowInputNum(CustomSmsCodeInputLayout.InputLineNum.SIX)//這里加載的是六個(gè)輸入框 setCurrentIndexLineColor(resources.getColor(R.color.global_text_color_grey)) //設(shè)置輸入類型只能是數(shù)字 setInputType(InputType.TYPE_CLASS_NUMBER or InputType.TYPE_NUMBER_FLAG_SIGNED) showSoftInput() }ll_sms_input.setOnInputListener()//做輸入完成后的監(jiān)聽ll_sms_input.setOnClickSmsCodeTvListener()//點(diǎn)擊重新獲取按鈕的監(jiān)聽
上述就是小編為大家分享的Android中怎么自定義一個(gè)驗(yàn)證碼輸入框了,如果剛好有類似的疑惑,不妨參照上述分析進(jìn)行理解。如果想知道更多相關(guān)知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。