自定義 View 實戰 07 - 字母欄

字母欄

效果分析:

  • 繪制 26 個字母
  • 處理手勢事件

自定義屬性

<declare-styleable name="LetterView">
        //繪制的文字大小
        <attr name="letterSize" format="dimension"/>
        //繪制文字的默認顏色
        <attr name="letterColor" format="reference|color" />
</declare-styleable>

初始化屬性

    private var mNormalPaint = TextPaint()
    private var mSelectPaint = TextPaint()
    private var mLetters = arrayOf("A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z")
    private var mCurPosition = -1

    init {
        val ta = context.obtainStyledAttributes(attributes, R.styleable.LetterView)
        val letterSize = ta.getDimensionPixelSize(R.styleable.LetterView_letterSize, sp2Px(14,resources))
        val letterColor = ta.getColor(R.styleable.LetterView_letterColor,Color.BLACK)
        ta.recycle()

        mNormalPaint.textSize = letterSize.toFloat()
        mNormalPaint.color = letterColor

        mSelectPaint.textSize = letterSize.toFloat()
        mSelectPaint.color = Color.RED
    }

測量

 override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
        //寬度 = 左內邊距 + 右內邊距 + 文字的寬度
        val width = paddingLeft + paddingRight + mNormalPaint.measureText(mLetters[0]).toInt()
        val height = MeasureSpec.getSize(heightMeasureSpec)
        setMeasuredDimension(width,height)
    }

繪制

override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)
            val x = (width - mNormalPaint.measureText(mLetters[0]))/2
            //獲取字母的高度
            val letterHeight = (height - paddingTop - paddingBottom)/mLetters.size
        for(i in mLetters.indices){
            val deltaY = (mNormalPaint.fontMetricsInt.bottom - mNormalPaint.fontMetricsInt.top)/2-mNormalPaint.fontMetricsInt.bottom
            val baseY = deltaY + letterHeight/2 + letterHeight * i
            if(i == mCurPosition){
                canvas.drawText(mLetters[i],x,baseY.toFloat(),mSelectPaint)
            }else{
                canvas.drawText(mLetters[i],x,baseY.toFloat(),mNormalPaint)
            }
        }
    }

手勢

override fun onTouchEvent(event: MotionEvent): Boolean {
        when(event.action){
            MotionEvent.ACTION_DOWN,MotionEvent.ACTION_MOVE->{
                val y= event.y
                val position  = (y / ((height - paddingTop - paddingBottom) / mLetters.size)).toInt()
                //如果當前 position 與之前 position 相同則不需要重新繪制
                if(position == mCurPosition){
                    return false
                }
                mCurPosition = position
                invalidate()
            }
        }
        return true
    }

項目地址

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。