美文网首页
自定义 View 实战 07 - 字母栏

自定义 View 实战 07 - 字母栏

作者: Kotyo | 来源:发表于2020-07-13 17:37 被阅读0次
    字母栏

    效果分析:

    • 绘制 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
        }
    

    项目地址

    相关文章

      网友评论

          本文标题:自定义 View 实战 07 - 字母栏

          本文链接:https://www.haomeiwen.com/subject/ghfzcktx.html