恒美微站 Logo 恒美微站
  • 首页
  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心
  • 联系我们

Android自定义View实现A-Z字母导航栏:触摸事件与列表联动全解析

  • 首页
  • 资讯中心
  • /
  • Android自定义View实现A-Z字母导航栏:触摸事件与列表联动全解析

相关资讯

Back to the Basics: Rethinking Issue-Commit Linking with LLM-Assisted Retrieval 2026/10/18 16:02:17
Android健身房助手:Kotlin+Compose+Room构建记录系统 2026/10/18 16:02:17
FLAC 3D隧道开挖数值模拟:从地应力平衡到分段开挖的完整实践指南 2026/10/18 15:57:17

最新资讯

基于YOLOv8的SAR图像建筑物旋转目标检测与部署实践
Chromium内核设备指纹仿真与环境隔离:浏览器自动化实战指南
Linux命令行开发工具链:Vim、GCC、GDB与Make实战指南
Comsol非厄米超表面非对称单向反射建模:从物理机制到参数调优
Superpowers实战:3步把AI编程助手变成按流程干活的项目员工
Unity UI性能优化实战:Canvas拆分与组件级调优指南

今日推荐

基于GMM的语音识别系统原理与MATLAB实现详解
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

本周热门

基于GMM的语音识别系统原理与MATLAB实现详解
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

本月精选

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证
2026 大模型集体涨价:用 Python 做企业 Token 成本测算与选型避坑(附配置)

Android自定义View实现A-Z字母导航栏:触摸事件与列表联动全解析

