实现这样的效果

布局:
  1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  2. xmlns:tools="http://schemas.android.com/tools"
  3. android:layout_width="match_parent"
  4. android:layout_height="match_parent"
  5. tools:context=".MainActivity" >
  6. <ListView
  7. android:id="@+id/lv_main"
  8. android:layout_width="match_parent"
  9. android:layout_height="match_parent" >
  10. </ListView>
  11. <com.itheima.quickindex.ui.QuickIndexBar
  12. android:id="@+id/bar"
  13. android:layout_width="30dp"
  14. android:layout_height="match_parent"
  15. android:layout_alignParentRight="true"
  16. android:background="#ff0000" />
  17. <TextView
  18. android:id="@+id/tv_center"
  19. android:layout_width="160dp"
  20. android:layout_height="100dp"
  21. android:background="@drawable/bg_index"
  22. android:gravity="center"
  23. android:textSize="32sp"
  24. android:visibility="gone"
  25. android:textColor="#ffffff"
  26. android:layout_centerInParent="true"
  27. android:text="A" />
  28. </RelativeLayout>

字的shape:
  1. <shape xmlns:android="http://schemas.android.com/apk/res/android"
  2. android:shape="rectangle" >
  3. <solid android:color="#66000000"/>
  4. <corners android:radius="20dp"/>
  5. </shape>
QuickIndexBar

  1. /**
  2. * 快速索引
  3. *
  4. * 用于根据字母快速定位联系人
  5. * @author poplar
  6. *
  7. */
  8. public class QuickIndexBar extends View {
  9. private static final String[] LETTERS = new String[]{
  10. "A", "B", "C", "D", "E", "F",
  11. "G", "H", "I", "J", "K", "L",
  12. "M", "N", "O", "P", "Q", "R",
  13. "S", "T", "U", "V", "W", "X",
  14. "Y", "Z"};
  15. private static final String TAG = "TAG";
  16. private Paint mPaint;
  17. private int cellWidth;
  18. private float cellHeight;
  19. /**
  20. * 暴露一个字母的监听,交给main执行
  21. */
  22. public interface OnLetterUpdateListener{
  23. void onLetterUpdate(String letter);
  24. }
  25. private OnLetterUpdateListener listener;
  26. public OnLetterUpdateListener getListener() {
  27. return listener;
  28. }
  29. /**
  30. * 设置字母更新监听
  31. * @param listener
  32. */
  33. public void setListener(OnLetterUpdateListener listener) {
  34. this.listener = listener;
  35. }
  36. public QuickIndexBar(Context context) {
  37. this(context, null);
  38. }
  39. public QuickIndexBar(Context context, AttributeSet attrs) {
  40. this(context, attrs, 0);//这样写,只需要在三个参数的构造函数初始化就可以了
  41. }
  42. public QuickIndexBar(Context context, AttributeSet attrs, int defStyle) {
  43. super(context, attrs, defStyle);
  44. mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
  45. mPaint.setColor(Color.WHITE);
  46. mPaint.setTypeface(Typeface.DEFAULT_BOLD);//当点中的时候变粗
  47. }
  48. @Override
  49. protected void onDraw(Canvas canvas) {
  50. for (int i = 0; i < LETTERS.length; i++) {
  51. String text = LETTERS[i];
  52. // 计算坐标
  53. int x = (int) (cellWidth / 2.0f - mPaint.measureText(text) / 2.0f);//先转成float再转成int,因为有可能丢失精度
  54. // 获取文本的高度
  55. Rect bounds = new Rect();// 矩形
  56. mPaint.getTextBounds(text, 0, text.length(), bounds);//字是矩形,通过矩形获得高
  57. int textHeight = bounds.height();
  58. int y = (int) (cellHeight / 2.0f + textHeight / 2.0f + i * cellHeight);
  59. // 根据按下的字母, 设置画笔颜色
  60. mPaint.setColor(touchIndex == i ? Color.GRAY : Color.WHITE);
  61. // 绘制文本A-Z
  62. canvas.drawText(text, x, y, mPaint);
  63. }
  64. }
  65. int touchIndex = -1;
  66. @Override
  67. public boolean onTouchEvent(MotionEvent event) {
  68. int index = -1;
  69. switch (MotionEventCompat.getActionMasked(event)) {
  70. case MotionEvent.ACTION_DOWN:
  71. // 获取当前触摸到的字母索引
  72. index = (int) (event.getY() / cellHeight);
  73. if(index >= 0 && index < LETTERS.length){
  74. // 判断是否跟上一次触摸到的一样
  75. if(index != touchIndex) {
  76. if(listener != null){
  77. listener.onLetterUpdate(LETTERS[index]);
  78. }
  79. Log.d(TAG, "onTouchEvent: " + LETTERS[index]);
  80. touchIndex = index;
  81. }
  82. }
  83. break;
  84. case MotionEvent.ACTION_MOVE:
  85. index = (int) (event.getY() / cellHeight);
  86. if(index >= 0 && index < LETTERS.length){
  87. // 判断是否跟上一次触摸到的一样
  88. if(index != touchIndex){
  89. if(listener != null){
  90. listener.onLetterUpdate(LETTERS[index]);
  91. }
  92. Log.d(TAG, "onTouchEvent: " + LETTERS[index]);
  93. touchIndex = index;
  94. }
  95. }
  96. break;
  97. case MotionEvent.ACTION_UP:
  98. touchIndex = -1;
  99. break;
  100. default:
  101. break;
  102. }
  103. invalidate();
  104. return true;
  105. }
  106. @Override
  107. protected void onSizeChanged(int w, int h, int oldw, int oldh) {
  108. super.onSizeChanged(w, h, oldw, oldh);
  109. // 获取单元格的宽和高
  110. cellWidth = getMeasuredWidth();
  111. int mHeight = getMeasuredHeight();
  112. cellHeight = mHeight * 1.0f / LETTERS.length;
  113. }
  114. }
