[Android开发] 在项目中快速实现 列表字母排序滑动索引 功能原理以及过程代码
来源:互联网 发布:人物识别软件 编辑:程序博客网 时间:2024/06/06 09:06
一、效果图
二、简介
我在做项目时候添加的功能,网上看了一些别人的做法,觉得一般般,然后就自己花了一下午写了一个感觉还可以的。
列表用的是listView,侧边字母栏是自定义了一个SideBar。
底部有完整的demo(包括json解析为对应的list bean)。
三、思路过程
1. 先确定服务端返回的json格式
2. 把服务器的数据解析为list bean
3. 根据list的bean里面的字符寸的第一个字母的拼音进行重新排序
4. 排序过程在bean添加首字母标识
5. 适配器进行数据填充到listView,根据bean里面的首字母标识进行显示隐藏字母
6. 封装SideBar字母侧边栏,滑动回调字母listView跳到指定的字母
四、详细过程
1. 知道接口数据格式
从后台开发者给的接口可以知道json的格式如下。
{ "desc":"查询成功", "data":{ "diseaseList":[ { "xmlName":"痴呆的评估", "xmlId":"242", "category":"symptom" }, { "xmlName":"非故意性体重减轻评估", "xmlId":"548", "category":"symptom" } ] }, "action":null, "code":"", "type":"SUCCESS"}
2. 解析为对应的bean的list
我这里是利用上一篇文章的json解析类进行解析: http://blog.csdn.net/niubitianping/article/details/53117978
这里就解析成了List,DiseaseList里面是xmlName、xmlId、category,还有对应的get和set。
3. 重新排序
这是重点,首先用到一个库:pinyin4j来转换把中文转换为拼音。
(ps:还有jpinyin,chineseandpinyin这两个库也是可以转换的。jpinyin好像是pinyin4的优化版 具体我没用。chineseandpinyin我导入了跑起来报错JSONObject找不到,我把json包导入了之后也是一堆问题)。
(1) 导入pinyin4j的库
官网下载地址:http://sourceforge.net/project/showfiles.php?group_id=163377
好多年没更新了,最新是2.5,导入库这么简单就不说了。
(2) 编写比较类
利用java的Collections类进行排序,自己实现排序方法
//对list进行按照拼音排序Collections.sort(list, new PinYinComparator());
PinYinComparator.java比较类
/** * 作用:取第一个字的拼音进行比较排序 * * @author LITP * @date 2016/11/10 */public class PinYinComparator implements Comparator<DiseaseList> { //已经存在的首字母列表 private SparseArray<Character> letters = new SparseArray<>(); @Override public int compare(DiseaseList lhs, DiseaseList rhs) { int c1 = PinYinUtils.getFirstPiniYin(lhs.getXmlName()).charAt(0); int c2 = PinYinUtils.getFirstPiniYin(rhs.getXmlName()).charAt(0); //判断是否已经存在了首字母了 if (letters.get(c1) == null) { //判断是不是字母 if (Character.isLetter((char) c1)) { letters.put(c1,(char) c1); //重点,设置首字母标识 lhs.setLetter((char) c1 + ""); } else { //设置#标识 letters.put('#', (char) c1); lhs.setLetter("#"); } } //c1 不为字母 if ((c1 < 65)) { c1 += 90; // 使其在后面 } //c2 不为字母 if ((c2 < 65)) { c2 += 90; // 使其在后面 } return c1 - c2; //负数则第一个参数在前面, }}
4. 编写适配器
列表的适配器,重点是 item的布局是包括的一行的字母的view,根据bean里面是否有字母而隐藏显示
BMJLetterListAdapter.java
/** * 作用: 字母排序列表的适配器 * * @author LITP * @date 2016/11/4 */public class BMJLetterListAdapter extends BaseAdapter { private LayoutInflater mInflater; private List<?> mDatas; public BMJLetterListAdapter(Context context, List<?> datas){ mInflater = LayoutInflater.from(context); mDatas = datas; } @Override public int getCount() { Log.e("tpnet","总数"+mDatas.size()); return mDatas.size(); } @Override public Object getItem(int arg0) { return mDatas.get(arg0); } @Override public long getItemId(int arg0) { return arg0; } @Override public View getView(int position, View convertView, ViewGroup arg2) { MyViewHolder myViewHolder = null; if(convertView == null){ myViewHolder = new MyViewHolder(); convertView = mInflater.inflate(R.layout.item_bmj_letter_list,arg2,false); myViewHolder.letterText = (TextView) convertView.findViewById(R.id.bmj_tv_letter); myViewHolder.contentText = (TextView) convertView.findViewById(R.id.bmj_tv_content); convertView.setTag(myViewHolder); }else{ myViewHolder = (MyViewHolder) convertView.getTag(); } DiseaseList item = (DiseaseList) getItem(position); if(item != null){ //如果有字母标识就显示 字母那一行 if(!item.getLetter().isEmpty()){ myViewHolder.letterText.setText(item.getLetter()); myViewHolder.letterText.setVisibility(View.VISIBLE); }else{ //否则隐藏 myViewHolder.letterText.setVisibility(View.GONE); } myViewHolder.contentText.setText(item.getXmlName()); } return convertView; } private class MyViewHolder{ private TextView letterText; private TextView contentText; }}
布局文件请看demo,代码太多就不贴了
5. 封装侧边字母栏
上面的排序和数据已经搞好了,接下来是侧边的字母索引。要实现的功能有点击其中的字母 listview跳到指定的位置,滑动时候也要跳到指定的位置。 这个很简单,100多行代码就可以了
SideBar.java
/** * 作用: 右边的字母View * * @author LITP * @date 2016/11/2 */public class SideBar extends View { // 26个字母 public static String[] letters = {"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 int choose = -1; // 选中的字母的y坐标 //字母画笔 private Paint paint = new Paint(); private TextView mTextDialog; //显示当前字母的文本框 private int singleHeight; //一个字母的空间 Rect rect = new Rect(); //存放文字的高度 public SideBar(Context context, AttributeSet attrs) { super(context, attrs); } @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); paint.setAntiAlias(true); //设置抗锯齿 paint.setTextSize(DensityUtil.sp2px(12f)); //设置字母字体大小为12sp //获取一个字母实际的宽高到rect paint.getTextBounds("A", 0, 1, rect); //获取一个字母的空间 singleHeight = (getHeight() - (getPaddingTop() + getPaddingBottom())) / 27; } /** * 为SideBar设置显示字母的TextView * * @param mTextDialog 在activity传递过来的textView */ public void setTextView(TextView mTextDialog) { this.mTextDialog = mTextDialog; } /** * 绘制 */ @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); //循环绘制字母 for (int i = 0; i < letters.length; i++) { //paint.setTypeface(Typeface.DEFAULT_BOLD); //设置默认字体加粗 // 选中的状态 if (i == choose) { paint.setColor(getResources().getColor(R.color.light_color_blue)); //选中的字母改变颜色 paint.setFakeBoldText(true); //设置字体为粗体 } else { paint.setColor(getResources().getColor(R.color.darkgray)); //设置字体颜色 paint.setFakeBoldText(false); //设置字体为正常 } // x坐标等于中间-字符宽度的一半. float xPos = getWidth() / 2 - paint.measureText(letters[i]) / 2; //Y轴坐标 float yPos = getPaddingTop() + singleHeight * i + rect.height(); canvas.drawText(letters[i], xPos, yPos, paint); //绘制字母 } } /** * 分发触摸事件 * * @param event * @return */ @Override public boolean dispatchTouchEvent(MotionEvent event) { final int action = event.getAction(); final float y = event.getY();// 点击y坐标 final int oldChoose = choose; //上一个选中的字母 // 点击y坐标所占总高度的比例 * 数组的长度就等于点击了 数组中的位置. final int c = (int) (y / (getHeight() - getPadddingTop() - getPaddingBottom()) * letters.length); switch (action) { case MotionEvent.ACTION_UP: //抬起来的时候设置背景为透明 //setBackgroundDrawable(new ColorDrawable(0x00000000)); choose = -1;// invalidate(); if (mTextDialog != null) { mTextDialog.setVisibility(View.INVISIBLE); } break; default: //按下,滑动的时候设置背景为灰色 //setBackgroundDrawable(new ColorDrawable(0x44000000)); //setBackgroundResource(R.drawable.sidebar_background); if (oldChoose != c) { //判断选中字母是否发生改变 if (c >= 0 && c < letters.length) { if (listener != null) { listener.onTouchLetterChanged(letters[c]); } if (mTextDialog != null) { mTextDialog.setText(letters[c]); mTextDialog.setVisibility(View.VISIBLE); } //设置选中字母在数组的位置 choose = c; invalidate(); } } break; } return true; } // 触摸回调接口 private OnTouchLetterChangedListener listener; public void setOnTouchLetterChangedListener( OnTouchLetterChangedListener onTouchLetterChangedListener) { this.listener = onTouchLetterChangedListener; } public interface OnTouchLetterChangedListener { /** * 触摸字母回调 * * @param s 触摸的字符 */ void onTouchLetterChanged(String s); }}
五、使用
- 窗口打开现在加载中的dialog
- 开始请求获取json
- 解析json为对应的list
- 在子线程中进行排序
- 更新到适配器
- 实现字母view滑动接口,字母view滑动点击 listView跳到指定位置
/** * 点击或者滑动到当前的字母 listView跳到指定位置 * * @param s 触摸的字符 */ @Override public void onTouchLetterChanged(String s) { for (DiseaseList item : list) { if (item.getLetter().equals(s)) { bmjLvLetter.setSelection(list.indexOf(item)); return; } } }
完整demo下载: http://download.csdn.net/detail/niubitianping/9679329
- [Android开发] 在项目中快速实现 列表字母排序滑动索引 功能原理以及过程代码
- Android中ListView字母排序,实现字母挤压效果以及右侧快速选中字母,搜索关键字功能
- Android实现通讯录功能,排序+字母索引
- 如何在开发过程中快速实现页面功能
- android开发中联系人列表显示字母索引
- 快速集成android实现listview的字母A-Z排序,界面侧边字母索引
- 快速集成android实现listview的字母A-Z排序,界面侧边字母索引
- Android字母索引列表
- Android ListView实现分组字母索引排序
- 【Android】自定义View快速建立字母索引列表
- 仿微信联系人列表滑动字母索引
- Android 仿联系人列表 实现ListView的A-Z字母排序和过滤搜索功能
- Android联系人列表,实现ListView的A-Z字母排序和过滤搜索功能,字母条目上顶
- 实现联系人列表字母索引
- Android仿微信通讯录功能,好友排序+字母索引
- Android仿微信通讯录功能,好友排序+字母索引
- android开发实例02:列表字母索引与过滤检索
- ItemDecoration详解以及用ItemDecoration实现按字母排序列表
- Android最佳的开源库集锦
- 自考总结
- 数据挖掘十大算法 --- KNN
- java--数据库连接池2(多例)
- 学习AOP之认识一下Spring AOP
- [Android开发] 在项目中快速实现 列表字母排序滑动索引 功能原理以及过程代码
- 无线技术学习笔记(1)
- PHPStrom全局搜索快捷键
- 基于OpenCV批量处理文件夹中的图片的方法
- colinux访问windows文件
- 【Android】子Fragment获取父Fragment
- mac下安装nginx
- java--获取数据库连接1(单例)
- sql性能优化