项目中有一新的需求,要求能像一些Android机带“联系人列表”一样,数据可以自动分组,且在列表滑动过程中,列表头固定在顶部,效果图如下:

下面就带大家实现上面的效果, 首先,我们要介绍的一个重要的开源库:StickyListHeaders,它的Github地址是:https://github.com/emilsjolander/StickyListHeaders
使用该库,可以更加方便的实现ListView数据分组,且Header固定在顶部。

首先,把github上的项目下载下来,加压后,可看到其中有一个library库,我们需要将该库(Module)导入到新建的项目中,并在自己的Module引入该Library。

项目建成后,开始使用该库进行开发:

1. 布局中引入StickyListHeadersListView:

<?xml version="1.0" encoding="utf-8"?>
<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"> <se.emilsjolander.stickylistheaders.StickyListHeadersListView
android:id="@+id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:cacheColorHint="#00000000"
android:clipToPadding="false"
android:drawSelectorOnTop="true"
android:fastScrollEnabled="true"
android:listSelector="#00000000"
android:overScrollMode="never"
android:scrollbarStyle="outsideOverlay" /> </RelativeLayout>

2. 创建要显示的数据实体

public class LangyaSimple {

    private String id;
private String proj_id;
private String title;
private String desc;
private String project_title; public LangyaSimple(String id, String proj_id, String title, String desc, String project_title) {
this.id = id;
this.proj_id = proj_id;
this.title = title;
this.desc = desc;
this. = project_title;
} public String getId() {
return id;
} public void setId(String id) {
this.id = id;
} public String getProj_id() {
return proj_id;
} public void setProj_id(String proj_id) {
this.proj_id = proj_id;
} public String getTitle() {
return title;
} public void setTitle(String title) {
this.title = title;
} public String getDesc() {
return desc;
} public void setDesc(String desc) {
this.desc = desc;
} public String getProject_title() {
return project_title;
} public void setProject_title(String project_title) {
this.project_title = project_title;
} @Override
public String toString() {
return "LangyaSimple{" +
"id='" + id + '\'' +
", proj_id='" + proj_id + '\'' +
", title='" + title + '\'' +
", desc='" + desc + '\'' +
", project_title='" + project_title + '\'' +
'}';
}
}

注: id是data数据的id,proj_id是该数据所属的组的意思,proj_title是该组的名字;

3. 定义StickyListHeadersListView要显示的适配器:

import android.app.Activity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView; import java.util.List; import se.emilsjolander.stickylistheaders.StickyListHeadersAdapter; public class LangyaAdapter extends BaseAdapter implements StickyListHeadersAdapter { private LayoutInflater inflater; private List<LangyaSimple> mPlanDetails; public LangyaAdapter(Activity context, List<LangyaSimple> mPlanDetails) {
inflater = LayoutInflater.from(context);
this.mPlanDetails = mPlanDetails; } @Override
public int getCount() {
return mPlanDetails.size();
} @Override
public Object getItem(int position) {
return mPlanDetails.get(position);
} @Override
public long getItemId(int position) {
return position;
} @Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder; if (convertView == null) {
holder = new ViewHolder();
convertView = inflater.inflate(R.layout.list_item_proj_plan, parent, false); holder.img_plan = (ImageView) convertView.findViewById(R.id.img_plan); holder.text_plan_name = (TextView) convertView.findViewById(R.id.text_plan_name);
holder.text_plan_info = (TextView) convertView.findViewById(R.id.text_plan_info); convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
} LangyaSimple planDetail = this.mPlanDetails.get(position); if (planDetail != null) { // ImageLoaderUtil.getInstance().displayListItemImage(imgUrl, holder.img_plan);
holder.text_plan_name.setText(planDetail.getTitle());
holder.text_plan_info.setText(planDetail.getDesc());
} return convertView;
} @Override
public View getHeaderView(int position, View convertView, ViewGroup parent) {
HeaderViewHolder holder;
if (convertView == null) {
holder = new HeaderViewHolder();
convertView = inflater.inflate(R.layout.proj_plans_header, parent, false);
holder.text = (TextView) convertView.findViewById(R.id.text1);
convertView.setTag(holder);
} else {
holder = (HeaderViewHolder) convertView.getTag();
}
//set proj_plans_header text as first char in name
String headerText = this.mPlanDetails.get(position).getProject_title();
holder.text.setText(headerText);
return convertView;
} @Override
public long getHeaderId(int position) {
//return the first character of the country as ID because this is what headers are based upon
return Long.parseLong(this.mPlanDetails.get(position).getProj_id());
} class HeaderViewHolder {
TextView text;
} class ViewHolder {
ImageView img_plan; TextView text_plan_name; TextView text_plan_info;
}
}