PinyinUtils
  1. public class PinyinUtils {
  2. /**
  3. * 根据传入的字符串(包含汉字),得到拼音
  4. * 黑马 -> HEIMA
  5. * 黑 马*& -> HEIMA
  6. * 黑马f5 -> HEIMA
  7. * @param str 字符串
  8. * @return
  9. */
  10. public static String getPinyin(String str) {
  11. HanyuPinyinOutputFormat format = new HanyuPinyinOutputFormat();
  12. format.setCaseType(HanyuPinyinCaseType.UPPERCASE);
  13. format.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
  14. StringBuilder sb = new StringBuilder();
  15. char[] charArray = str.toCharArray();
  16. for (int i = 0; i < charArray.length; i++) {
  17. char c = charArray[i];
  18. // 如果是空格, 跳过
  19. if(Character.isWhitespace(c)){
  20. continue;
  21. }
  22. if(c >= -127 && c < 128){
  23. // 肯定不是汉字
  24. sb.append(c);
  25. }else {
  26. String s = "";
  27. try {
  28. // 通过char得到拼音集合. 单 -> dan, shan
  29. s = PinyinHelper.toHanyuPinyinStringArray(c, format)[0];
  30. sb.append(s);
  31. } catch (BadHanyuPinyinOutputFormatCombination e) {
  32. e.printStackTrace();
  33. sb.append(s);
  34. }
  35. }
  36. }
  37. return sb.toString();
  38. }
  39. }
Person
  1. public class Person implements Comparable<Person>{//实现比较功能
  2. private String name;
  3. private String pinyin;
  4. public Person(String name) {
  5. super();
  6. this.name = name;
  7. this.pinyin = PinyinUtils.getPinyin(name);
  8. }
  9. public String getName() {
  10. return name;
  11. }
  12. public void setName(String name) {
  13. this.name = name;
  14. }
  15. public String getPinyin() {
  16. return pinyin;
  17. }
  18. public void setPinyin(String pinyin) {
  19. this.pinyin = pinyin;
  20. }
  21. @Override
  22. public int compareTo(Person another) {
  23. return this.pinyin.compareTo(another.getPinyin());
  24. }
  25. }
adapter布局
  1. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  2. android:layout_width="match_parent"
  3. android:layout_height="match_parent"
  4. android:orientation="vertical" >
  5. <TextView
  6. android:id="@+id/tv_index"
  7. android:layout_width="match_parent"
  8. android:layout_height="40dp"
  9. android:background="#888888"
  10. android:gravity="center_vertical"
  11. android:paddingLeft="20dp"
  12. android:text="A"
  13. android:textColor="#ffffff"
  14. android:textSize="20sp" />
  15. <TextView
  16. android:id="@+id/tv_name"
  17. android:layout_width="match_parent"
  18. android:layout_height="50dp"
  19. android:gravity="center_vertical"
  20. android:paddingLeft="20dp"
  21. android:text="宋江"
  22. android:textSize="24sp" />
  23. </LinearLayout>
