Android自定义字母索引View

代码:


import android.content.Context
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.MotionEvent.*
import android.view.View
import java.util.*
/**
 * 使用示例:
 * <com.david.core.view.CharsView
	android:id="@+id/song_chars"
	android:layout_width="40dp"
	android:layout_height="match_parent"
	android:layout_gravity="end"
	android:layout_marginBottom="180dp"/>
 * 
 * 
 * */
class CharsView: View {
    constructor(context: Context) : super(context)
    constructor(context: Context, attr:AttributeSet) : super(context, attr)


    private var chars = 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 paint:Paint = Paint()
    private var charWidth = 0f

    private var selectColor = Color.parseColor("#00ff00")
    private var defaultColor = Color.parseColor("#b2b2b2")
    private var touchColor = Color.parseColor("#0000ff")

    private var current = 0
    private var touchingPosition = -1
    init {
        paint.color = Color.parseColor("#b2b2b2")
        paint.textSize = 22f
        paint.isAntiAlias = true
        charWidth = paint.measureText("A")
        textSize = paint.textSize
    }
    private var charHeight = 0
    private var startX = 0f

    private var textSize = 0f

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
        charHeight = measuredHeight/chars.size

        startX = (measuredWidth shr 1) - charWidth/2
    }

    override fun onDraw(canvas: Canvas?) {
        super.onDraw(canvas)
        if (canvas != null) {
            if (touchingPosition >= 0) {
                paint.color = touchColor
                canvas.drawCircle((measuredWidth shr 1).toFloat(),
                    ((touchingPosition + 1)*charHeight).toFloat() - charWidth/2, 20f, paint)

                /*实现点中的字母变大,由于手指按住无法看到所以先注释*/
//                for ((index, item) in chars.withIndex()) {
//                    if (index == touchingPosition) {//选中的item设置字体变大
//                        paint.textSize = textSize + 3
//                    } else {
//                        paint.textSize = textSize
//                    }
//                    drawChar(canvas, index, item)
//                }
            }
//            else {
//                for ((index, item) in chars.withIndex()) {
//                    drawChar(canvas, index, item)
//                }
//            }

            for ((index, item) in chars.withIndex()) {
                drawChar(canvas, index, item)
            }
        }
    }

    private fun drawChar(canvas: Canvas, index:Int, item:Char){
        paint.color = if (current == index) selectColor else defaultColor
        startX = (measuredWidth shr 1)-paint.measureText(item.toString())/2
        canvas.drawText(item.toString(), startX, (charHeight * (index + 1)).toFloat(), paint)
    }

    fun setCurrentChar(char: String){
        setCurrentChar(getCharIndex(char.toUpperCase(Locale.ROOT)[0]))
    }

    fun setCurrentChar(char: Char){
        setCurrentChar(getCharIndex(char))
    }

    fun setCurrentChar(position:Int){
        current = position
        invalidate()
    }

    var tempPosition = -1
    override fun onTouchEvent(event: MotionEvent?): Boolean {
        if (event != null) {
            when(event.action) {
                ACTION_MOVE,ACTION_DOWN -> {
                    tempPosition = (event.getY(0)/charHeight).toInt()
                    if (current != tempPosition) {
                        current = tempPosition
                        touchingPosition = current
                        invalidate()

                        onCharSelectListener?.onCharSelect(chars[current])
                    }
                }
                ACTION_UP -> {
                    if (touchingPosition >= 0) {
                        touchingPosition = -1
                        invalidate()
                    }
                }
            }
        }
        return true
    }

    var onCharSelectListener: OnCharSelectListener? = null

    interface OnCharSelectListener{
        fun onCharSelect(char:Char)
    }

    /**
     * 通过char与int转化直接查找,时间复杂度为O(1)
     * */
    private fun getCharIndex(item:Char):Int{
        return if ('#' == item) {
            26
        } else {
            item.toInt() - 65;
        }
    }

    /**
     * 二分法时间复杂度:O(log2n);遍历元素查找时间复杂度为O(n)
     * 二分法查找排序好的数组下标,对于已经排好序的人名,地名等查找效率更高
     * */
    private fun indexOf(item:Char):Int{
        var left = 0
        var right:Int = chars.size - 1
        var medium = (left + right) shr 1

        while (left <= right) {
            when {
                item == chars[medium] -> {
                    return medium
                }
                item < chars[medium] -> {
                    right = medium - 1
                }
                else -> {
                    left = medium + 1
                }
            }
            medium = (left + right) shr 1
        }
        if ('#' == item) {
            return 26
        }
        return -1
    }
}

效果图:





不足之处敬请指出,万分感谢🙏。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值