适配器是List数据显示最重要的部分,为了实现数据分组,该适配器必须要实现StickyListHeadersAdapter接口,并重写其中的getHeaderView(int position, View convertView, ViewGroup parent);和long getHeaderId(int position);方法。

说明:

     getHeaderView方法指定了Header的View的显示;

     getHeaderId决定header出现的时机,如果当前的headerid和前一个headerid不同时,就会显示。

4. 定义数据显示的Activity:

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView; import java.util.ArrayList;
import java.util.List; import se.emilsjolander.stickylistheaders.StickyListHeadersListView; public class MainActivity extends Activity { public StickyListHeadersListView list; private LangyaAdapter langyaAdapter; private List<LangyaSimple> mLangyaDatas; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); list = (StickyListHeadersListView) findViewById(R.id.list);
mLangyaDatas = new ArrayList<LangyaSimple>(); initDatas(); list.setOnItemClickListener(new OnPlanItemClick());
list.setOnItemLongClickListener(new OnPlanItemLongClick()); langyaAdapter = new LangyaAdapter(this, mLangyaDatas);
list.setAdapter(langyaAdapter); } private void updateData() { if (langyaAdapter != null && mLangyaDatas != null) { langyaAdapter.notifyDataSetChanged();
}
} private class OnPlanItemClick implements AdapterView.OnItemClickListener { @Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
LangyaSimple oLangyaSimple = (LangyaSimple) parent.getAdapter().getItem(
position);
Log.e("tag", oLangyaSimple.toString());
}
} private class OnPlanItemLongClick implements AdapterView.OnItemLongClickListener { @Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) { LangyaSimple oLangyaSimple = mLangyaDatas.get(position); Log.e("tag", oLangyaSimple.toString()); mLangyaDatas.remove(oLangyaSimple); updateData(); return true;
}
} private void initDatas() { mLangyaDatas.add(new LangyaSimple("1", "1", "无缘公子", "无缘公子无缘公子无缘公子无缘公子", "公子榜"));
mLangyaDatas.add(new LangyaSimple("2", "1", "无请公子", "无请公子无请公子无请公子无请公子", "公子榜"));
mLangyaDatas.add(new LangyaSimple("3", "1", "无名公子", "无名公子无名公子无名公子无名公子", "公子榜"));
mLangyaDatas.add(new LangyaSimple("4", "1", "无非公子", "无非公子无非公子无非公子无非公子", "公子榜"));
mLangyaDatas.add(new LangyaSimple("5", "1", "无能公子", "无能公子无能公子无能公子无能公子", "公子榜")); mLangyaDatas.add(new LangyaSimple("6", "2", "最无情", "最无情最无情最无情最无情最无情", "高手榜"));
mLangyaDatas.add(new LangyaSimple("7", "2", "最无情", "最无情最无情最无情最无情最无情", "高手榜"));
mLangyaDatas.add(new LangyaSimple("8", "2", "最无情", "最无情最无情最无情最无情最无情", "高手榜"));
mLangyaDatas.add(new LangyaSimple("9", "2", "最无情", "最无情最无情最无情最无情最无情", "高手榜"));
mLangyaDatas.add(new LangyaSimple("10", "2", "最无情", "最无情最无情最无情最无情最无情", "高手榜")); mLangyaDatas.add(new LangyaSimple("11", "3", "情殇", "情殇情殇情殇情殇情殇情殇情殇", "美人榜"));
mLangyaDatas.add(new LangyaSimple("12", "3", "情殇", "情殇情殇情殇情殇情殇情殇情殇", "美人榜"));
mLangyaDatas.add(new LangyaSimple("13", "3", "情殇", "情殇情殇情殇情殇情殇情殇情殇", "美人榜"));
mLangyaDatas.add(new LangyaSimple("14", "3", "情殇", "情殇情殇情殇情殇情殇情殇情殇", "美人榜"));
mLangyaDatas.add(new LangyaSimple("15", "3", "情殇", "情殇情殇情殇情殇情殇情殇情殇", "美人榜"));
}
}

该Activity实现了较多的方法,1. 数据显示, 2. 列表的单机事件, 3. 列表的长按事件, 4. 数据更新等;

有个地方需要着重说明,那就是在初始化数据时,数据必须proj_id必须按分组排列,即,不要将proj_id不同的数据参差着放在集合中,否则容易造成列表显示多组相同组名的数据。

对StickyListHeadersListView其余的操作(点击、长按),和普通的ListView一致,包括在xml中设置的属性也是一致的。

如此这般,便可实现上述的效果了!

源码下载地址(免费):http://download.csdn.net/detail/zuiwuyuan/9274693

