强大的分组SectionListView, 支持自定义组头布局和分组的内容布局, 组头有挤压效果
效果与系统的联系人分组效果类似,组头有挤压效果。但是不同的是,SectionListView支持每组的组头布局自定义,每组的内容布局也可以自定义。
效果图如下:
自定义Adapter:
package com.hiphonezhu.demo.lib;import java.util.HashMap;
import java.util.Map;import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
/*** 带分组功能的Adapter* @author hiphonezhu@gmail.com* @version [TestAndroid, 2015-2-16]*/
public abstract class SectionAdapter extends BaseAdapter
{private Map<Integer, Integer> sectionPositionMap; // 存储分组编号及对应的改组内的条目数量private Map<Integer, Integer> sectionForPositionMap = new HashMap<Integer, Integer>(); // 存储position对应的分组编号private Map<Integer, Integer> positionForSectionMap = new HashMap<Integer, Integer>(); // 存储分组编号对应的第一个出现的positon位置public SectionAdapter(Map<Integer, Integer> sectionPositionMap){this.sectionPositionMap = sectionPositionMap;// 初始化Position与Section对应关系数据int sectionSize = sectionPositionMap != null? sectionPositionMap.size() : 0;int position = 0;for(int i = 0; i < sectionSize; i++){int size = sectionPositionMap.get(i) != null? sectionPositionMap.get(i) : 0;for(int j = 0; j < size; j++){if (!positionForSectionMap.containsKey(i)){positionForSectionMap.put(i, position);}sectionForPositionMap.put(position, i);position++;}}}@Overridepublic View getView(int position, View convertView, ViewGroup parent){int type = getItemViewType(position);return getView(type, position, convertView, parent);}/*** 加载每一行的View* @param section 分组编号* @param position* @param convertView* @param parent* @return*/protected abstract View getView(int section, int position, View convertView, ViewGroup parent);/*** 根据position返回item的样式(每个分组一种样式)* @param position* @return* @see android.widget.BaseAdapter#getItemViewType(int)*/@Overridepublic int getItemViewType(int position){return getSectionForPosition(position);}/*** 返回样式的总共数量(总计多少分组就多少个样式)* @return* @see android.widget.BaseAdapter#getViewTypeCount()*/@Overridepublic int getViewTypeCount(){return getSectionCount();}@Overridepublic int getCount(){int sectionCount = getSectionCount();int sectionItemTotalCount = 0;for(int i=0; i<sectionCount; i++){sectionItemTotalCount += getCountForSection(i);}return sectionItemTotalCount;}/*** 判断当前行是否要显示分组信息* @param position 下标* @return*/public boolean sectionVisible(int position){int section = getSectionForPosition(position);return position == getPositionForSection(section);}/*** 根据分组号加载分组View* @param section* @return*/public abstract View getSectionView(int section);/*** 根据下标位置查询分组编号* @param position 下标* @return*/public int getSectionForPosition(int position){if (!sectionForPositionMap.containsKey(position)){return -1;}return sectionForPositionMap.get(position);}/*** 根据分组号查找第一个下标位置* @param section 分组编号* @return*/public int getPositionForSection(int section){if (!positionForSectionMap.containsKey(section)){return -1;}return positionForSectionMap.get(section);}/*** 返回分组数量* @return*/protected int getSectionCount(){return sectionPositionMap != null? sectionPositionMap.size() : 0;}/*** 返回指定分组中的item数目* @param section 分组编号* @return*/protected int getCountForSection(int section){return sectionPositionMap != null? (sectionPositionMap.get(section) != null? sectionPositionMap.get(section) : 0) : 0;}
}
自定义ListView:
package com.hiphonezhu.demo.lib;import java.util.HashMap;
import java.util.Map;
import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.ListView;
/*** 带分组表头的ListView* @author hiphonezhu@gmail.com* @version [TestAndroid, 2015-2-16]*/
public class SectionListView extends ListView
{private SectionAdapter sectionAdapter;private ViewGroup sectionContainer;public SectionListView(Context context, AttributeSet attrs, int defStyle){super(context, attrs, defStyle);}public SectionListView(Context context, AttributeSet attrs){super(context, attrs);}public SectionListView(Context context){super(context);}/*** 绑定数据适配器* @param sectionAdapter* @param sectionContainer*/public void setAdapter(SectionAdapter sectionAdapter, ViewGroup sectionContainer){super.setAdapter(sectionAdapter);this.sectionAdapter = sectionAdapter;this.sectionContainer = sectionContainer;setOnScrollListener(scrollListener);}private OnScrollListener scrollListener = new OnScrollListener(){private int lastFirstVisibleItem = -1; final Map<Integer, View> sectionViewMap = new HashMap<Integer, View>();@Overridepublic void onScrollStateChanged(AbsListView paramAbsListView, int paramInt){}@Overridepublic void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount){int section = sectionAdapter.getSectionForPosition(firstVisibleItem);int nextSecPosition = sectionAdapter.getPositionForSection(section + 1); View sectionView = sectionViewMap.get(section);if (sectionView == null){sectionView = sectionAdapter.getSectionView(section);sectionViewMap.put(section, sectionView);sectionContainer.addView(sectionView);}else{int count = sectionContainer.getChildCount();for(int i = 0; i < count; i++){if (sectionContainer.getChildAt(i) != sectionView){sectionContainer.getChildAt(i).setVisibility(View.GONE);}else{sectionContainer.getChildAt(i).setVisibility(View.VISIBLE);}}}if (firstVisibleItem != lastFirstVisibleItem) { MarginLayoutParams params = (MarginLayoutParams) sectionContainer.getLayoutParams(); params.topMargin = 0; sectionContainer.setLayoutParams(params); } if (nextSecPosition - firstVisibleItem < visibleItemCount) // 下一个分组在当前屏幕可见范围{// 下一个分组的ViewView childView = view.getChildAt(nextSecPosition - firstVisibleItem); if (childView != null) { int titleHeight = sectionContainer.getHeight(); int top = childView.getTop(); MarginLayoutParams params = (MarginLayoutParams) sectionContainer .getLayoutParams(); if (top < titleHeight) { float pushedDistance = top - titleHeight; params.topMargin = (int) pushedDistance; sectionContainer.setLayoutParams(params); } else { if (params.topMargin != 0) { params.topMargin = 0; sectionContainer.setLayoutParams(params); } } } }lastFirstVisibleItem = firstVisibleItem; }};
}
源码下载地址:https://github.com/hiphonezhu/SectionListView
强大的分组SectionListView, 支持自定义组头布局和分组的内容布局, 组头有挤压效果相关推荐
- 开源自定义表单提交系统源码 支持自定义字段功能强大
分享一个强大的可以自定义字段的表单提交系统源码,完全开源可以二次开发,支持新建N个表单主题,不限制数量,解决所有表单的应用场景.自定义表单模型,任何类型都支持,功能十分强大. 此套万能表单系统厉害了, ...
- ml不是内部或外部命令_美国飞机制造商波音公司采用VR技术训练宇航员 ; Snap Lens Studio推出支持自定义ML驱动的Snapchat镜头...
看日报是个好习惯! Valve宣布为Steam开发者推出OpenXR预览版本,支持跨平台VR/AR内容开发 Valve在为Steam游戏开发人员迎接OpenXR面世的准备方面迈出了重要的一步,开发 ...
- winform定义数据源名称_WinForm中使用CrystalReport水晶报表——基础,分组统计,自定义数据源...
开篇 本篇文章主要是帮助刚开始接触CrystalReport报表的新手提供一个循序渐进的教程.该教程主要分为三个部分1)CrystalReport的基本使用方法:2)使用CrystalReport对数 ...
- python selenium post请求_工作随笔——selenium支持post请求,支持自定义header
2018-01-10:fix post 请求数据遗漏部分内容 背景: 最近在写一个小程序,发现博主所在的地区访问该网站时有防ddos功能验证导致程序不能正常工作. 经过试验发现可以用国外代理ip解决这 ...
- element form自定义校验_SpringBoot分组校验及自定义校验注解
前言 在日常的开发中,参数校验是非常重要的一个环节,严格参数校验会减少很多出bug的概率,增加接口的安全性.在此之前写过一篇SpringBoot统一参数校验主要介绍了一些简单的校验方法.而这篇则是 ...
- 模拟get和post请求(支持自定义header和测试CDN节点)
下面是一个模拟get或者post请求的方法支持 1.get,post方法 2.自定义参数 3.自定义header 4.返回服务器的返回内容和header 5.支持相特定的服务器请求url,适合测试cd ...
- datatable的数据进行组内排序_Spark实现分组Top-k排序的四种方案(scala语言)
Spark中实现分组排序(取Top-k)的四种方法. 以求每个学科最受欢迎的老师为例,假设学科下每个老师的主页访问量的多少代表该老师的受欢迎程度. 截取log日志文件中的网址数据的格式为: 数据格式: ...
- 服务器阵列卡安装win7系统,乐扩阵列卡IO-PCE9230-4IR组阵列方法和windows7系统安装到阵列组详细讲解(附视频) - 常见问题 - 技术支持 - 乐扩...
以[乐扩IO-PCE9230-4IR阵列卡]为例,详细讲解组阵列方法,安装Win7 操作系统安装到阵列组的方法: 一.组阵列:[观看视频] 先组阵列: 1.在关机状态下,把阵列卡插到主板的PCI-E插 ...
- 开源表单网站系统源码支持自定义字段提交
分享一个完全开源的自定义表单提交系统源码,功能强大,支持三级联动,支持在线付费报名,带完整搭建教程. 春哥万能自定义表单系统是支持自定义的万能表单系统,支持普通表单.付费报名.预约服务等三合一功能,支 ...
最新文章
- Win10系列:JavaScript访问文件和文件夹
- 机器学习的教训:5家公司分享的错误经验
- CheckBox in ListView
- 设计模式示例_责任链设计模式示例
- C语言有参函数调用时参数值传递问题
- springboot_通过Actuator了解应用程序运行时的内部状况
- 玩游戏用什么轴的机械键盘好_机械键盘选什么轴?全方面分析各轴手感和区别...
- scala中的柯里化函数
- CPU指令集科普:CISC指令集和RISC指令集
- python实现九九乘法表代码解释_python编写九九乘法表代码
- 快速清理C盘的四个方法
- 快速添加百度网盘文件到Aria2 猴油脚本
- 又有朋友被骗入传销了!
- PyCharm 的调试功能
- qt生成程序以管理员身份运行和取消以管理员身份运行方式
- 儿童身高体重健康对照表
- 一个ppp帧的数据部分(用十六进制写出)是7D 5E FE 27 7D 5D 7D 5D 65 7D 5E。
- Juniper设备审计
- 这些东西别晒到朋 友 圈,小心惹来祸!
- 常见的网络营销技巧有哪些?