自定义view之简单实现字母索引列表
程序员文章站
2022-04-03 16:02:07
自定义view之简单实现字母索引列表效果思路大体可分为两部分,一个是中间显示的英文字符,一个是右侧的字母索引列表,通过自定义view方法,计算每个字母的高度,然后依次绘制,通过触碰,绘制中心显示的文字,最后通过handler延时操作使其消失代码import android.annotation.SuppressLint;import android.content.Context;import android.graphics.Canvas;import android.graphics....
自定义view之简单实现字母索引列表
效果
思路
大体可分为两部分,一个是中间显示的英文字符,一个是右侧的字母索引列表,通过自定义view方法,计算每个字母的高度,然后依次绘制,通过触碰,绘制中心显示的文字,最后通过handler延时操作使其消失
代码
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Handler;
import android.os.Looper;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.MotionEvent;
import android.view.View;
import androidx.annotation.Nullable;
public class LetterSideBar extends View {
private Paint paint = new Paint();
private Paint tempPaint = new Paint();
private boolean isTouch = false;
// 定义26个字母
public static String[] mLetters = {"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 String mCurrentTouchLetter;
private int currentPos;
int textWidth = (int) paint.measureText("A");
public LetterSideBar(Context context) {
this(context,null);
}
public LetterSideBar(Context context, @Nullable AttributeSet attrs) {
this(context, attrs,0);
}
public LetterSideBar(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
paint.setAntiAlias(true);
paint.setTextSize(sp2px(20));
paint.setColor(Color.BLUE);
}
//sp转px
private float sp2px(int sp){
return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,
sp, getResources().getDisplayMetrics());
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
@Override
protected void onDraw(Canvas canvas) {
int itemHeight = (getHeight() - getPaddingTop() - getPaddingBottom()) / mLetters.length;
for (int i = 0 ; i < mLetters.length ;i++){
int letterCenterY = i * itemHeight + itemHeight / 2 + getPaddingTop();
Paint.FontMetrics fontMetrics = paint.getFontMetrics();
int dy = (int) ((fontMetrics.bottom - fontMetrics.top) / 2 - fontMetrics.bottom);
int baseLine = letterCenterY + dy;
int textWidth = (int) paint.measureText(mLetters[i]);
int x = getWidth()/2 - textWidth/2;
int dis =0;
if (Math.abs(i - currentPos) < 3 && isTouch){
dis = 60-Math.abs(i - currentPos) * 20;
}
if (mLetters[i].equals(mCurrentTouchLetter)){
paint.setColor(Color.RED);
}else {
paint.setColor(Color.BLUE);
}
drawCenter(mCurrentTouchLetter,canvas,isTouch);
canvas.drawText(mLetters[i], x+getWidth()/2-getPaddingRight()-dis, baseLine, paint);
}
}
private void drawCenter(final String mLetter, final Canvas canvas, boolean isTouch) {
canvas.save();
if (isTouch){
tempPaint.setColor(Color.BLUE);
tempPaint.setTextSize(sp2px(40));
tempPaint.setAntiAlias(true);
canvas.drawCircle(getWidth()/2,getHeight()/2,getWidth()/5,tempPaint);
tempPaint.setColor(Color.WHITE);
Paint.FontMetrics fontMetrics = tempPaint.getFontMetrics();
int dy = (int) ((fontMetrics.bottom - fontMetrics.top) / 2 - fontMetrics.bottom);
final int baseLine = getHeight()/2 + dy;
int textWidth = (int) paint.measureText(mLetter);
final int x = getWidth()/2 - textWidth;
canvas.drawText(mLetter,x,baseLine,tempPaint);
canvas.restore();
}else {
canvas.restore();
}
}
Handler handler=new Handler(Looper.getMainLooper());
@SuppressLint("ClickableViewAccessibility")
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()){
case MotionEvent.ACTION_MOVE:
case MotionEvent.ACTION_DOWN:
float currentY = event.getY();
float currentX = event.getX();
if (currentX > getWidth() - getPaddingRight() -textWidth-getPaddingLeft() -60){
int itemHeight = (getHeight() - getPaddingTop() -getPaddingBottom()) / mLetters.length;
currentPos = (int) (currentY / itemHeight);
if (currentPos < 0){
currentPos = 0;
}
if (currentPos > mLetters.length -1){
currentPos = mLetters.length -1;
}
mCurrentTouchLetter = mLetters[currentPos];
isTouch = true;
invalidate();
handler.postDelayed(new Runnable() {
@Override
public void run() {
isTouch = false;
invalidate();
}
},2000);
}
break;
default:
break;
}
return true;
}
}
本文地址:https://blog.csdn.net/wu_zixuan97/article/details/108712663