- 要实现右边的字母索引。
- 滑动事件响应到
RecyclerView
上。 - 展示当前选中的索引值(效果图中间灰色B)。
实现思路:
- 用自定义
View
画出字母A到Z。 - 重写
onTouch
方法定位当前字母索引。
3.通过RecyclerView
的scrollToPositionWithOffset()
方法来触发定位。
实现
- 1.自定义View
重写onMeasure()
,onTouchEvent
,onDraw()
//设定高度,宽度值固定。
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
setMeasuredDimension(DisplayUtils.dip2px(15F), DisplayUtils.dip2px(390F))
}
在onDraw
方法里按照定距离画出字母就可以了。
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
// v是字母,aList是A---Z的集合。
for ((i, v) in aList.withIndex()) {
canvas.drawText(
v.toString(),
DisplayUtils.dip2px(7.5F).toFloat(),
DisplayUtils.dip2px((15 * i) + 12F).toFloat(),
paint
)
}
}
在onTouch()
方法里需要注意的是,写一个接口,让滑动和当前选中事件暴露给Activity
, 方便RecyclerView
滑动到指定位置。
interface AlphabetCallBack{
//在移动的时候调用
fun movingChar(c:Char)
//最后选中的位置。
fun finished(i:Int)
}
上面的接口中的两个方法分别对应onTouch()
的MotionEven.ACTION_MOVE
和MotionEvent.ACTION_UP
关键部分。
override fun onTouchEvent(event: MotionEvent?): Boolean {
val y:Int=event?.y!!.toInt()
if (event.action==MotionEvent.ACTION_MOVE){
//这里把View的高度等分,找出对应的值。
val position= (DisplayUtils.px2dip(y) - DisplayUtils.dip2px(12F))/DisplayUtils.dip2px(15F)
if (position!=oldPosition){
if (callBack!=null){
callBack!!.movingChar(aList[position])
}
oldPosition=position
}
}else if (event.action==MotionEvent.ACTION_UP){
if (callBack!=null){
callBack!!.finished(oldPosition)
}
}
//返回true 表示事件已被消费。
return true
}
让Activity
实现AlphabetCallBack
。
override fun movingChar(c: Char) {
//防止多次运行
if (tvAlpha.visibility != View.VISIBLE){
tvAlpha.text=c.toString()
tvAlpha.visibility=View.VISIBLE
}else{
tvAlpha.text=c.toString()
}
}
//最后选中位置.
override fun finished(i:Int) {
//RecyclerView的LayoutManager
manager.scrollToPositionWithOffset(i,0)
//延迟把View隐藏。
Handler().postDelayed({ tvAlpha.visibility=View.GONE },500)
}
完。