Android 开源库StickyListHeadersListView来实现ListView列表分组效果

  项目中有一新的需求,要求能像一些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

时间: 2024-09-20 21:16:29

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

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

GitHub Android Libraries Top 100 简介 本文转载于:https://github.com/Freelander/Android_Data/blob/master/Android-Librarys-Top-100.md 本项目主要对目前 GitHub 上排名前 100 的 Android 开源库进行简单的介绍, 至于排名完全是根据 GitHub 搜索 Java 语言选择 (Best Match) 得到的结果, 然后过滤了跟 Android 不相关的项目, 所以排名并

Android 开源库获取途径整理

介绍目前收藏 Android 开源库比较多的 GitHub 项目.网站.Twitter.App 及如何获取最新的 Android 开源库. 一. 网站 1. p.codekk.com 这是一个开源项目自动搜集.方便快速浏览和中英文搜索的网站,目前已经收集了 1000+ Android 开源项目.特点: (1) 按日期以卡片形式显示 随时了解最新开源项目,包含项目简介,体验比 GitHub Timeline 更好. (2) 支持中英文搜索 中英文搜索同样方便,搜索列表同样支持下面介绍的快捷键. (

(android开源库android-gif-drawable)第一篇 eclipse使用这个开源库

如果想显示gif图片 推荐使用Glide开源库 android-gif-drawable我就不推荐了 android开源库android-gif-drawable的使用 android的开源库是用来在android上显示gif图片的.我在网上查了一下,大家说这个框架写的不错,加载大的gif图片 不会内存溢出,于是我就想试试这个开源库,我下了作者的源代码和例子,但是我却跑不起来.不知道为什么,我又到网上去找使用这个开源库的例子发现有一个,我也下载了下来,发现还是跑不起来.我决定自己好好试试这个源代

Android公共库(缓存 下拉ListView 下载管理Pro 静默安装 root运行 Java公

最新内容建议直接访问原文: Android公共库(缓存 下拉ListView 下载管理Pro 静默安装 root运行 Java公共类) 总结的一些android公共库,包含缓存(图片缓存.预取缓存).公共View(下拉及底部加载更多ListView.底部加载更多ScrollView.滑动一页Gallery).及工具类(下载管理.静默安装.shell工具类等等). 具体使用可见总结的一些android公共库.Demo APK地址见TrineaAndroidDemo,主要包括: 一. 缓存类 主要特

Android 开源库——侧滑菜单栏(SlidingMenu)的导入和使用

   一:前言     在今天的学习之前:     首先看看我手机中应用了侧滑菜单栏应用:     知乎:                                                                      知乎日报:                                                  Google音乐:                                                               

Android开源库loopj的android-async-http的 JsonHttpResponseHandler 存在死循环GC_CONCURRENT

我现在用的是 AndroidAsyncHttp 1.4.4 版本,之前遇到一个很奇怪的问题, 当使用 JsonHttpResponseHandler 解析请求的页面出现服务器错误或其他情况返回的内容不是 JSON 字符串时不会调用自己复写实现的 onSuccess 或者 onFailure 方法,将会出现不停打印 GC_CONCURRENT 出现死循环,自己完全没法调试的问题. 后来在 论坛上发了一篇帖子但好多天都没人回复 http://bbs.csdn.net/topics/390734079

Android 开源库和项目 2

1.带尾巴的RecyclerViewPager        特点:1.像viewPager一样滑动一次就滑动一页               2.像画廊gallery一样,滑动一次可以滑动很多页               3.竖向滑动               4.支持点击事件,没有错乱                                                      项目地址:https://github.com/lsjwzh/RecyclerViewPager

Android开源堆叠滑动控件仿探探效果

堆叠滑动控件,类似于社交软件探探的效果,并增加以下扩展: 支持滑动方向控制 支持消失方向控制 支持嵌入到ViewPager等滑动控件 支持内嵌ListView,RecycleView等滑动控件 效果演示 如何使用 xml引入StackCardsView: <com.beyondsw.lib.widget.StackCardsView android:id="@+id/cards" android:layout_width="match_parent" andr

Android非常有用的开源库介绍整理

Android开源库 自己一直很喜欢Android开发,就如博客副标题一样,我想做个好的App. 在摸索过程中,GitHub上搜集了很多很棒的Android第三方库,推荐给在苦苦寻找的开发者,而且我会不定期的更新这篇文章. 本文的其他贡献者: ____sky____ 感谢~ 我的GitHub Android下的优秀开发库数不胜数,在本文中,我列举的多是开发流程中最常用的一些.如果你还想了解更多的Android开源库,可以查看我的GitHub Star,过滤Java选项,每一个库都是我认真查看或者