自定义 View 实战 07 - 字母栏

2020-07-13  本文已影响0人  Kotyo
字母栏

效果分析:

自定义属性

<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
    }

项目地址

上一篇下一篇

猜你喜欢

热点阅读