1. 程式人生 > >自定義控制元件-----自定義數字鍵盤,適配了正則表示式的帶輸出字串的控制元件

自定義控制元件-----自定義數字鍵盤,適配了正則表示式的帶輸出字串的控制元件

一、主要的類:CustomAmountInputKeyboard 

class CustomAmountInputKeyboard constructor(context: Context, attrs: AttributeSet? = null) : LinearLayout(context, attrs), AdapterView.OnItemClickListener, View.OnClickListener {

    private var mItemHeight: Int = 0//行高
    private var mItemTextSize: Float = 0.toFloat()//item文字大小
    private var mKeyBoardType: Int = 0//鍵盤型別
    private var mAdapter: KeyBoardNumAdapter? = null

    private var mKeyBoartTouchListener: KeyBoartTouchListener? = null
    private var mInput: String = ""//已經輸入的數字

    //    private val mPatternCalculation = "^(([1-9]\\d{0,8})|([0]{0,1}))(\\.(\\d){0,2})?$"//計算器模式
    private val mPatternCalculation = "^(([1-9]{1}\\d{0,6})|([0]{1}))(\\.(\\d){0,2})?\$"//計算器模式
    private val mPatternPassword = "^(\\d{0,6})"//密碼鍵盤模式

    companion object {
        private val TYPE_CALCULATION = 1//主介面鍵盤
        private val TYPE_PASSWORD = 2//輸入密碼
        private val TYPE_OTHER = 3//亂序
    }

    init {
        val view = LayoutInflater.from(context).inflate(R.layout.base_view_custom_amount_input_keyboard, null)
        setLinearLayoutStyle(context, attrs, view)
        addView(view)
    }

    private fun setLinearLayoutStyle(context: Context, attrs: AttributeSet?, view: View) {
        val array = context.obtainStyledAttributes(attrs, R.styleable.CustomAmountInputKeyboard)
        mItemHeight = array.getDimensionPixelSize(R.styleable.CustomAmountInputKeyboard_itemHeight, 100)
        mItemTextSize = array.getDimension(R.styleable.CustomAmountInputKeyboard_itemTextSize, 30f)
        mKeyBoardType = array.getInt(R.styleable.CustomAmountInputKeyboard_keyBoardType, TYPE_CALCULATION)

        val gvKeyBoardNum = view.findViewById<View>(R.id.gv_keyboard_num) as GridView
        gvKeyBoardNum.onItemClickListener = this
        mAdapter = KeyBoardNumAdapter(context, getNumbers(mKeyBoardType))
        gvKeyBoardNum.adapter = mAdapter

        val tvKeyBoardZero: TextView = view.findViewById<View>(R.id.tv_keyboard_zero) as TextView
        tvKeyBoardZero.setOnClickListener(this)
        tvKeyBoardZero.textSize = mItemTextSize
        setViewHeight(tvKeyBoardZero)
        val windowManager1 = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager
        tvKeyBoardZero.setPadding(0, 0, windowManager1.defaultDisplay.width / 4, 0)

        val tvKeyboardPoint: TextView = view.findViewById(R.id.tv_keyboard_point) as TextView
        tvKeyboardPoint.setOnClickListener(this)
        tvKeyboardPoint.textSize = mItemTextSize
        setViewHeight(tvKeyboardPoint)

        val tvKeyboardClear: TextView = view.findViewById(R.id.tv_keyboard_clear) as TextView
        tvKeyboardClear.setOnClickListener(this)
        tvKeyboardClear.textSize = mItemTextSize
        setViewHeight(tvKeyboardClear)
        if (mKeyBoardType == TYPE_PASSWORD) tvKeyboardClear.visibility = View.VISIBLE else tvKeyboardPoint.visibility = View.VISIBLE

        val llKeyBoardDelete = view.findViewById<View>(R.id.ll_keyboard_del) as LinearLayout
        llKeyBoardDelete.setOnClickListener(this)

        val tvKeyBoardOk = view.findViewById<View>(R.id.tv_keyboard_ok) as TextView
        tvKeyBoardOk.setOnClickListener(this)
        tvKeyBoardOk.textSize = mItemTextSize - 8
    }

    /**
     * 設定子控制元件的高度
     */
    private fun setViewHeight(view: View) {
        val params = view.layoutParams as LinearLayout.LayoutParams
        val windowManager = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager
        val height = (windowManager.defaultDisplay.height * mItemHeight / 1280.0).toInt()
        params.height = height
        view.layoutParams = params
    }


    /**
     * 獲得鍵盤上要填入的資料
     */
    private fun getNumbers(keyBoardType: Int): List<String> {
        var numbers: MutableList<String>? = null
        when (keyBoardType) {
            TYPE_CALCULATION -> numbers = Arrays.asList(*arrayOf("1", "2", "3", "4", "5", "6", "7", "8", "9"))
//            TYPE_PASSWORD -> numbers = Arrays.asList(*arrayOf("1", "2", "3", "4", "5", "6", "7", "8", "9", "0", " ", "C"))
//            TYPE_OTHER -> {
//                numbers = Arrays.asList(*arrayOf("1", "2", "3", "4", "5", "6", "7", "8", "9", " ", "0", "C"))
//                Collections.shuffle(numbers)//亂序
//                numbers[numbers.indexOf(" ")] = numbers[10]
//                numbers[10] = " "
//                numbers[numbers.indexOf("C")] = numbers[11]
//                numbers[11] = "C"
//            }
            else -> numbers = Arrays.asList(*arrayOf("1", "2", "3", "4", "5", "6", "7", "8", "9"))
        }

        return numbers
    }

