8.快速索引、listview

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity" ><ListViewandroid:id="@+id/lv_main"android:layout_width="match_parent"android:layout_height="match_parent" ></ListView><com.itheima.quickindex.ui.QuickIndexBarandroid:id="@+id/bar"android:layout_width="30dp"android:layout_height="match_parent"android:layout_alignParentRight="true"android:background="#ff0000" /><TextViewandroid:id="@+id/tv_center"android:layout_width="160dp"android:layout_height="100dp"android:background="@drawable/bg_index"android:gravity="center"android:textSize="32sp"android:visibility="gone"android:textColor="#ffffff"android:layout_centerInParent="true"android:text="A" /></RelativeLayout>
<shape xmlns:android="http://schemas.android.com/apk/res/android"android:shape="rectangle" ><solid android:color="#66000000"/><corners android:radius="20dp"/></shape>

/*** 快速索引** 用于根据字母快速定位联系人* @author poplar**/public class QuickIndexBar extends View {private static final 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"};private static final String TAG = "TAG";private Paint mPaint;private int cellWidth;private float cellHeight;/*** 暴露一个字母的监听,交给main执行*/public interface OnLetterUpdateListener{void onLetterUpdate(String letter);}private OnLetterUpdateListener listener;public OnLetterUpdateListener getListener() {return listener;}/*** 设置字母更新监听* @param listener*/public void setListener(OnLetterUpdateListener listener) {this.listener = listener;}public QuickIndexBar(Context context) {this(context, null);}public QuickIndexBar(Context context, AttributeSet attrs) {this(context, attrs, 0);//这样写,只需要在三个参数的构造函数初始化就可以了}public QuickIndexBar(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);mPaint.setColor(Color.WHITE);mPaint.setTypeface(Typeface.DEFAULT_BOLD);//当点中的时候变粗}@Overrideprotected void onDraw(Canvas canvas) {for (int i = 0; i < LETTERS.length; i++) {String text = LETTERS[i];// 计算坐标int x = (int) (cellWidth / 2.0f - mPaint.measureText(text) / 2.0f);//先转成float再转成int,因为有可能丢失精度// 获取文本的高度Rect bounds = new Rect();// 矩形mPaint.getTextBounds(text, 0, text.length(), bounds);//字是矩形,通过矩形获得高int textHeight = bounds.height();int y = (int) (cellHeight / 2.0f + textHeight / 2.0f + i * cellHeight);// 根据按下的字母, 设置画笔颜色mPaint.setColor(touchIndex == i ? Color.GRAY : Color.WHITE);// 绘制文本A-Zcanvas.drawText(text, x, y, mPaint);}}int touchIndex = -1;@Overridepublic boolean onTouchEvent(MotionEvent event) {int index = -1;switch (MotionEventCompat.getActionMasked(event)) {case MotionEvent.ACTION_DOWN:// 获取当前触摸到的字母索引index = (int) (event.getY() / cellHeight);if(index >= 0 && index < LETTERS.length){// 判断是否跟上一次触摸到的一样if(index != touchIndex) {if(listener != null){listener.onLetterUpdate(LETTERS[index]);}Log.d(TAG, "onTouchEvent: " + LETTERS[index]);touchIndex = index;}}break;case MotionEvent.ACTION_MOVE:index = (int) (event.getY() / cellHeight);if(index >= 0 && index < LETTERS.length){// 判断是否跟上一次触摸到的一样if(index != touchIndex){if(listener != null){listener.onLetterUpdate(LETTERS[index]);}Log.d(TAG, "onTouchEvent: " + LETTERS[index]);touchIndex = index;}}break;case MotionEvent.ACTION_UP:touchIndex = -1;break;default:break;}invalidate();return true;}@Overrideprotected void onSizeChanged(int w, int h, int oldw, int oldh) {super.onSizeChanged(w, h, oldw, oldh);// 获取单元格的宽和高cellWidth = getMeasuredWidth();int mHeight = getMeasuredHeight();cellHeight = mHeight * 1.0f / LETTERS.length;}}

public class PinyinUtils {/*** 根据传入的字符串(包含汉字),得到拼音* 黑马 -> HEIMA* 黑 马*& -> HEIMA* 黑马f5 -> HEIMA* @param str 字符串* @return*/public static String getPinyin(String str) {HanyuPinyinOutputFormat format = new HanyuPinyinOutputFormat();format.setCaseType(HanyuPinyinCaseType.UPPERCASE);format.setToneType(HanyuPinyinToneType.WITHOUT_TONE);StringBuilder sb = new StringBuilder();char[] charArray = str.toCharArray();for (int i = 0; i < charArray.length; i++) {char c = charArray[i];// 如果是空格, 跳过if(Character.isWhitespace(c)){continue;}if(c >= -127 && c < 128){// 肯定不是汉字sb.append(c);}else {String s = "";try {// 通过char得到拼音集合. 单 -> dan, shans = PinyinHelper.toHanyuPinyinStringArray(c, format)[0];sb.append(s);} catch (BadHanyuPinyinOutputFormatCombination e) {e.printStackTrace();sb.append(s);}}}return sb.toString();}}
public class Person implements Comparable<Person>{//实现比较功能private String name;private String pinyin;public Person(String name) {super();this.name = name;this.pinyin = PinyinUtils.getPinyin(name);}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getPinyin() {return pinyin;}public void setPinyin(String pinyin) {this.pinyin = pinyin;}@Overridepublic int compareTo(Person another) {return this.pinyin.compareTo(another.getPinyin());}}
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical" ><TextViewandroid:id="@+id/tv_index"android:layout_width="match_parent"android:layout_height="40dp"android:background="#888888"android:gravity="center_vertical"android:paddingLeft="20dp"android:text="A"android:textColor="#ffffff"android:textSize="20sp" /><TextViewandroid:id="@+id/tv_name"android:layout_width="match_parent"android:layout_height="50dp"android:gravity="center_vertical"android:paddingLeft="20dp"android:text="宋江"android:textSize="24sp" /></LinearLayout>
public class HaoHanAdapter extends BaseAdapter {private Context mContext;private ArrayList<Person> persons;public HaoHanAdapter(Context mContext, ArrayList<Person> persons) {this.mContext = mContext;this.persons = persons;}@Overridepublic int getCount() {// TODO Auto-generated method stubreturn persons.size();}@Overridepublic Object getItem(int position) {return persons.get(position);}@Overridepublic long getItemId(int position) {return position;}@Overridepublic View getView(int position, View convertView, ViewGroup parent) {View view = convertView;if(convertView == null){view = view.inflate(mContext, R.layout.item_list, null);}ViewHolder mViewHolder = ViewHolder.getHolder(view);Person p = persons.get(position);String str = null;String currentLetter = p.getPinyin().charAt(0) + "";// 根据上一个首字母,决定当前是否显示字母if(position == 0){str = currentLetter;}else {// 上一个人的拼音的首字母String preLetter = persons.get(position - 1).getPinyin().charAt(0) + "";if(!TextUtils.equals(preLetter, currentLetter)){str = currentLetter;}}// 根据str是否为空,决定是否显示索引栏mViewHolder.mIndex.setVisibility(str == null ? View.GONE : View.VISIBLE);mViewHolder.mIndex.setText(currentLetter);mViewHolder.mName.setText(p.getName());return view;}static class ViewHolder {TextView mIndex;TextView mName;public static ViewHolder getHolder(View view) {//了解这种写法Object tag = view.getTag();if(tag != null){return (ViewHolder)tag;}else {ViewHolder viewHolder = new ViewHolder();viewHolder.mIndex = (TextView) view.findViewById(R.id.tv_index);viewHolder.mName = (TextView) view.findViewById(R.id.tv_name);view.setTag(viewHolder);return viewHolder;}}}}
public class MainActivity extends Activity {private ListView mMainList;private ArrayList<Person> persons;private TextView tv_center;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);QuickIndexBar bar = (QuickIndexBar) findViewById(R.id.bar);// 设置监听,和回调一个意思bar.setListener(new OnLetterUpdateListener() {@Overridepublic void onLetterUpdate(String letter) {// Utils.showToast(getApplicationContext(), letter);showLetter(letter);// 根据字母定位ListView, 找到集合中第一个以letter为拼音首字母的对象,得到索引for (int i = 0; i < persons.size(); i++) {Person person = persons.get(i);String l = person.getPinyin().charAt(0) + "";if(TextUtils.equals(letter, l)){// 匹配成功mMainList.setSelection(i);break;}}}});mMainList = (ListView) findViewById(R.id.lv_main);persons = new ArrayList<Person>();// 填充数据 , 排序fillAndSortData(persons);mMainList.setAdapter(new HaoHanAdapter(MainActivity.this , persons));tv_center = (TextView) findViewById(R.id.tv_center);}private Handler mHandler = new Handler();/*** 显示字母* @param letter*/protected void showLetter(String letter) {tv_center.setVisibility(View.VISIBLE);tv_center.setText(letter);mHandler.removeCallbacksAndMessages(null);mHandler.postDelayed(new Runnable() {@Overridepublic void run() {tv_center.setVisibility(View.GONE);}}, 2000);}private void fillAndSortData(ArrayList<Person> persons) {// 填充数据for (int i = 0; i < Cheeses.NAMES.length; i++) {String name = Cheeses.NAMES[i];persons.add(new Person(name));}// 进行排序Collections.sort(persons);}}
附件列表
8.快速索引、listview的更多相关文章
- Android ListView A~Z快速索引(改进版)
上一篇文章虽然实现了ListView 快速索引的效果,但是有一个小小的Bug.这个Bug我在前面也说了,这篇文章就来解决这个Bug. 我研究的时候发现只要showBg值为true,中间的字母就显示,而 ...
- 实现ListView A~Z快速索引
ListView A~Z快速索引这种效果在通信录和城市列表中经常看到,方便用户查找,是一种增加用户体验的好方法. 实现步骤: 1.自定义一个名叫SlideBar 的View. 2.在布局文件中加入这个 ...
- Android学习系列(15)--App列表之游标ListView(索引ListView)
游标ListView,提供索引标签,使用户能够快速定位列表项. 也可以叫索引ListView,有的人称也为Tweaked ListView,可能更形象些吧. 一看图啥都懂了: 1. ...
- 快速索引 (对View的自定义)
快速索引 (对View的自定义) 快速索引应用场景: 微信好友列表, 联系人通讯录, 应用管理, 文件管理等. 快速索引7步曲: *1. A-Z索引的绘制. * 2. 处理Touch事件. * 3. ...
- Android-自定义联系人快速索引
效果图: 布局去指定 view.custom.shangguigucustomview.MyCustomIndexView 自定义View对象 <!-- 自定义联系人快速索引 --> &l ...
- Log4net快速索引参考
官方项目地址:The Apache log4net project 本文内容仅为相关项参考,不进行具体使用讨论 另转载请注明出处 Log4net快速索引参考 Log4net主要有以下三个部件: log ...
- Android 快速索引(城市列表和联系人)
最近需要实现一个城市列表的快速索引功能.类似于联系人应用,根据姓名首字母快速索引功能. 要实现这个功能只需要解决两个问题:1.对列表进行分组(具有同一特征),并且能够快速定位到该组的第一项 2.右侧分 ...
- IPFS - 可快速索引的版本化的点对点文件系统(草稿3)
摘要 星际文件系统是一种点对点的分布式文件系统, 旨在连接所有有相同的文件系统的计算机设备.在某些方面, IPFS类似于web, 但web 是中心化的,而IPFS是一个单一的Bittorrent 群集 ...
- 联系人的侧边字母索引ListView 将手机通讯录姓名通过首字母排序。
package com.lixu.letterlistview; import java.util.ArrayList; import java.util.List; import org.apa ...
随机推荐
- swift 关于FDFullscreenPopGesture的右滑返回
关于导航栏右滑返回的工具库 FDFullscreenPopGesture 是 OC 版本,用了 runtime 等各种骚操作 关于 swift ,我在 UINavigationController 的 ...
- 分析abex-crackme#1
1.分析环境2.运行程序,了解大致的运行过程3.运行Ollydbg调试程序3.1.分析结果简述4.破解4.1.方法一4.2.方法二5.运行结果6.与书中不同之处 1.分析环境 操作系统:Win10 1 ...
- 更换Appsecrect应该要注意的问题
1. 有时候因为需要,有些地方需要填写Appsecrect, 但是大家都知道微信公众平台上这个值 即使你自己是管理员是看不到的,只能重置,但是重置后,一定要记住刷新AccessToken啊,不然就尴尬 ...
- 分布式之redis
正文 1.为什么使用redis 分析:博主觉得在项目中使用redis,主要是从两个角度去考虑:性能和并发.当然,redis还具备可以做分布式锁等其他功能,但是如果只是为了分布式锁这些其他功能,完全还有 ...
- Windows10开机pin界面循环重启解决办法
昨天电脑在开机时,进入pin界面,输入pin码之后系统没反应,也不显示登陆成功,大概一分钟之后自动重启,遂百度答案:大部分建议都是在开机显示win图标时强制关机,强制关机两次即自动进入疑难解答页面,以 ...
- php实现仿百度分页
本文主要和大家分享php实现仿百度分页的实例,先来看一下效果图. 基本策略 1, 首先要查询总记录数 2, 设置每页显示的数量并计算总页数 3, 增加一个get传值num代表当前访问的是哪一页,如果没 ...
- 20172306 2018-2019-2 《Java程序设计与数据结构》第八周学习总结
20172306 2018-2019-2 <Java程序设计与数据结构>第八周学习总结 教材学习内容总结 堆 堆是具有两个附加属性的一棵二叉树 它是一个完全树 对每一结点,它小于或等于其左 ...
- oracle数据导出以及导入
导出 1.服务器上mkdir创建一个真实目录/home/oracle/dump 2.sqlplus /nolog 3.conn /as sysdba; 4.SQL> create directo ...
- 《Linux就该这么学》第十八天课程
1.使用MariaDB数据库管理系统 今天没什么笔记,就不发了.想深入学习的可以前往原创地址:https://www.linuxprobe.com/chapter-18.html 图18-1 Mari ...
- LOJ-10094(强连通分量)
题目链接:传送门 思路: 先缩点,然后统计入度为0的点即可. #include<iostream> #include<cstdio> #include<cstring&g ...