现在的App的ListView大部分都有分组头部和快速滑动索引,而且分组头部还有挤压的效果,看起来比较炫,于是就在各路大神的博客里找思路,果然发现了几种比较好的实现思路。其中夏神的关于列表快速索引是最好的,我个人认为,git上也有类似的效果但好多是重写ListView实现的,导致可扩展性变得不是很好,夏神是通过自定义View和SectionIndex实现此效果的。而头部分组挤压动画则是郭神的思路最好。通过添加OnScrollListener实现,也没有修改到ListView.

现在:我主要将两位大神的代码合并,调整优化部分代码,顺便改几个小bug。
思路上面基本说清楚了,下面看主要代码实现:
1.快速索引的实现:

/**
* @description 依附于列表的索引View
* @author rzq
* @date 2015年9月19日
*/public class SideBar extends View
{/*** 要绘制的内容*/private static String[] biao ={ "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 Context mContext;private Paint mPaint;/*** View的宽高*/private int mWidth, mHeight;/*** 单个表的高度*/private int mSingleHeight;private int choose = -1;/*** */private boolean isDown;private OnTouchingLetterListener mChangedListener;public SideBar(Context context, AttributeSet attrs){this(context, attrs, 0);}public SideBar(Context context){this(context, null, 0);}public SideBar(Context context, AttributeSet attrs, int defStyleAttr){super(context, attrs, defStyleAttr);mContext = context;init();}private void init(){mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);mPaint.setTypeface(Typeface.DEFAULT_BOLD);mPaint.setTextSize(20);}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){super.onMeasure(widthMeasureSpec, heightMeasureSpec);mWidth = getWidth();mHeight = getHeight();mSingleHeight = mHeight / biao.length;}/*** onDraw()尽量值负责与绘制相关的东西 */@Overrideprotected void onDraw(Canvas canvas){setBackgroundDrawable(isDown ? new ColorDrawable(0x99C60000) : new ColorDrawable(0x00000000));for (int i = 0; i < biao.length; i++){mPaint.setColor(i == choose ? Color.parseColor("#3399ff") : Color.rgb(33, 65, 98));float xPos = (mWidth - mPaint.measureText(biao[i])) / 2;float yPos = mSingleHeight * i + mSingleHeight;canvas.drawText(biao[i], xPos, yPos, mPaint);}}@Overridepublic boolean onTouchEvent(MotionEvent event){final int oldChoose = choose;float y = event.getY();int c = (int) (y / mHeight * biao.length);switch (event.getAction()){case MotionEvent.ACTION_DOWN:case MotionEvent.ACTION_MOVE:isDown = true;if (oldChoose != c){if (c >= 0 && c < biao.length){if (mChangedListener != null){mChangedListener.onTouchingletterChanged(biao[c]);}choose = c;invalidate();}}break;case MotionEvent.ACTION_CANCEL:case MotionEvent.ACTION_UP:isDown = false;choose = -1;invalidate();break;}// 将点击事件吃掉return true;}public void setOnTouchingLetterChangedListener(OnTouchingLetterListener onTouchingLetterListener){this.mChangedListener = onTouchingLetterListener;}public interface OnTouchingLetterListener{public void onTouchingletterChanged(String s);}
}package view;import com.example.sortlistview.R;
import com.example.sortlistview.SortModel;import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.SectionIndexer;
import android.widget.TextView;import java.util.List;/**
* @description 实现了SectionIndexer的可快速滑动Adapter
* @author rzq
* @date 2015年9月19日
*/
public class SortAdapter extends BaseAdapter implements SectionIndexer
{private List<SortModel> list = null;private Context mContext;public SortAdapter(Context mContext, List<SortModel> list){this.mContext = mContext;this.list = list;}@Overridepublic int getCount(){return list.size();}@Overridepublic Object getItem(int position){return list.get(position);}@Overridepublic long getItemId(int position){return position;}@Overridepublic View getView(int position, View convertView, ViewGroup parent){ViewHolder viewHolder = null;final SortModel mContent = list.get(position);if (convertView == null){viewHolder = new ViewHolder();convertView = LayoutInflater.from(mContext).inflate(R.layout.item, null);viewHolder.tvTitle = (TextView) convertView.findViewById(R.id.title);viewHolder.tvLetter = (TextView) convertView.findViewById(R.id.catalog);convertView.setTag(viewHolder);}else{viewHolder = (ViewHolder) convertView.getTag();}int section = getSectionForPosition(position);if (position == getPositionForSection(section)){viewHolder.tvLetter.setVisibility(View.VISIBLE);viewHolder.tvLetter.setText(mContent.getSortLetters());}else{viewHolder.tvLetter.setVisibility(View.GONE);}viewHolder.tvTitle.setText(this.list.get(position).getName());return convertView;}@Overridepublic Object[] getSections(){return null;}@Overridepublic int getPositionForSection(int sectionIndex){for (int i = 0; i < getCount(); i++){String sortStr = list.get(i).getSortLetters();char firstChar = sortStr.toUpperCase().charAt(0);if (firstChar == sectionIndex){return i;}}return -1;}@Overridepublic int getSectionForPosition(int position){return list.get(position).getSortLetters().charAt(0);}final static class ViewHolder{TextView tvLetter;TextView tvTitle;}
}

代码基本copy的大神的,对一些代码的位置做了优化。主要是onDraw()让其只负责绘制相关。

2.头部挤压动画实现:

sortListView.setOnScrollListener(new OnScrollListener(){@Overridepublic void onScrollStateChanged(AbsListView view, int scrollState){}/*** 滑动结束时调用 */@Overridepublic void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount){/*** 获取firstVisibleItem所在section*/int section = adapter.getSectionForPosition(firstVisibleItem);/*** 获取下一item所在section*/int nextSection = adapter.getSectionForPosition(firstVisibleItem + 1);/*** 获取下一item所在section的position*/int nextSecPosition = adapter.getPositionForSection(nextSection);/*** 显示firstVisibleItem所在分组的头部*/if (firstVisibleItem != lastFirstVisibleItem){MarginLayoutParams params = (MarginLayoutParams) titleLayout.getLayoutParams();params.topMargin = 0;titleLayout.setLayoutParams(params);if (String.valueOf((char) section) != null){title.setText(String.valueOf((char) section));}}/*** 说明到了临界位置*/if (nextSecPosition == firstVisibleItem + 1){View childView = view.getChildAt(0);if (childView != null){int titleHeight = titleLayout.getHeight();int bottom = childView.getBottom();MarginLayoutParams params = (MarginLayoutParams) titleLayout.getLayoutParams();/*** 产生了碰撞,上移titleLayout*/if (bottom < titleHeight){float pushedDistance = bottom - titleHeight;params.topMargin = (int) pushedDistance;titleLayout.setLayoutParams(params);}else{if (params.topMargin != 0){params.topMargin = 0;titleLayout.setLayoutParams(params);}}}}lastFirstVisibleItem = firstVisibleItem;}});

