[Android开发] 在项目中快速实现 列表字母排序滑动索引 功能原理以及过程代码
2016-11-10 18:44
1376 查看
一、效果图
二、简介
我在做项目时候添加的功能,网上看了一些别人的做法,觉得一般般,然后就自己花了一下午写了一个感觉还可以的。列表用的是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中ListView字母排序,实现字母挤压效果以及右侧快速选中字母,搜索关键字功能
- Android项目类似淘宝 电商 搜索功能,监听软键盘搜索事件,延迟自动搜索,以及时间排序的搜索历史记录的实现
- Android 仿联系人列表 实现ListView的A-Z字母排序和过滤搜索功能,并挤压效果
- 快速集成android实现listview的字母A-Z排序,界面侧边字母索引
- Android 仿联系人列表 实现ListView的A-Z字母排序和过滤搜索功能,并挤压效果(一)
- Android开发之仿联系人界面(根据文字首字母A、B、C实现快速索引)
- Android 仿联系人列表 实现ListView的A-Z字母排序和过滤搜索功能
- 快速集成android实现listview的字母A-Z排序,界面侧边字母索引
- Android项目类似淘宝 电商 搜索功能,监听软键盘搜索事件,延迟自动搜索,以及时间排序的搜索历史记录的实现
- Android开发--全国各城市列表并按首字母排序加快速定位
- Android项目类似淘宝 电商 搜索功能,监听软键盘搜索事件,延迟自动搜索,以及时间排序的搜索历史记录的实现
- Android联系人列表,实现ListView的A-Z字母排序和过滤搜索功能,字母条目上顶
- Android实现通讯录功能,排序+字母索引
- Android实现ListView的A-Z字母排序和过滤搜索功能,实现汉字转成拼音
- Slip.js – 在触摸屏上实现列表的滑动排序功能
- asp.net导出excel-一行代码实现excel、xml、pdf、word、html、csv等7种格式文件导出功能而且美观-SNF快速开发平台
- 【android开发】手写签名系统的设计与实现之实现文件夹以及文件列表显示(一)
- Android开发 如何快速实现分享功能
- Android开发 如何快速实现分享功能
- android:照片涂画功能实现过程及原理