Android如何实现自定义字母选择侧边栏
发表于:2026-11-01 作者:千家信息网编辑
千家信息网最后更新 2026年11月01日,这篇文章将为大家详细讲解有关Android如何实现自定义字母选择侧边栏,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。具体内容如下LetterSideBar.java
千家信息网最后更新 2026年11月01日Android如何实现自定义字母选择侧边栏
这篇文章将为大家详细讲解有关Android如何实现自定义字母选择侧边栏,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。
具体内容如下
LetterSideBar.java
package com.zb.customview.widgets; import android.content.Context;import android.content.res.TypedArray;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.graphics.Rect;import android.text.TextUtils;import android.util.AttributeSet;import android.view.MotionEvent;import android.view.View; import androidx.annotation.Nullable; import com.zb.customview.R; public class LetterSideBar extends View { private Paint mPaint; private int color, selectedColor; private float textSize, spacing; private String mChoosing = "Z"; private OnLetterSelectedListener listener; private int width, height; private String[] LETTERS = new String[] {"#", "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"}; public interface OnLetterSelectedListener { //空表示取消选中 void onSelected(String letter); } public void setOnLetterSelectedListener(OnLetterSelectedListener listener) { this.listener = listener; } public LetterSideBar(Context context) { this(context, null); } public LetterSideBar(Context context, @Nullable AttributeSet attrs) { super(context, attrs); if(null != attrs) { TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.LetterSideBar); color = ta.getColor(R.styleable.LetterSideBar_LetterSideBar_textColor, Color.BLACK); selectedColor = ta.getColor(R.styleable.LetterSideBar_LetterSideBar_textSelectedColor, Color.RED); textSize = ta.getDimensionPixelSize(R.styleable.LetterSideBar_LetterSideBar_textSize, sp2px(12)); spacing = ta.getDimensionPixelSize(R.styleable.LetterSideBar_LetterSideBar_spacing, dp2px(5)); ta.recycle(); } init(); } private void init() { mPaint = new Paint(); mPaint.setAntiAlias(true); mPaint.setColor(color); mPaint.setTextSize(textSize); } @Override protected void onDraw(Canvas canvas) { drawText(canvas); drawSelectedText(canvas, mChoosing); } private void drawText(Canvas canvas) { mPaint.setColor(color); for (int i=0; i= LETTERS.length) return; drawLetterAt(canvas, position, selected); } @Override public boolean onTouchEvent(MotionEvent event) { int action = event.getAction(); switch (action) { case MotionEvent.ACTION_DOWN: case MotionEvent.ACTION_MOVE: float x = event.getX(); float y = event.getY(); if(isTouchInsideView(x, y)) { //触摸在控件内 int position = caculatePosition(y); if(position >= 0 && position < LETTERS.length) { //合规位置 String letter = LETTERS[position]; if(!letter.equals(mChoosing)) { //与选中的不符 去刷新控件 mChoosing = letter; performListener(mChoosing); invalidate(); } } else { //不合规位置 if(null != mChoosing) { mChoosing = null; performListener(mChoosing); invalidate(); } } } else if(null != mChoosing) { //点击事件不在view内部 mChoosing = null; performListener(mChoosing); invalidate();//触摸在view之外 取消选中 } return true; default: if(mChoosing != null) { mChoosing = null; performListener(mChoosing); invalidate(); } break; } return super.onTouchEvent(event); } private void performListener(String letter) { if(null != listener) listener.onSelected(letter); } private boolean isTouchInsideView(float x, float y) { //左右可以适当判断在控件内 if(x >= 0 && x <= width && y >= getPaddingTop() && y < height) return true; return false; } /** * 计算触摸的位置 * @param y * @return */ private int caculatePosition(float y) { float heightWithOutPadding = height - getPaddingTop() - getPaddingBottom(); float eachElementHeight = heightWithOutPadding / LETTERS.length; y -= getPaddingTop(); int position = (int) (y / eachElementHeight); return position; } private void drawLetterAt(Canvas canvas, int position, String letter) { float heightForEach = ((height * 1f - getPaddingTop() - getPaddingBottom()) - (LETTERS.length - 1) * spacing) / LETTERS.length; float spacingInUp = spacing * (position - 1); if(spacingInUp < 0) spacingInUp = 0; float currentTop = getPaddingTop() + (heightForEach * position) + spacingInUp; float currentBottom = currentTop + heightForEach; Paint.FontMetrics fmi = mPaint.getFontMetrics(); float x = (width - getPaddingLeft() - getPaddingRight() - mPaint.measureText(letter)) / 2f + getPaddingLeft(); float baseLine = (fmi.descent + Math.abs(fmi.ascent)) / 2f - fmi.descent; float y = (currentBottom + currentTop) / 2f + baseLine; canvas.drawText(letter, 0, 1, x, y, mPaint); } @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); if(changed) { width = getWidth(); height = getHeight(); } } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int textWidth = (int) (getPaddingLeft() + getPaddingRight() + mPaint.measureText("A")); Rect textBounds = new Rect(); mPaint.getTextBounds("A", 0, 1, textBounds); int singleTextHeight = textBounds.height(); int totalHeight = (int) (27f * singleTextHeight + 26f * spacing) + getPaddingBottom() + getPaddingTop();//26个字母+1个# int widthMode = MeasureSpec.getMode(widthMeasureSpec); int heightMode = MeasureSpec.getMode(widthMeasureSpec); int specWidth = MeasureSpec.getSize(widthMeasureSpec); int specHeight = MeasureSpec.getSize(widthMeasureSpec); int realWidth, realHeight; if(widthMode == MeasureSpec.EXACTLY) { realWidth = specWidth; } else { realWidth = textWidth; } if(heightMode == MeasureSpec.EXACTLY) { realHeight = specHeight; } else { realHeight = totalHeight; } setMeasuredDimension(realWidth, realHeight); } protected int dp2px(int dp) { return (int) (getContext().getResources().getDisplayMetrics().density * dp + 0.5); } protected int sp2px(int sp) { return (int) (getContext().getResources().getDisplayMetrics().scaledDensity * sp + 0.5); }} attrs.xml
layout.xml
代码中使用
sideBar.setOnLetterSelectedListener(new LetterSideBar.OnLetterSelectedListener() { @Override public void onSelected(String letter) { if(TextUtils.isEmpty(letter)) { P.p("取消选中"); letterTxt.setVisibility(View.GONE); } else { P.p("选中" + letter); letterTxt.setText(letter); letterTxt.setVisibility(View.VISIBLE); } } });关于"Android如何实现自定义字母选择侧边栏"这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,使各位可以学到更多知识,如果觉得文章不错,请把它分享出去让更多的人看到。
字母
篇文章
侧边
选择
内容
更多
P.p
不错
实用
代码
位置
控件
文章
知识
参考
帮助
有关
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
山东特亿宝互联网科技有限公司
互联网金融与金融科技
科技与互联网发展
互联网金融 科技金融
唐信互联网科技
成都互联网科技公司
鑫亿盛互联网科技
无线互联网科技
互联网科技logo
上海卓越科技 互联网
银川新华互联网科技学校地址
须眉科技是互联网公司吗
互联网科技大奖都有哪些公司
链环科技传统企业怎么转型互联网
互联网科技和信息
民营互联网公司国防科技
风投北京互联网科技
互联网硬科技公司
珠海东科互联网科技有限公司
三亚科技创新互联网基地
科技平台互联网
科技与互联网
互联网科技会
伴你行互联网科技有限公司
华脉科技工业互联网产品
互联网科技中介
明优互联网科技有限公司
工业互联网展湾科技股份有限公司
广西科技产业互联网是什么
数字互联网科技有限公司