HaoHanAdapter
  1. public class HaoHanAdapter extends BaseAdapter {
  2. private Context mContext;
  3. private ArrayList<Person> persons;
  4. public HaoHanAdapter(Context mContext, ArrayList<Person> persons) {
  5. this.mContext = mContext;
  6. this.persons = persons;
  7. }
  8. @Override
  9. public int getCount() {
  10. // TODO Auto-generated method stub
  11. return persons.size();
  12. }
  13. @Override
  14. public Object getItem(int position) {
  15. return persons.get(position);
  16. }
  17. @Override
  18. public long getItemId(int position) {
  19. return position;
  20. }
  21. @Override
  22. public View getView(int position, View convertView, ViewGroup parent) {
  23. View view = convertView;
  24. if(convertView == null){
  25. view = view.inflate(mContext, R.layout.item_list, null);
  26. }
  27. ViewHolder mViewHolder = ViewHolder.getHolder(view);
  28. Person p = persons.get(position);
  29. String str = null;
  30. String currentLetter = p.getPinyin().charAt(0) + "";
  31. // 根据上一个首字母,决定当前是否显示字母
  32. if(position == 0){
  33. str = currentLetter;
  34. }else {
  35. // 上一个人的拼音的首字母
  36. String preLetter = persons.get(position - 1).getPinyin().charAt(0) + "";
  37. if(!TextUtils.equals(preLetter, currentLetter)){
  38. str = currentLetter;
  39. }
  40. }
  41. // 根据str是否为空,决定是否显示索引栏
  42. mViewHolder.mIndex.setVisibility(str == null ? View.GONE : View.VISIBLE);
  43. mViewHolder.mIndex.setText(currentLetter);
  44. mViewHolder.mName.setText(p.getName());
  45. return view;
  46. }
  47. static class ViewHolder {
  48. TextView mIndex;
  49. TextView mName;
  50. public static ViewHolder getHolder(View view) {//了解这种写法
  51. Object tag = view.getTag();
  52. if(tag != null){
  53. return (ViewHolder)tag;
  54. }else {
  55. ViewHolder viewHolder = new ViewHolder();
  56. viewHolder.mIndex = (TextView) view.findViewById(R.id.tv_index);
  57. viewHolder.mName = (TextView) view.findViewById(R.id.tv_name);
  58. view.setTag(viewHolder);
  59. return viewHolder;
  60. }
  61. }
  62. }
  63. }
MainActivity
  1. public class MainActivity extends Activity {
  2. private ListView mMainList;
  3. private ArrayList<Person> persons;
  4. private TextView tv_center;
  5. @Override
  6. protected void onCreate(Bundle savedInstanceState) {
  7. super.onCreate(savedInstanceState);
  8. setContentView(R.layout.activity_main);
  9. QuickIndexBar bar = (QuickIndexBar) findViewById(R.id.bar);
  10. // 设置监听,和回调一个意思
  11. bar.setListener(new OnLetterUpdateListener() {
  12. @Override
  13. public void onLetterUpdate(String letter) {
  14. // Utils.showToast(getApplicationContext(), letter);
  15. showLetter(letter);
  16. // 根据字母定位ListView, 找到集合中第一个以letter为拼音首字母的对象,得到索引
  17. for (int i = 0; i < persons.size(); i++) {
  18. Person person = persons.get(i);
  19. String l = person.getPinyin().charAt(0) + "";
  20. if(TextUtils.equals(letter, l)){
  21. // 匹配成功
  22. mMainList.setSelection(i);
  23. break;
  24. }
  25. }
  26. }
  27. });
  28. mMainList = (ListView) findViewById(R.id.lv_main);
  29. persons = new ArrayList<Person>();
  30. // 填充数据 , 排序
  31. fillAndSortData(persons);
  32. mMainList.setAdapter(new HaoHanAdapter(MainActivity.this , persons));
  33. tv_center = (TextView) findViewById(R.id.tv_center);
  34. }
  35. private Handler mHandler = new Handler();
  36. /**
  37. * 显示字母
  38. * @param letter
  39. */
  40. protected void showLetter(String letter) {
  41. tv_center.setVisibility(View.VISIBLE);
  42. tv_center.setText(letter);
  43. mHandler.removeCallbacksAndMessages(null);
  44. mHandler.postDelayed(new Runnable() {
  45. @Override
  46. public void run() {
  47. tv_center.setVisibility(View.GONE);
  48. }
  49. }, 2000);
  50. }
  51. private void fillAndSortData(ArrayList<Person> persons) {
  52. // 填充数据
  53. for (int i = 0; i < Cheeses.NAMES.length; i++) {
  54. String name = Cheeses.NAMES[i];
  55. persons.add(new Person(name));
  56. }
  57. // 进行排序
  58. Collections.sort(persons);
  59. }
  60. }




附件列表