发布时间:2026/10/18 16:02:17
Android自定义View实现A-Z字母导航栏:触摸事件与列表联动全解析 简介面向Android应用开发者的自定义View实现资料围绕字母导航栏AlphabetNavigationBar这一典型交互组件讲解从布局设计、字母按钮生成、点击事件监听到与ListView/RecyclerView联动滚动的完整实现思路。适合需要提升列表交互体验、学习自定义控件开发流程的中级开发者。压缩包共977个文件约6.66MB以xml布局/配置、png图片资源、java源码与class编译产物为主同时包含jar库、json配置及可直接安装的apk文件可对照工程结构进行源码阅读与运行调试。目前已收获423人学习/下载。资料提供完整Android Studio工程包含多个版本构建产物和资源文件便于研究自定义View的测量绘制、事件分发以及与列表适配器的联动机制可直接解压导入通过示例工程验证字母索引、平滑滚动、悬浮提示等效果是理解和复用字母导航栏功能的一份实用参考。1. 字母导航栏通讯录右侧那个 A-Z远没有表面那么简单做过通讯录类 App 的人都知道列表右边那一列 A-Z 索引条看着只是 26 个字母画在竖条上真正落地时却牵扯触摸事件分发、绘制性能、字母按位取整、ListView 滚动同步四个环节任何一个环节处理不好用户体验直接就崩了。这个 Android 自定义 View 字母导航栏项目正是把这一整套交互完整实现好的源码包从绘制字母、触摸变色到联动列表滑动、惯性滑动选字母、边界处理全都有覆盖。适合正在做 IM、城市选择、联系人、歌曲列表 App 的 Android 开发者也适合想真正搞懂自定义 View 触摸机制和绘制机制的进阶学习者。它的价值不在于那几个字母画得多好看而在于把事件分发和绘制流程串成了可复用的完整控件。2. 字母导航栏的整体架构先用一个图理清触摸、绘制、回调三条线2.1 控件职责划分为什么不能把逻辑全塞进 onDraw拿到这个源码包第一件事不是去看 onDraw 怎么画字母而是先理清楚整个控件的职责边界。字母导航栏这个控件的核心职责有三个绘制 A-Z 字母、响应触摸事件、把当前按中的字母回调给外部。这三个职责互相独立但又彼此关联源码包里的结构也确实是按这个逻辑拆的。绘制职责集中在 onDraw 和 onSizeChanged 里。onSizeChanged 负责在控件尺寸确定后计算出每个字母的绘制区域包括字母的基准线 baseline、每个字母的 y 坐标、触摸判定区域的上下边界。onDraw 只做一件事根据当前按压位置绘制对应的字母颜色状态。触摸职责集中在 onTouchEvent 里它处理 ACTION_DOWN、ACTION_MOVE、ACTION_UP 三个事件计算当前触摸点对应哪个字母并触发回调。回调职责则是通过一个接口把当前字母传给外部 ListView 或 RecyclerView。这里有一个很重要的设计原则onDraw 里不能做耗时计算触摸事件里不能直接操控列表滑动否则很容易造成卡顿和逻辑耦合。很多初学者会把字母按位取整的逻辑写在 onDraw 里导致每次重绘都算一遍触摸位置对应的字母这是个典型的反面案例。正确做法是 onTouchEvent 里计算好当前字母通知外部列表滑动同时触发 invalidate() 让 onDraw 只负责渲染当前状态。2.2 字母均匀分布的布局算法让 26 个字母在控件里不挤不散字母导航栏看起来简单但字母分布是个容易被忽略的细节。如果直接用高度除以 26 得到每个字母的间隔再把每个字母居中绘制在屏幕高度不够的情况下26 个字母会挤在一起手指按上去根本分不清按的是哪个字母。源码包里采用的方案是按字母列表实际长度做均匀分布。具体做法是在 onSizeChanged 里获取控件高度减去上下 padding再除以 letters.size()得到每个字母占用的 cellHeight。每个字母的中心 y 坐标就是 paddingTop cellHeight * index cellHeight / 2。绘制时通过 Paint 的 FontMetrics 计算 ascent 和 descent得出 baseline 位置确保字母在视觉上垂直居中而不是简单地把 y 坐标对齐到网格中心。Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); mTotalHeight h - getPaddingTop() - getPaddingBottom(); mCellHeight mTotalHeight / mLetters.size(); mItemHeight mTotalHeight / mLetters.size(); }这段代码的关键在于减去了 padding而不是直接用控件高度除以字母数量。如果控件设置了 paddingTop 或 paddingBottom 而没有减去第一个字母和最后一个字母会超出绘制区域呈现被裁切的效果。mCellHeight 是每个字母占用的单元格高度后续 touch 事件判断触摸点落在哪个字母区间时也是用这个值做除法取整。FontMetrics 那块是绘制字母垂直居中的关键很多人直接画的时候发现字母偏上或偏下就是因为没有用 baseline 对齐。baseline 的计算方式是基准线 y 坐标等于字母中心 y 坐标减去 (ascent descent) / 2。之所以不能简单地让字母的 y 坐标加上字体大小的一半是因为不同字体的 ascent 和 descent 比例不同同样的字号有的字体视觉偏上有的偏下必须用 FontMetrics 计算才能做到视觉上的居中。3. 触摸事件分发与字母命中检测手指按下去的那一秒发生了什么3.1 ACTION_DOWN / ACTION_MOVE / ACTION_UP 三分支处理触摸事件处理是整个字母导航栏的灵魂。手指按下、滑动、抬起三个事件的职责完全不同。ACTION_DOWN 里要做的是记录当前触摸的 y 坐标计算出按中的字母 index并触发回调通知外部列表滑动到对应位置。ACTION_MOVE 里做同样的计算但要额外处理手指滑出控件边界的情况。ACTION_UP 里要做的是重置按压状态把当前按中的字母置为 -1并触发 invalidate 让控件恢复默认颜色。从源码包里的 onTouchEvent 实现可以看到它的核心逻辑是抽出 handleTouchEvent 方法统一处理三个事件避免代码重复。每个事件分支里都会调用 invalidate() 触发重新绘制以更新按压颜色。Override public boolean onTouchEvent(MotionEvent event) { final int y (int) event.getY(); int lastIndex mCurrentIndex; mCurrentIndex getIndexByY(y); switch (event.getActionMasked()) { case MotionEvent.ACTION_DOWN: mIsPressed true; break; case MotionEvent.ACTION_MOVE: if (mCurrentIndex ! lastIndex) { if (mOnTouchingLetterChangedListener ! null mCurrentIndex mLetters.size()) { mOnTouchingLetterChangedListener.onTouchingLetterChanged(mLetters.get(mCurrentIndex)); } } break; case MotionEvent.ACTION_UP: mIsPressed false; mCurrentIndex -1; break; default: return super.onTouchEvent(event); } invalidate(); return true; }这里有个关键细节onTouchEvent 的返回值必须是 true。如果返回 false只会在 ACTION_DOWN 时触发一次事件后续的 ACTION_MOVE 和 ACTION_UP 都不会传给这个 View。很多人自定义 View 时踩过这个坑返回值写成了 super.onTouchEvent(event)而父类 View 默认是不消费触摸事件的结果按下去只在手指离开时才响应一次。private int getIndexByY(int y) { int index (int) ((y - getPaddingTop()) / mCellHeight); if (index 0) { index 0; } else if (index mLetters.size() - 1) { index mLetters.size() - 1; } return index; }这个方法是字母命中检测的核心它用触摸点到控件顶部的距离减去 paddingTop再除以单个字母格高度向下取整得到当前字母下标。这里减 paddingTop 是个很容易漏掉的操作如果控件设置了 paddingTop 而忘记减掉手指实际触摸位置和字母判定区间会整体偏移。边界处理是 index 小于 0 时强制归 0大于列表长度时强制归列表末尾防止数组越界。3.2 按压状态绘制变色、背景圆角、当前字母放大怎么协同按压状态的视觉反馈是字母导航栏交互体验的重要一环。源码包的绘制逻辑里当 mIsPressed 为 true 时会绘制一个圆角矩形背景并且当前按中的字母用高亮颜色绘制其他字母用默认颜色。这里需要关注的细节是绘制背景的时机和顺序。背景绘制要放在字母绘制之前否则背景会盖住字母。圆角矩形通过 Paint 设置 Style.FILL再用 drawRoundRect 绘制。绘制字母时根据 index 是否等于 mCurrentIndex 来决定用什么颜色的画笔。源码包里额外做了一个效果按压状态下当前字母放大绘制。这个效果在视觉上很舒服但实现时要注意 Paint 的 textSize 改变后需要重新计算 baseline否则字体会在放大后发生上下偏移。Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); if (mIsPressed) { // 绘制按压背景色注意背景遮罩画在半透明还是全透明上 mPaint.setColor(mBackgroundColor); canvas.drawRoundRect(mBgRect, mBgRadius, mBgRadius, mPaint); } for (int i 0; i mLetters.size(); i) { mPaint.setColor(i mCurrentIndex ? mTextColorPressed : mTextColorNormal); mPaint.setTextSize(i mCurrentIndex ? mTextSizePressed : mTextSizeNormal); // 每次改变 textSize 后要重新计算 baseline float baseline mItemHeight * i mItemHeight / 2 - (mPaint.getFontMetrics().ascent mPaint.getFontMetrics().descent) / 2; canvas.drawText(mLetters.get(i), mCenterX, baseline getPaddingTop(), mPaint); } }这段代码里值得注意的地方是 baseline 的计算。可以看到 baseline 是基于每个字母格的垂直中心点减去字体 ascent 和 descent 平均值得到的。由于每个字母格的高度一致这里用 mItemHeight * i mItemHeight / 2 计算中心点 y 坐标再加上 paddingTop 偏移。画圆角矩形背景时mBgRect 的位置也很讲究它不能是整块控件大小而应该只包裹当前按中的字母那一格通常做法是让背景矩形的高度等于 mItemHeight宽度等于控件宽度减去左右 padding这样视觉上就像高亮显示了当前项。3.3 触摸回调接口设计把当前字母安全地传给 ListView回调接口是这个控件和外部列表通信的桥梁。源码包里定义了一个 OnTouchingLetterChangedListener 接口包含一个方法 onTouchingLetterChanged(String letter)。这个接口在触摸事件中触发外部列表根据收到的字母去查找对应分组的位置然后平滑滚动到该位置。接口设计要注意的是回调时机。ACTION_DOWN 时也要触发回调因为用户在快速滑动时可能手指落下时已经落在某个字母上了如果只在 MOVE 里回调第一次落下到第一个字母时就不会触发。源码包的实现里 ACTION_DOWN 和 ACTION_MOVE 都调用了回调只是 MOVE 里先判断 index 是否变化避免同一个字母反复回调。public interface OnTouchingLetterChangedListener { void onTouchingLetterChanged(String letter); } public void setOnTouchingLetterChangedListener(OnTouchingLetterChangedListener listener) { this.mOnTouchingLetterChangedListener listener; }外部使用时的典型做法是在 Activity 或 Fragment 里实现这个接口拿到字母后遍历数据源找到第一个以该字母开头或所属分组等于该字母的数据项然后调用 ListView 的 setSelection 或 RecyclerView 的 scrollToPositionWithOffset 完成联动。这里有一个优化建议数据量大时不要在主线程遍历查找把数据源按字母分组缓存到 HashMap 中key 是字母value 是起始 position回调时直接查表即可O(1) 复杂度就能定位。4. 联动与性能优化从能用到好用之间隔着一整层细节4.1 数据分组与索引映射HashMap 缓存起始位置避免每次遍历列表联动要达到流畅效果不能每次触摸都在几千条数据里线性查找。源码包里虽然主控件没有内置数据分组逻辑但它预留了接口让外部自己处理。实际项目中我一般会用 HashMap 把数据按首字母分组启动时遍历一次数据源记录每个字母在列表中的起始位置。具体做法是这样的先对数据源做一次排序确保相同首字母的数据聚在一起然后遍历时检测当前项的首字母是否和前一项相同如果不同就把当前位置和当前字母放入 HashMap。private void buildLetterPositionMap(ListUserInfo dataList) { mLetterPositionMap.clear(); for (int i 0; i dataList.size(); i) { String letter getFirstLetter(dataList.get(i).getName()); if (!mLetterPositionMap.containsKey(letter)) { mLetterPositionMap.put(letter, i); } } }这样在回调接口里直接查表Override public void onTouchingLetterChanged(String letter) { if (mLetterPositionMap.containsKey(letter)) { int position mLetterPositionMap.get(letter); mListView.setSelection(position); } }这个方案有几个注意点。一是汉字转拼音需要引入转拼音库这里建议在数据入库时就存好拼音首字母字段而不是运行时每次转换因为运行时转换在列表滚动时要反复计算卡顿严重。二是字母导航栏的字母列表要有序且和数据源的字母集合一一对应否则会出现按了 B 但数据里没有 B 开头的项列表不响应的情况。4.2 invalidate 的频率控制避免高频触摸时频繁重绘导致的卡顿字母导航栏有个性能隐患手指在 A-Z 之间快速滑动时如果每移动一个像素就触发一次 invalidate会造成频繁重绘。onDraw 里虽然有 26 个字母要画数量不大但如果项目的控件复杂、背景模糊或有阴影效果时重绘开销会明显上升。源码包里的处理思路是只在字母 index 变化时才触发 invalidate而不是每个 MOVE 事件都重绘。可以看到代码里 ACTION_MOVE 分支先判断了 mCurrentIndex ! lastIndex只有 index 真正变化时才回调并重绘。这个优化虽然简单但收益很高一次手指快速滑动从 A 到 Z中间可能产生上百个 MOVE 事件但 index 变化只有 25 次重绘次数从上百次降到了二十多次节省了大量绘制时间。除了这个基础优化还可以在 index 变化时只刷新当前字母所在区域用 invalidate 带四个参数的重载方法只重绘变化的那一格进一步减少绘制面积。不过这个优化的前提是 onDraw 里的绘制逻辑能针对局部区域做裁剪否则只调用局部刷新但绘制时还是全量绘制就没有意义了。4.3 触摸事件和列表滚动的冲突为什么 ListView 会抢事件字母导航栏和 ListView 叠在一起时事件分发会产生冲突。ListView 本身是支持纵向滑动的手指按在字母导航栏上滑动时ListView 也想响应这个滑动手势如果处理不当会出现按着字母导航栏滑动时列表也跟着滚动或者字母导航栏收不到 MOVE 事件的情况。解决冲突的核心思路是让字母导航栏消费掉所有触摸事件不让事件继续传给 ListView。实现上就是 onTouchEvent 返回 true 并拦截事件。只要触摸起点落在字母导航栏内部后续的事件流就全部交给它处理ListView 拿不到事件自然不会滚动。但这里有个坑字母导航栏如果宽度设置得不够宽比如只刚好包裹住字母的宽度用户手指很容易滑出字母导航栏的边界一旦滑出边界事件就被父容器接管列表就会突然滚动体验很差。解决方案有两种一是在触摸事件里处理滑出边界的情况仍然消费事件直到手指抬起二是把字母导航栏的可点击区域扩大实际绘制字母的区域占控件宽度的 60% 左右剩下的 40% 作为触摸热区。源码包里用的是第二种方案布局时给控件设置了一个合理的宽度同时在触摸判定时不限制 x 坐标的范围只要事件被分发到这个 View就按 y 坐标计算命中字母不关心 x 坐标。Override public boolean onTouchEvent(MotionEvent event) { // 不判断 event.getX() 是否在控件范围内只要事件进来了就消费 final int y (int) event.getY(); switch (event.getActionMasked()) { case MotionEvent.ACTION_DOWN: mIsPressed true; ... break; ... } return true; }这是整个触摸处理里极易被忽略的一点。很多初版实现会加一句 if (event.getX() mWidth) 之类的判断看似有边界保护实际上因为手指滑出边界后事件依然会继续派发给这个 View加了 x 坐标判断反而会导致手指滑出后控件立刻失去响应UP 事件也拿不到了。5. 字母导航栏常见问题排查五个实操中会翻车的细节5.1 坑一手指按下去字母不变色抬起才变色现象字母导航栏触摸按下后没有反应手指移开后才出现颜色变化或者是松开后才跳到对应字母。原因多半是 onTouchEvent 的返回值写错了返回了 false 或者 super.onTouchEvent(event)。事件机制里如果 onTouchEvent 返回 false表示这个 View 不消费此次触摸事件系统不会再分发后续的 MOVE 和 UP 事件给它。结果就是 ACTION_DOWN 时没有触发回调ACTION_UP 时系统补发了一个 DOWN 事件看起来就像松开才变色。解决检查 onTouchEvent 的返回值确认是 return true。调试时可以在三个事件分支里各打一条 Log确认事件是否按预期到达。如果 DOWN 只触发一次、MOVE 完全没有输出那一定是返回值的问题。5.2 坑二最后一个字母点不到第一个字母位置偏移现象触摸最底部的字母 Z 时没有反应或触摸顶部第一个字母 A 时命中位置偏下。原因onSizeChanged 里计算 mTotalHeight 时忘了减掉 paddingTop 和 paddingBottom。字母格的分布是从 paddingTop 开始算的但如果 mTotalHeight 等于控件总高度实际绘制时最后一个字母的中心点加上字体高度已经超出控件底部导致按不到的假象。第一个字母偏移同理getIndexByY 时触摸 y 坐标减了 paddingTop但如果不减手指位置和字母位置对不上。解决严格按照 getPaddingTop 和 getPaddingBottom 来计算 mTotalHeightgetIndexByY 里也必须减 paddingTop。如果布局里没设置 padding这块逻辑不会出错但一旦设置了 padding 就全乱了。5.3 坑三滑动与 ListView 联动时列表不滚动或跳位现象手指在字母导航栏上滑动ListView 没有跟着滑动或者跳到了错误的分组。原因回调方法里拿到字母后做了耗时操作比如遍历几千条数据找 position导致主线程卡顿触摸事件处理被延迟。另外如果 ListView 没有开启快速滚动调用 setSelection 后可能没有动画效果视觉上比较生硬但不至于不滚动。跳位的情况通常是数据没有按首字母排序首字母相同的项没有聚在一起按位置跳转时自然就错位了。解决用 HashMap 缓存字母到起始位置的映射回调里只做查表和 setSelection。数据源要确保有序最好在数据层完成排序UI 层不做排序操作。另外用 RecyclerView 的话注意 scrollToPositionWithOffset 方法要传 offset 参数为 0否则会保留上次偏移导致跳位。5.4 坑四按压背景圆角矩形位置对不上字母现象按压时高亮背景和当前字母不在同一水平位置背景偏上或偏下。原因绘制背景矩形的 top 坐标计算和字母的 baseline 计算使用了不同的参考系。字母中心 y 坐标是基于 cellHeight 的整数倍加上 paddingTop 算出来的背景矩形如果用的是另一种算法比如用 getHeight() 直接乘比例就会出现错位。解决背景矩形的 top 和 bottom 也要基于同一个 mItemHeight 计算。top mItemHeight * index paddingTop 少许间距bottom top mItemHeight - 少许间距。绘制背景的代码和绘制字母的代码用同一套坐标源不要各自为政。5.5 坑五触摸事件和外部手势冲突列表无响应现象加了字母导航栏之后ListView 本身的滑动变得不流畅或者字母导航栏触摸区域过大挡住了列表的滑动。原因字母导航栏的布局宽度设置过宽把可点击区域铺满了整个列表右侧用户想在列表区滑动却点在了导航栏上事件被导航栏消费了。另一种情况是字母导航栏的父容器做了事件拦截导致导航栏收不到事件。解决字母导航栏的布局宽度控制在 30dp 到 60dp 之间既能方便手指触摸又不会占太多列表空间。如果触摸区域确实偏大可以用 clipChildren 或触摸热区控制重写 onTouchEvent 里的 DOWN 判断如果 x 坐标在控件右边 60% 以外就不消费事件返回 false 并把事件还给父容器。但要注意这么写之后手指从字母区滑出到列表区时后续事件依然会走导航栏需要处理好事件流。6. 进阶玩法与验证方法把触摸反馈画在屏幕中央并验证完整链路字母导航栏做到能和列表联动基本功能就算闭环了。但实际产品里很多 App 在手指按住字母时会弹出一个居中的大字母气泡显示当前按中的字母松手后消失。这个效果代码量很少但给用户的反馈感提升非常明显。实现思路有两种一是自定义一个独立的 BubbleView用 WindowManager 把它添加到屏幕中央监听导航栏的回调更新显示二是直接把气泡画在导航栏控件自己的 onDraw 里让它在控件上方绘制。但第二种方案有个先天缺陷View 的绘制范围默认是自身边界超出边界的内容会被裁剪要么关闭 setClipChildren 要么就得把气泡画在控件内部空间里会在窄条上挤占空间效果不好。我一般采用的是 WindowManager 方案代码结构上是这样的。private void showBubble(String letter) { if (mBubbleView null) { mBubbleView new TextView(getContext()); mBubbleView.setTextColor(Color.WHITE); mBubbleView.setTextSize(30); mBubbleView.setGravity(Gravity.CENTER); mBubbleView.setBackgroundResource(R.drawable.bg_bubble); WindowManager.LayoutParams params new WindowManager.LayoutParams( dp2px(90), dp2px(90), WindowManager.LayoutParams.TYPE_APPLICATION_PANEL, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, PixelFormat.TRANSLUCENT); params.gravity Gravity.CENTER; mWindowManager.addView(mBubbleView, params); } mBubbleView.setText(letter); } private void hideBubble() { if (mBubbleView ! null) { mWindowManager.removeViewImmediate(mBubbleView); mBubbleView null; } }这段代码有两个细节值得记录。第一是 WindowManager.LayoutParams 的 type 要选 TYPE_APPLICATION_PANEL这样气泡不会出现在其他应用之上也不需要申请悬浮窗权限。第二是 FLAG_NOT_FOCUSABLE 这个标志位必须加上否则气泡会抢占焦点导致导航栏收不到后续的触摸事件。这个坑我踩过一次当时加了气泡后导航栏只响应第一次按下后续滑动全部失效查了半天才发现是焦点被抢走了。说完气泡再给一套完整的验证路径。代码合入之前我建议按这个顺序手动测一遍完整链路第一步验证绘制正确性。打开 App 让导航栏正常显示A-Z 字母是否均匀分布、无重叠、无裁切底部 Z 是否完整可见。然后用开发者选项里的显示布局边界确认字母中心线和触摸区域对齐。第三步验证联动准确性按住 A 松手看列表是否到顶部按住 Z 列表是否到底部。然后从 A 快速滑动到 Z 再松手看列表是否中途出现闪跳。如果有闪跳回到 HashMap 分组逻辑排查数据源是否有序。整个链路走一遍之后这个字母导航栏控件才算真正可用。从那以后我每次把字母导航栏接到新项目里都会强制走一遍上面的验证流程尤其是气泡焦点抢占那个点因为那个是最隐蔽的功能正常、气泡正常只有当你手指滑到第二个字母的时候才猛然发现导航栏失灵了。希望这个控件和这些排查思路能帮你少走几趟弯路。希望帮到你。本文还有配套的精品资源点击获取

关于恒美微站

恒美微站专注于为个体商户、工作室提供极简自助建站服务,让每个人都能轻松拥有专业网站。

快速链接

  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心

服务项目

  • 可视化建站
  • 拖拽编辑
  • 主题定制
  • SEO 优化
  • 网站托管

联系方式

  • 📍 地址:北京市朝阳区建国路 88 号
  • 📞 电话:400-888-8888
  • ✉️ 邮箱:info@hmyw.cn
  • 🕐 时间:周一至周日 9:00-18:00

© 2024 恒美微站 hmyw.cn 版权所有 | 京 ICP 备 12345678 号