如何在ListView中添加粘性标头?

时间:2013-05-09 08:02:05

标签: android listview header

我有一个listView,所以我想添加一个粘性标题,以便它粘贴在listView的顶部,当列表中的另一个类别开始时,一个不同的标题取代它的位置,就像联系人一样,其中是& #34;"因为Sticky标题位于顶部,直到" b"进来。 有没有图书馆可以做到? 我使用自定义列表适配器来显示我的列表...

这是我的自定义适配器类

public class NewsRowAdapter extends ArrayAdapter<Item>  {

private Activity activity;
private List<Item> items;
private Item objBean;
private int row;

private DisplayImageOptions options;
ImageLoader imageLoader;

public NewsRowAdapter(Activity act, int resource, List<Item> arrayList) {
    super(act, resource, arrayList);
    this.activity = act;
    this.row = resource;
    this.items = arrayList;



    imageLoader = ImageLoader.getInstance();
    File cacheDir1 = StorageUtils.getCacheDirectory(activity);

    ImageLoaderConfiguration config = new
    ImageLoaderConfiguration.Builder(activity)
    .maxImageWidthForMemoryCache(600)
    .maxImageHeightForMemoryCache(400)
    .httpConnectTimeout(5000)
    .httpReadTimeout(20000)
    .threadPoolSize(3)
    .threadPriority(Thread.MIN_PRIORITY + 3)
    .denyCacheImageMultipleSizesInMemory()
    .memoryCache(new UsingFreqLimitedMemoryCache(20000)) // You can pass your own memory cache implementation
    .discCache(new TotalSizeLimitedDiscCache(cacheDir1, 30000)) // You can pass your own disc cache implementation
    .defaultDisplayImageOptions(DisplayImageOptions.createSimple())
    .build();


    ImageLoader.getInstance().init(config);
//              imageLoader = ImageLoader;
//      

   options = new DisplayImageOptions.Builder()
    .showStubImage(R.drawable.icon2x)
    .showImageForEmptyUrl(R.drawable.icon2x).cacheInMemory()
    .cacheOnDisc().build();
//imageLoader = ImageLoader.getInstance();

}

@Override
public Item getItem(int position)
{
    return items.get(position);
}

@Override
public int getCount()
{
    return items.size();
}

@Override
public int getViewTypeCount()
{
    return 3;
}

@Override
public int getItemViewType(int position)
{
    Item item = items.get(position);
    if (item.isHeader())
    {
        return TYPE_SECTION_HEADER;
    }
    else
    {
        return TYPE_LIST_ITEM;
    }
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
    View view = convertView;
    ViewHolder holder;
    if (view == null) {
        LayoutInflater inflater = (LayoutInflater) activity
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        view = inflater.inflate(row, null);

        holder = new ViewHolder();
        view.setTag(holder);
    } else {
        holder = (ViewHolder) view.getTag();
    }

    if ((items == null) || ((position + 1) > items.size()))
        return view;

    objBean = items.get(position);

    holder.tvName = (TextView) view.findViewById(R.id.title);
    holder.tvId = (TextView) view.findViewById(R.id.id);
    holder.tvFlag = (TextView) view.findViewById(R.id.flag);
    holder.tvimageurl=(TextView) view.findViewById(R.id.imageurl);
    holder.tvGender = (ImageView) view.findViewById(R.id.image);
    //holder.tvAge = (TextView) view.findViewById(R.id.tvage);
    holder.pbar = (ProgressBar) view.findViewById(R.id.pbar);
    if (holder.tvName != null && null != objBean.getName()
            && objBean.getName().trim().length() > 0) {
        holder.tvName.setText(Html.fromHtml(objBean.getName()));
    }
    if (holder.tvId != null && null != objBean.getId()
            && objBean.getId().trim().length() > 0) {
        holder.tvId.setText(Html.fromHtml(objBean.getId()));

    }
    if (holder.tvFlag != null && null != objBean.getFlag()
            && objBean.getFlag().trim().length() > 0) {
        holder.tvFlag.setText(Html.fromHtml(objBean.getFlag()));

    }

    if (holder.tvimageurl != null && null != objBean.getGender()
            && objBean.getFlag().trim().length() > 0) {
        holder.tvimageurl.setText(Html.fromHtml(objBean.getGender()));

    }

    //if (holder.tvBDate != null && null != objBean.getBirthdate()
    //      && objBean.getBirthdate().trim().length() > 0) {
    //  holder.tvBDate.setText(Html.fromHtml(objBean.getBirthdate()));
    //}
    if (holder.tvGender != null) {
        if (null != objBean.getGender()
                && objBean.getGender().trim().length() > 0) {
            final ProgressBar pbar = holder.pbar;


            imageLoader.displayImage(objBean.getGender(), holder.tvGender,
                    options, new ImageLoadingListener() {

                        @Override
                        public void onLoadingComplete() {
                            pbar.setVisibility(View.INVISIBLE);

                        }


                        @Override
                        public void onLoadingFailed() {
                            pbar.setVisibility(View.INVISIBLE);
                        }


                        @Override
                        public void onLoadingStarted() {
                            pbar.setVisibility(View.INVISIBLE);

                        }
                    });

        } else {
            holder.tvGender.setImageResource(R.drawable.icon2x);
        }
    }


    return view;
}

public class ViewHolder {
    public TextView tvimageurl;
    public TextView tvFlag;
    public TextView tvId;
    public ProgressBar pbar;
    public TextView tvName, tvCity, tvBDate, tvAge;
    ImageView tvGender;
}


}