为ListView添加OnScrollListener,监听ListView的滑动。。。

夏神博客地址:http://blog.csdn.net/xiaanming/article/details/12684155
郭神博客地址:http://blog.csdn.net/guolin_blog/article/details/9033553

Demo下载

Android自定义头部悬浮,快速索引ListView相关推荐

  1. Android仿微信实现快速索引选择联系人

    Android仿微信实现快速索引选择联系人 原创 2016年03月05日 13:19:20 1640 3 1 一.概述 先看效果图,然后在给大家慢慢介绍  二.实现 先给大家说说这些城市的数据是怎么来 ...

  2. android 让应用悬浮,快速回复+app下载

    快速回复+应用多窗口,在玩游戏或者看视频的时候可以开启悬浮窗口回复消息,不用特意切换后台回复消息非常方便.可以自由调节软件的窗口大小以及位置,无需root就能使用.内存占用小不用担心会对其他应用造型卡 ...

  3. android 自定义表情包,快速打造 Android 自定义表情库

    简介 本文灵感来源是经典的https://github.com/rockerhieu/emojicon,部分代码直接不要脸的 copy 了,在其基础上更美观好用,且自定义空间更大. 最终效果图 源码下 ...

  4. android 仿微信联系人 首字母分组快速索引

    总结是一种习惯,不能停,一停人就懒了,都快一个月没有写了!该提提神了! 进入正题:android 仿微信联系人 首字母快速索引,先用下美团的索引效果图: 1.自定义View字母索引栏(右边那一列): ...

  5. Android App列表之游标ListView(索引ListView)

    原帖地址:http://www.apkbus.com/android-14717-1-1.html 游标ListView,提供索引标签,使用户能够快速定位列表项.       也可以叫索引ListVi ...

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

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

  7. android中上拉下滑布局,3年以上勿进!最简单的Android自定义ListView下拉刷新与上拉加载,代码直接拿去用~...

    本文主要针对开发新手,手写实现一个最简单Android自定义listview下拉刷新和上拉加载demo. 不喜可喷,欢迎大佬留言指点. 效果图 一:编写需要在ListView中增加头加载的布局文件,与 ...

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

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

  9. Android 自定义ScrollView ListView 体验各种纵向滑动的需求

    1.概述 群里的一个哥们有个需求是这样的:问题:主要功能就是:1.循环的一个滑动:2.每次滑动结束,保持每个Item的完整.然后我当时给他写了个Demo,所有代码都在Activity里面,后期看来其太 ...

  10. ListView字母快速索引 自动搜索

    最近先来没事,提取一下项目中的一些实用性功能,也算是一种知识总结.希望对自己和需要此功能的朋友有一些帮助 效果图: 字母索引 过滤搜索 功能代码: 自定义一个字母索引的View MyLetterLis ...

