Kotlin自定義實(shí)現(xiàn)支付密碼數(shù)字鍵盤的方法實(shí)例
你能學(xué)到什么
- kotlin的使用, 擴(kuò)展特性的寫法等
- 自定義ViewGroup的一些基礎(chǔ)知識(shí)
- xml屬性的編寫和讀取
因?yàn)槊總€(gè)按鍵都考慮到需要支持背景設(shè)置等其他個(gè)性設(shè)置和Touch手勢的處理, 所以我決定采用 每個(gè)按鍵 對(duì)應(yīng)一個(gè)View的思路實(shí)現(xiàn). 否則可以使用Canvas.drawText
實(shí)現(xiàn)
這樣可以提高擴(kuò)展性和可自定義性
1.根據(jù)效果圖先定義按鍵
//首先定義需要的那些按鍵 //順序打亂,展示的時(shí)候也就是亂序的,可以更安全. //特殊按鍵-> "":表示空白占位按鍵; "-1":表示回退鍵, 也就是刪除. var keys = arrayOf("1", "2", "3", "4", "5", "6", "7", "8", "9", "", "0", "-1")
更新對(duì)應(yīng)的按鍵, 創(chuàng)建對(duì)應(yīng)的view
keys.forEach { val keyView: View = when (it) { "-1" -> { //刪除 imageView(R.drawable.keyboard_del, R.drawable.keyboard_del_press).apply { background = null setBackgroundColor(Color.parseColor("#E2E7ED")) } } "" -> { //占位View View(context).apply { setBackgroundColor(Color.parseColor("#E2E7ED")) } } else -> { createKeyView(it) } } keyView.tag = it //通過tag, 保存按鍵對(duì)應(yīng)的值 addView(keyView) } private fun createKeyView(key: String): View { return if (useImageKey) { val keyRes = when (key) { "1" -> R.drawable.keyboard_1 "2" -> R.drawable.keyboard_2 "3" -> R.drawable.keyboard_3 "4" -> R.drawable.keyboard_4 "5" -> R.drawable.keyboard_5 "6" -> R.drawable.keyboard_6 "7" -> R.drawable.keyboard_7 "8" -> R.drawable.keyboard_8 "9" -> R.drawable.keyboard_9 else -> R.drawable.keyboard_0 } imageView(keyRes) } else { textView(key) } } private fun imageView(res: Int, pressRes: Int = -1): ImageView { return ImageView(context).apply { if (pressRes == -1) { setImageResource(res) } else { setImageResource(res) //setImageDrawable(ResUtil.selector(getDrawable(res), getDrawable(pressRes))) } scaleType = ImageView.ScaleType.CENTER keyViewBGDrawable?.let { background = it.constantState.newDrawable() } setOnClickListener(this@KeyboardLayout) } } private fun textView(text: String): TextView { return TextView(context).apply { gravity = Gravity.CENTER this.text = text setTextSize(TypedValue.COMPLEX_UNIT_PX, keyTextSize) keyViewBGDrawable?.let { background = it.constantState.newDrawable() } setTextColor(Color.BLACK) setOnClickListener(this@KeyboardLayout) } }
2.按鍵元素創(chuàng)建好之后, 開始自定義ViewGroup的標(biāo)準(zhǔn)操作
onMeasure:測量每個(gè)按鍵的寬度和高度
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { //super.onMeasure(widthMeasureSpec, heightMeasureSpec) var widthSize = MeasureSpec.getSize(widthMeasureSpec) val widthMode = MeasureSpec.getMode(widthMeasureSpec) var heightSize = MeasureSpec.getSize(heightMeasureSpec) val heightMode = MeasureSpec.getMode(heightMeasureSpec) if (widthMode != MeasureSpec.EXACTLY) { widthSize = resources.displayMetrics.widthPixels } if (heightMode != MeasureSpec.EXACTLY) { heightSize = (4 * keyViewHeight + 3 * vSpace).toInt() } childWidth = ((widthSize - 2 * hSpace - paddingLeft - paddingRight) / 3).toInt() childHeight = ((heightSize - 3 * vSpace - paddingTop - paddingBottom) / 4).toInt() childs { _, view -> view.measure(exactlyMeasure(childWidth), exactlyMeasure(childHeight)) } setMeasuredDimension(widthSize, heightSize) }
onLayout:決定按鍵在ViewGroup中的坐標(biāo)位置
override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) { //一行一行布局, 共4行 for (line in 0..3) { var top: Int = (paddingTop + line * (childHeight + vSpace)).toInt() //3列 for (i in 0..2) { var left: Int = (paddingLeft + i * (childWidth + hSpace)).toInt() getChildAt(line * 3 + i).layout(left, top, left + childWidth, top + childHeight) } } }
3:事件監(jiān)聽和回調(diào)
override fun onClick(v: View?) { if (onKeyboardInputListener == null) { return } v?.let { view -> val tag = view.tag if (tag is String) { val isDel = "-1" == tag onKeyboardInputListener?.onKeyboardInput(tag, isDel) } } }
4:xml中的屬性聲明
需要在 values 文件夾中創(chuàng)建一個(gè)任意文件名的xml文件
<?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="KeyboardLayout"> <attr name="r_key_height" format="dimension"/> <attr name="r_key_width" format="dimension"/> <attr name="r_key_text_size" format="dimension"/> <attr name="r_key_background" format="reference"/> <attr name="r_background" format="reference"/> <attr name="r_use_image_key" format="boolean"/> </declare-styleable> </resources>
declare-styleable 都是標(biāo)準(zhǔn)寫法, name對(duì)應(yīng)的就是自定義view的類型, 都是標(biāo)準(zhǔn)寫法, 不同的format對(duì)應(yīng)不同的get方法. 熟悉了就很容易使用.
5:xml中的屬性讀取
init { val typedArray = context.obtainStyledAttributes(attributeSet, R.styleable.KeyboardLayout) //注意1: keyViewHeight = typedArray.getDimensionPixelOffset(R.styleable.KeyboardLayout_r_key_height, keyViewHeight) //typedArray.getDimensionPixelOffset(R.styleable.KeyboardLayout_r_key_width, keyViewHeight) keyTextSize = typedArray.getDimension(R.styleable.KeyboardLayout_r_key_text_size, keyTextSize) useImageKey = typedArray.getBoolean(R.styleable.KeyboardLayout_r_use_image_key, useImageKey) keyViewBGDrawable = typedArray.getDrawable(R.styleable.KeyboardLayout_r_key_background) if (keyViewBGDrawable == null) { keyViewBGDrawable = getDrawable(R.drawable.base_white_bg_selector) } mBackgroundDrawable = typedArray.getDrawable(R.styleable.KeyboardLayout_r_background) if (mBackgroundDrawable == null) { mBackgroundDrawable = ColorDrawable(getColor(R.color.base_chat_bg_color)) } setWillNotDraw(false) typedArray.recycle() //注意2 }
注意1,2: 都是必備的寫法, 中間部分才是對(duì)應(yīng)的屬性讀取操作.
源碼地址 https://github.com/angcyo/KeyboardLayout (本地下載)
總結(jié)
以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問大家可以留言交流,謝謝大家對(duì)腳本之家的支持。
相關(guān)文章
Android底部導(dǎo)航組件BottomNavigationView
這篇文章主要介紹了Android底部導(dǎo)航組件BottomNavigationView,BottomNavigationView是相當(dāng)于一個(gè)導(dǎo)航的標(biāo)簽,但是它的形式就是像QQ微信之類的界面,至于寫出后怎樣綁定這三個(gè)界面,就得用Fragment,寫這三個(gè)頁面的布局2023-03-03Android內(nèi)嵌Unity并實(shí)現(xiàn)互相跳轉(zhuǎn)的實(shí)例代碼
這篇文章主要介紹了Android內(nèi)嵌Unity并實(shí)現(xiàn)互相跳轉(zhuǎn)的實(shí)例代碼,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-11-11ActivityManagerService廣播并行發(fā)送與串行發(fā)送示例解析
這篇文章主要為大家介紹了ActivityManagerService廣播并行發(fā)送與串行發(fā)送示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-03-03Android通過PHP服務(wù)器實(shí)現(xiàn)登錄功能
這篇文章主要為大家詳細(xì)介紹了Android通過PHP服務(wù)器實(shí)現(xiàn)登錄功能的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-01-01Android編程UI設(shè)計(jì)之GridView和ImageView的用法
這篇文章主要介紹了Android編程UI設(shè)計(jì)之GridView和ImageView的用法,結(jié)合實(shí)例形式較為詳細(xì)的分析了Android中GridView和ImageView組件的相關(guān)方法使用技巧,需要的朋友可以參考下2016-01-01Android入門之LinearLayout、AbsoluteLayout的用法實(shí)例講解
這篇文章主要介紹了Android入門之LinearLayout、AbsoluteLayout的用法,對(duì)于Android初學(xué)者有很好的參考借鑒價(jià)值,需要的朋友可以參考下2014-08-08Android中的導(dǎo)航navigation的使用詳細(xì)步驟
在Android中,導(dǎo)航主要通過使用Navigation SDK來實(shí)現(xiàn),該SDK提供了一組工具和組件,可以幫助開發(fā)人員構(gòu)建具有一致性和可訪問性的用戶界面,這篇文章主要介紹了Android中的導(dǎo)航navigation的使用詳細(xì)步驟,需要的朋友可以參考下2024-04-04