zoukankan      html  css  js  c++  java
  • 城市导航列表

    先看实现的效果图如下:

    左侧的列表根据拼音自动排序,支持头部悬停,点击Item会提示选择的城市;右侧是一个快速导航栏,点击字母会提示选择的字母,左侧列表会滑动到对应位置,支持导航栏快速滑动。

     

    OK,整体效果就是这样,真机测试也挺流畅,一起看看怎么实现这个炫酷的城市导航列表。

     

    1数据准备 

    1.1构建城市实体类 

     

    假如服务器返回的是一堆杂乱无章的城市数据,我们需要对这些数据根据拼音的先后顺序进行排序。对应的实体类如下:

    cityPinyin代表城市名称的拼音,cityName代表城市名称,firstPinYin则代表城市拼音的第一个字母,也就是索引。

     

    1.2 将汉字转换为拼音 

     

    这里我用的是TinyPinyin,一个适用于Java和Android的快速、低内存占用的汉字转拼音库。TinyPinyin的特点有:生成的拼音不包含声调,也不处理多音字,默认一个汉字对应一个拼音;拼音均为大写;无需初始化,执行效率很高(Pinyin4J的4倍);很低的内存占用(小于30KB)。

     

    使用起来也很简单:

     

    比如传入一个汉字“安庆”,返回的结果就是“ANQING”

     

    1.3 根据拼音进行排序 

     

    这里用的是java中的compareto方法,返回参与比较的前后两个字符串的asc码的差值,举个栗子: 

    若a=”b”,b=”a”,输出1; 
    若a=”abcdef”,b=”a”输出5; 
    若a=”abcdef”,b=”ace”输出-1;

     即参与比较的两个字符串如果首字符相同,则比较下一个字符,直到有不同的为止,返回该不同的字符的asc码差值。

    1 public class PinyinComparator implements Comparator<City> {
    2     @Override
    3     public int compare(City cityFirst, City citySecond) {
    4         return cityFirst
    5                 .getCityPinyin()
    6                 .compareTo(citySecond.getCityPinyin());
    7     }
    8 }

    使用的时候实现Comparator接口,传入需要比较的实体类,然后将返回值作为 Collections.sort(cityList, pinyinComparator)中的第二个参数,Collections.sort方法会根据这个传入的int值对cityList进行排序。

     

     

    2自定义快速导航栏   

     

    2.1 重写onDraw()方法 

     

    右侧快速导航栏是一个自定义View,这里重点说一下onDraw()方法。

    这里的pinyinList是去除重复的,按照A-Z顺序排列的字母索引集合。遍历这个集合,依次绘制出这些字母。在 i 等于 position -1(点击触摸的位置)的时候,将字体颜色设置为红色,否则字体颜色为白色。这一点在演示动态图中有所体现,触摸点击的字体颜色会改变。

     

    2.2 重写onTouchEvent()方法

    case MotionEvent.ACTION_DOWN:设置背景颜色,设置字体初始高度,计算触摸位置,调用invalidate()进行重绘; 

    case MotionEvent.ACTION_MOVE:与ACTION_DOWN一样的操作,加上一个判断,让滑动的距离大于默认的最小滑动距离才设置滑动有效; 
    case MotionEvent.ACTION_UP:设置背景颜色,设置字体初始高度,将position设置为0,进行重置操作,调用invalidate()进行重绘;

     

    2.3 触摸监听

     

    屏幕中间是一个自定义的圆形TextView,默认设置为View.GONE,触摸的时候设置为View.VISIBLE,并将TextView的值设置为点击触摸的字母。因此我们的接口设计如下:

    1 public interface onTouchListener {
    2     void showTextView(String textView, boolean dismiss);
    3 }

    在MotionEvent.ACTION_DOWN与MotionEvent.ACTION_MOVE的时候:

    1 listener.showTextView(selectTxt, false);

    在MotionEvent.ACTION_UP的时候:

    1 listener.showTextView(selectTxt, true);

    然后让Activity实现该接口,通过传过来的boolean值控制圆形TextView是否显示:

    点击触摸的同时,需要让recyclerView滑动到对应的位置。遍历cityList数组,得到拼音的第一个字母,与传递过来的索引字母进行对比,相等则将 

    i 设置为selectPosition。最后调用recyclerView.scrollToPosition()方法,滑动到对应的位置,达到索引导航的作用。

     

    3RecyclerView的悬停实现   

     

    3.1 布局文件 

     

    头部布局:layout_sticky_header_view.xml,也就是示例图中红色的部分,里面

    包含一个索引字母TextView 

    主界面的布局:一共两层,头部布局覆盖在RecyclerView上面

    子item的布局:线性布局竖直排列,上面引入头部布局,下面为显示城市名字的布局

     

    3.2 构建CityAdapter

    这里重点说一下onBindViewHolder这个方法:

     

    每一个RecyclerView的item的布局里面都包含一个头部布局,然后判断当前item和上一个item的头部布局里的索引字母是否相同,来决定是否展示item的头部布局。

    第一个item的头部布局是显示的,设置为View.VISIBLE,标记tag为FIRST_STICKY_VIEW; 
    item布局中,索引字母不相同的头部布局是显示的,设置为View.VISIBLE,标记tag为HAS_STICKY_VIEW; 
    item布局中,索引字母相同的头部布局是隐藏的,设置为View.GONE,标记tag为NONE_STICKY_VIEW;

    最后为每一个item设置一个ContentDescription ,用来记录并获取头部布局展示的信息。

     

    3.3 RecyclerView的滑动监听

     

    主界面的布局中,最上层有一个头部布局tvStickyHeaderView,通过监听RecyclerView的滚动,根据RecyclerView的滚动距离,决定头部布局向上或者向下滚动的距离,实现悬停效果:


    1. 第一次调用RecyclerView的findChildViewUnder()方法,返回指定位置的childView,这里也就是item的头部布局,因为我们的tvStickyHeaderView展示的肯定是最上面item的头部布局里的索引字母信息。 

    2. 第二次调用RecyclerView的findChildViewUnder()方法,这里返回的是固定在屏幕上方那个tvStickyHeaderView下面一个像素位置的RecyclerView的item,根据这个item来更新tvStickyHeaderView要translate多少距离。 

    3. 如果tag为HAS_STICKY_VIEW,表示当前item需要展示头部布局,那么根据这个item的getTop和tvStickyHeaderView的高度相差的距离来滚动tvStickyHeaderView;如果tag为NONE_STICKY_VIEW,表示当前item不需要展示头部布局,那么就不会引起tvStickyHeaderView的滚动。

    最后使用接口回调处理RecyclerView的点击事件即可。由于篇幅有限,这里就只介绍了一些重点。项目完整源码已经上传到我的github上:

     

  • 相关阅读:
    Unity3D之Character Controller(CC)与GameObject的碰撞方法
    Unity3D之资源问题处理
    Unity3D之多个fbx导入场景, 合并多个动画
    Unity3D性能优化--- 收集整理的一堆
    批量删除
    Unity3D插件之Easy Touch 3.1(1): Easy Joystick
    Unity3D与iOS消息交互方法(1)--iOS接收Unity3D发出的消息
    爬虫 requests 模块
    Flask 模型操作
    11.4 Flask session,闪现
  • 原文地址:https://www.cnblogs.com/huolongluo/p/6340831.html
Copyright © 2011-2022 走看看