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


更多相关文章

  1. Android中Okhttp,Volley,Retrofit网络框架优缺点及对比
  2. 短信的收发及在android模拟器之间实践(3)
  3. Android(安卓)Databinding技术由浅入深(4)------Databinding进阶An
  4. Android整合网上资源以及个人对GreenDao数据库框架的理解与使用(
  5. Android(安卓)Parcelable和Serializable的区别
  6. Android官方架构组件介绍之LifeCycle
  7. Android非常强大的第三方数据库LitePal
  8. Android(安卓)ListView基础篇
  9. android访问php webservice简单一例

随机推荐

  1. Android之使用picker打开相应的app
  2. Android Web Server
  3. 第11章(1)---Android的线程和线程池
  4. Android改变文件的权限
  5. 了解 uri, content provide,包括 data and
  6. 【Android】数据存储之SQLite
  7. Android关于LinearLayout和RelativeLayou
  8. Android的介绍
  9. 百度招聘Android客服端(1)
  10. 在Android(安卓)studio中建立Java工程