    override fun onClick(v: View) {
        if (mKeyBoartTouchListener == null) return
        when (v.id) {
            R.id.tv_keyboard_zero -> input((v as TextView).text as String)
            R.id.tv_keyboard_point -> input((v as TextView).text as String)
            R.id.tv_keyboard_clear -> input((v as TextView).text as String)
            R.id.ll_keyboard_del -> input("del")
            R.id.tv_keyboard_ok -> mKeyBoartTouchListener!!.onOkTouch()
        }
    }

    override fun onItemClick(parent: AdapterView<*>, view: View, position: Int, id: Long) {
        input(mAdapter!!.getItem(position).toString() + "")
        showNumber(mInput)
    }

    interface KeyBoartTouchListener {
        fun onOkTouch()
        fun onInputNumberTouch(inputNumber: String)
    }

    fun setKeyBoartTouchListener(listener: KeyBoartTouchListener) {
        this.mKeyBoartTouchListener = listener
    }

    private inner class KeyBoardNumAdapter(private val mContext: Context, mNumbers: List<String>) : BaseAdapter() {
        private val mNumbers: List<String>

        private val inflater: LayoutInflater

        init {
            this.mNumbers = getNumbers(mNumbers)
            this.inflater = LayoutInflater.from(mContext)
        }

        private fun getNumbers(mNumbers: List<String>?): List<String> {
            var mNumbers = mNumbers
            if (mNumbers == null) {
                mNumbers = ArrayList()
            }
            return mNumbers
        }

        override fun getCount(): Int {
            return mNumbers.size
        }

        override fun getItem(position: Int): Any {
            return mNumbers[position]
        }

        override fun getItemId(position: Int): Long {
            return position.toLong()
        }


        override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
            var convertView = convertView
            val hodler: ViewHodler
            if (convertView == null) {
                hodler = ViewHodler()
                convertView = inflater.inflate(R.layout.base_grid_item_custom_amount_input_keyboard, null)
                hodler.mTvStyle = convertView!!.findViewById<View>(R.id.tv_style) as TextView
                hodler.mTvStyle!!.textSize = mItemTextSize

                convertView.tag = hodler
            } else {
                hodler = convertView.tag as ViewHodler
            }
            setViewHeight(hodler.mTvStyle!!)

            val number = mNumbers[position]
            hodler.mTvStyle!!.text = number

            if (position == 11) {
                hodler.mTvStyle!!.setTextColor(resources.getColor(R.color.colorAccent))//清除按鈕
            }

            return convertView
        }

        private inner class ViewHodler {
            var mTvStyle: TextView? = null
        }

    }

    /**
     * 顯示內容
     */
    fun showNumber(inputNumber: String) {
        if (mKeyBoartTouchListener == null) return
        mKeyBoartTouchListener!!.onInputNumberTouch(inputNumber)
    }

    /**
     * 數字鍵盤輸入內容
     */
    fun input(input: String) {
        var tempInput: String = mInput + input
        var regex: String? = null
        when (mKeyBoardType) {
            TYPE_CALCULATION -> {//計算器模式(帶小數點)
                if ("0" == (tempInput)) return//一次輸入0
                if ("." == tempInput) tempInput = "0."
                regex = mPatternCalculation
            }
            TYPE_PASSWORD -> regex = mPatternPassword//密碼鍵盤模式(帶C的清除按鈕)
        }
        when (input) {
            "del" -> if (tempInput.length > 4) {
                if (tempInput.startsWith("0.") && tempInput.length == 5) {//此時tempInput == 0.del
                    mInput = ""
                } else {
                    tempInput = tempInput.substring(0, tempInput.length - 4)
                }

            } else mInput = ""
            "C" -> tempInput = ""
        }

        var pattern = Pattern.compile(regex)
        if (pattern.matcher(tempInput).matches()) {
            mInput = tempInput
        }
        showNumber(mInput)
    }

}

二、呼叫

class MainActivity : BaseActivity(),CustomAmountInputKeyboard.KeyBoartTouchListener{
    var mPopupWindow: TipPopupWindow? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.main_activity_main)

        keyboard.setKeyBoartTouchListener(this)
    }


    @SuppressLint("NewApi")
    override fun onOkTouch() {
        //點選OK按鈕
    }

    override fun onInputNumberTouch(inputNumber: String) {
        if (!"".equals(inputNumber)) tv_input_amount.text = inputNumber else tv_input_amount.text = "0"
    }

}

三、其他res下面的檔案可參考 https://mp.csdn.net/postedit/81163156 裡的佈局及資源