8.快速索引、listview的更多相关文章

  1. Android ListView A~Z快速索引(改进版)

    上一篇文章虽然实现了ListView 快速索引的效果,但是有一个小小的Bug.这个Bug我在前面也说了,这篇文章就来解决这个Bug. 我研究的时候发现只要showBg值为true,中间的字母就显示,而 ...

  2. 实现ListView A~Z快速索引

    ListView A~Z快速索引这种效果在通信录和城市列表中经常看到,方便用户查找,是一种增加用户体验的好方法. 实现步骤: 1.自定义一个名叫SlideBar 的View. 2.在布局文件中加入这个 ...

  3. Android学习系列(15)--App列表之游标ListView(索引ListView)

    游标ListView,提供索引标签,使用户能够快速定位列表项.      也可以叫索引ListView,有的人称也为Tweaked ListView,可能更形象些吧.      一看图啥都懂了: 1. ...

  4. 快速索引 (对View的自定义)

    快速索引 (对View的自定义) 快速索引应用场景: 微信好友列表, 联系人通讯录, 应用管理, 文件管理等. 快速索引7步曲: *1. A-Z索引的绘制. * 2. 处理Touch事件. * 3. ...

  5. Android-自定义联系人快速索引

    效果图: 布局去指定 view.custom.shangguigucustomview.MyCustomIndexView 自定义View对象 <!-- 自定义联系人快速索引 --> &l ...

  6. Log4net快速索引参考

    官方项目地址:The Apache log4net project 本文内容仅为相关项参考,不进行具体使用讨论 另转载请注明出处 Log4net快速索引参考 Log4net主要有以下三个部件: log ...

  7. Android 快速索引(城市列表和联系人)

    最近需要实现一个城市列表的快速索引功能.类似于联系人应用,根据姓名首字母快速索引功能. 要实现这个功能只需要解决两个问题:1.对列表进行分组(具有同一特征),并且能够快速定位到该组的第一项 2.右侧分 ...

  8. IPFS - 可快速索引的版本化的点对点文件系统(草稿3)

    摘要 星际文件系统是一种点对点的分布式文件系统, 旨在连接所有有相同的文件系统的计算机设备.在某些方面, IPFS类似于web, 但web 是中心化的,而IPFS是一个单一的Bittorrent 群集 ...

  9. 联系人的侧边字母索引ListView 将手机通讯录姓名通过首字母排序。

      package com.lixu.letterlistview; import java.util.ArrayList; import java.util.List; import org.apa ...

随机推荐

  1. swift 关于FDFullscreenPopGesture的右滑返回

    关于导航栏右滑返回的工具库 FDFullscreenPopGesture 是 OC 版本,用了 runtime 等各种骚操作 关于 swift ,我在 UINavigationController 的 ...

  2. 分析abex-crackme#1

    1.分析环境2.运行程序,了解大致的运行过程3.运行Ollydbg调试程序3.1.分析结果简述4.破解4.1.方法一4.2.方法二5.运行结果6.与书中不同之处 1.分析环境 操作系统:Win10 1 ...

  3. 更换Appsecrect应该要注意的问题

    1. 有时候因为需要,有些地方需要填写Appsecrect, 但是大家都知道微信公众平台上这个值 即使你自己是管理员是看不到的,只能重置,但是重置后,一定要记住刷新AccessToken啊,不然就尴尬 ...

  4. 分布式之redis

    正文 1.为什么使用redis 分析:博主觉得在项目中使用redis,主要是从两个角度去考虑:性能和并发.当然,redis还具备可以做分布式锁等其他功能,但是如果只是为了分布式锁这些其他功能,完全还有 ...

  5. Windows10开机pin界面循环重启解决办法

    昨天电脑在开机时,进入pin界面,输入pin码之后系统没反应,也不显示登陆成功,大概一分钟之后自动重启,遂百度答案:大部分建议都是在开机显示win图标时强制关机,强制关机两次即自动进入疑难解答页面,以 ...

  6. php实现仿百度分页

    本文主要和大家分享php实现仿百度分页的实例,先来看一下效果图. 基本策略 1, 首先要查询总记录数 2, 设置每页显示的数量并计算总页数 3, 增加一个get传值num代表当前访问的是哪一页,如果没 ...

  7. 20172306 2018-2019-2 《Java程序设计与数据结构》第八周学习总结

    20172306 2018-2019-2 <Java程序设计与数据结构>第八周学习总结 教材学习内容总结 堆 堆是具有两个附加属性的一棵二叉树 它是一个完全树 对每一结点,它小于或等于其左 ...

  8. oracle数据导出以及导入

    导出 1.服务器上mkdir创建一个真实目录/home/oracle/dump 2.sqlplus /nolog 3.conn /as sysdba; 4.SQL> create directo ...

  9. 《Linux就该这么学》第十八天课程

    1.使用MariaDB数据库管理系统 今天没什么笔记,就不发了.想深入学习的可以前往原创地址:https://www.linuxprobe.com/chapter-18.html 图18-1 Mari ...

  10. LOJ-10094(强连通分量)

    题目链接:传送门 思路: 先缩点,然后统计入度为0的点即可. #include<iostream> #include<cstdio> #include<cstring&g ...