代码:
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
}
}
效果图:
不足之处敬请指出,万分感谢🙏。
因篇幅问题不能全部显示,请点此查看更多更全内容