Android 开源库StickyListHeadersListView来实现ListView列表分组效果的更多相关文章

  1. GitHub上排名前100的Android开源库介绍(来自github)

    本项目主要对目前 GitHub 上排名前 100 的 Android 开源库进行简单的介绍,至于排名完全是根据 GitHub 搜索 Java 语言选择 (Best Match) 得到的结果,然后过滤了 ...

  2. GitHub Top 100的Android开源库

    摘要: 本项目主要对目前 GitHub 上排名前 100 的 Android 开源库进行简单的介绍, 至于排名完全是根据GitHub搜索Java语言选择「Best M... 本项目主要对目前 GitH ...

  3. 我的Android进阶之旅】GitHub 上排名前 100 的 Android 开源库进行简单的介绍

    GitHub Android Libraries Top 100 简介 本文转载于:https://github.com/Freelander/Android_Data/blob/master/And ...

  4. <Android开源库 ~ 1> GitHub Android Libraries Top 100 简介

    转载自GitHub Android Libraries Top 100 简介 本项目主要对目前 GitHub 上排名前 100 的 Android 开源库进行简单的介绍, 至于排名完全是根据 GitH ...

  5. GitHub上排名前100的Android开源库介绍

    GitHub上排名前100的Android开源库介绍 文章来源: http://www.open-open.com/news/view/1587067#6734290-qzone-1-31660-bf ...

  6. 【Java&amp;Android开源库代码分析】のandroid-async-http の开盘

          在<[Java&Android开源库代码剖析]のandroid-smart-image-view>一文中我们提到了android-async-http这个开源库,本文正 ...

  7. Android 开源库和项目 3

    Android 开源库和项目 Android 开源库和项目 2 1.Matisse Android 图片选择器 -- 知乎开源 github 地址:https://github.com/zhihu/M ...

  8. Android 开源库获取途径整理

    介绍眼下收藏 Android 开源库比較多的 GitHub 项目.站点.Twitter.App 及怎样获取最新的 Android 开源库. 微信号: 1. GitHub Android 开源项目汇总 ...

  9. 100个Github上Android开源库

    项目名称 项目简介 1. react-native 这个是 Facebook 在 React.js Conf 2015 大会上推出的基于 JavaScript 的开源框架 React Native, ...

随机推荐

  1. vuex的简单教程

    首先安装vuex npm install vuex --save 然后创建store.js文件里写 import Vue from 'vue' import Vuex from 'vuex' Vue. ...

  2. Leetcode34.Find First and Last Position of Element in Sorted Array在排序数组中查找元素的位置

    给定一个按照升序排列的整数数组 nums,和一个目标值 target.找出给定目标值在数组中的开始位置和结束位置. 你的算法时间复杂度必须是 O(log n) 级别. 如果数组中不存在目标值,返回 [ ...

  3. ubuntu16.04上在使用搜狗输入法时,按shift不能正常切换中英文

    问题描述: ubuntu16.04上在使用搜狗输入法时,不知道把什么组合键给错按了,导致了按shift不能正常切换中英文,这是一件很烦恼的事儿! 解决步骤: 1,终端输入打开: fcitx-confi ...

  4. PLSql 查询结果让数字显示为字符

    有时候某些地段太长的话就会默认显示为数字,例如ID字段过长就会显示为4.34E23的形式,遇到这样情况如何还原id字段的本身形式呢? Tools-->preference-->SQL Wi ...

  5. 最短路径问题 HDU - 3790 (Dijkstra算法 + 双重权值)

    参考:https://www.cnblogs.com/qiufeihai/archive/2012/03/15/2398455.html 最短路径问题 Time Limit: 2000/1000 MS ...

  6. UML时序图(Sequence Diagram)学习笔记

    什么是时序图时序图(Sequence Diagram),又名序列图.循序图,是一种UML交互图.它通过描述对象之间发送消息的时间顺序显示多个对象之间的动态协作. 让我们来看一看visio2016对时序 ...

  7. laravel 分页带参数

    {{$data->appends(request()->except(['page']))->links()}}

  8. 遗传算法MATLAB实现(3):多元函数优化举例

    多峰的Shubert为: 求f(x,y)在[-10,10]x[-10,10]上的最大值. MATLAB代码: fun_mutv函数为: function my=fun_mutv(x,y) t1=zer ...

  9. Directx11教程(55) 建立球形和锥形物体

    原文:Directx11教程(55) 建立球形和锥形物体 本教程中,我们新建2个model class,SphereModelClass以及CylinderModelClass,分别用来表示球形和锥形 ...

  10. CSS user-select文本是否可复制

    1. 概述 1.1 说明 在项目过程中,有时候需要网页中内容信息不可被复制进行保护数据信息,故可使用css属性user-select进行控制用户能否选中文本. 1.2 语法 user-select : ...