最新文章

  1. KBMMW 的日志管理器
  2. 将一维数组的值逆序输出
  3. vim 命令模式与输入模式切换
  4. VIM - 每行前或者每行后增加相同的字符串
  5. Java基础总结之数组
  6. 跨链Cosmos(5)ABCI 接口
  7. 软件测试工作常用linux命令,软件测试工程师工作中常用的Linux命令
  8. [ 人机交互 ] 第三次作业 2015080360025秦嘉颍
  9. [深度学习] FM FFM 算法基本原理
  10. python安装anaconda ubuntu_Ubuntu 16.4 安装anaconda 详细教程
  11. sbt创建web项目
  12. 格力电器:回购股份比例超3% 已耗资95.15亿元
  13. Idea和使用git命令上传本地新项目到gitee上
  14. (已更新)视频app小程序模板源码
  15. zooInspector下载
  16. 用我的亲身经历来告诉你如何自学Java?
  17. 燕山大学计算机辅助设计三级项目报告,《计算机辅助设计Auto CAD》燕山大学
  18. 软件工程-软件测试和系统运维
  19. 中国K12在线教育用户消费行为报告
  20. c# winform 无边框窗体 移动办法

热门文章

  1. matlab kfcm,聚类——KFCM的matlab程序
  2. iframe中的右键 禁止_网站排名优化中必须要注意的事项
  3. 三维重建_基于RGB-D相机的三维重建总览(静态动态)
  4. 企业架构-发布在线文档【企业架构框架-TOGAF v0.2.pdf】
  5. input 函数的输入和输出
  6. 【贪心 哈夫曼树】bzoj2923: [Poi1998]The lightest language
  7. 聚类-----KMeans
  8. 个人作业-2016.12.2
  9. iOS开发证书要点详解
  10. LintCode: Combination Sum