需要帮助.....

2 个答案:

答案 0 :(得分:7)

由于StickyHeader git与我的需求不完全匹配,因此我在编写自己的StickyListHeaders时遇到了很长时间。但是,StickyListHeaders帮助我理解如何最终使它工作,因此StickyListHeaders的作者值得一提。

必须将许多事情放在一起才能使标头工作。

首先,声明以下内容

private TextView mStickyHeader;
private TextView mStickyHeader2;
private int mCurrentStickyHeaderSection;
onActivityCreated

中的

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    ...     
    mCurrentStickyHeaderSection = -1;

    mStickyHeader = (TextView) getView().findViewById(R.id.textview_sticky_header_section);
    mStickyHeader2 = (TextView) getView().findViewById(R.id.textview_sticky_header_section_2);

    mListView = (ListView) getView().findViewById(R.id.listView_with_sticky_headers); 
    mListView.setOnScrollListener(new OnScrollListener() {
        @Override
        public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
            updateStickyHeader(firstVisibleItem);
        }

        @Override
        public void onScrollStateChanged(AbsListView arg0, int arg1) {
            // TODO Auto-generated method stub
        }
    });

我假设您已经编写了一个带有段索引的CustomAdapter,并且只关注粘性标题。

以下方法包含了粘贴标头所需的全部内容。棘手的部分是确定firstVisibleItem是否是标题(pos = -1)和相应的部分。这部分可能需要您几次才能使其正常工作。

private void updateStickyHeader(int firstVisibleItem) {
    // here is the tricky part. You have to determine pos and section
    // pos is the position within a section pos = -1 means it's the header of the section        
    // you have to determine if firstVisibleItem is a header or not
    // you also have to determine the section to which belongs the first item
    int pos = whatIsThePositionOfTheItem[firstVisibleItem];
    int section = whatIsTheSectionOfTheItem[firstVisibleItem];

    if (section != mCurrentStickyHeaderSection) {
        mStickyHeader.setText("Your_Previous_Section_Text");
        mStickyHeader2.setText("Your_Next_Section_Text");
        mCurrentStickyHeaderSection = section;
    }

    int stickyHeaderHeight = mStickyHeader.getHeight();
    if (stickyHeaderHeight == 0) {
        stickyHeaderHeight = mStickyHeader.getMeasuredHeight();
    }

    View SectionLastView = mListView.getChildAt(0);
    if (SectionLastView != null && pos == -1 && SectionLastView.getBottom() <= stickyHeaderHeight) {
        int lastViewBottom = SectionLastView.getBottom();
        mStickyHeader.setTranslationY(lastViewBottom - stickyHeaderHeight);
        mStickyHeader2.setTranslationY(lastViewBottom - stickyHeaderHeight + mStickyHeader.getHeight());
    } else if (stickyHeaderHeight != 0) {
        mStickyHeader.setTranslationY(0);
        mStickyHeader2.setTranslationY(mStickyHeader.getHeight());
    }
}

最后,布局必须包含FrameLayout,看起来应该是

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    //this textview is just a global title of your listview if you need one but can be remove
    <TextView
        android:id="@+id/textview_title"
        style="?android:attr/listSeparatorTextViewStyle"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingLeft="6dp"
        android:paddingRight="6dp"
        android:textIsSelectable="false" />

    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >

        <TextView
            android:id="@+id/textview_sticky_header_section"
            style="?android:attr/listSeparatorTextViewStyle"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:paddingLeft="6dp"
            android:paddingRight="6dp"
            android:textIsSelectable="false" />

        <TextView
            android:id="@+id/textview_sticky_header_section_2"
            style="?android:attr/listSeparatorTextViewStyle"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:paddingLeft="6dp"
            android:paddingRight="6dp"
            android:textIsSelectable="false" />
    </FrameLayout>

    <ListView
        android:id="@+id/listView_with_sticky_header"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:fastScrollEnabled="true"
        android:longClickable="true" >
    </ListView>

</LinearLayout>

<强>更新

正如评论中所述,是对whatIsThePositionOfTheItemwhatIsTheSectionOfTheItem的解释。这些方法必须返回给定项目的positionsection

就我而言,这很简单,我的数据已包含sectionposition。实际上,我正在显示文字,该文字以sectionposition开头。因此,我只是解析该文本以确定sectionposition

对于其他人来说,很难举出一个例子,因为它实际上取决于你所展示的内容。但是长话短说whatIsThePositionOfTheItemwhatIsTheSectionOfTheItem必须返回给定项目的位置和部分。您可能需要在列表中填入列表中每个项目的positionsection,并从该表中获取positionsection

答案 1 :(得分:5)

有一个完全具有该名称的库可以实现您想要的:

Library demo image

您可以在此处查看:https://github.com/emilsjolander/StickyListHeaders