项目中有一新的需求,要求能像一些Android机带“联系人列表”一样,数据可以自动分组,且在列表滑动过程中,列表头固定在顶部,效果图如下:
下面就带大家实现上面的效果, 首先,我们要介绍的一个重要的开源库:StickyListHeaders,它的Github地址是:https://github.com/emilsjolander/StickyListHeaders, 使用该库,可以更加方便的实现ListView数据分组,且Header固定在顶部。
首先,把github上的项目下载下来,加压后,可看到其中有一个library库,我们需要将该库(Module)导入到新建的项目中,并在自己的Module引入该Library。
项目建成后,开始使用该库进行开发:
1. 布局中引入StickyListHeadersListView:
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 + '\'' +
'}';
}
}
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 mPlanDetails;
public LangyaAdapter(Activity context, List 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;
}
}
说明:
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 mLangyaDatas;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
list = (StickyListHeadersListView) findViewById(R.id.list);
mLangyaDatas = new ArrayList();
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", "情殇", "情殇情殇情殇情殇情殇情殇情殇", "美人榜"));
}
}
有个地方需要着重说明,那就是在初始化数据时,数据必须proj_id必须按分组排列,即,不要将proj_id不同的数据参差着放在集合中,否则容易造成列表显示多组相同组名的数据。
对StickyListHeadersListView其余的操作(点击、长按),和普通的ListView一致,包括在xml中设置的属性也是一致的。
如此这般,便可实现上述的效果了!
源码下载地址(免费):http://download.csdn.net/detail/zuiwuyuan/9274693