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

Saa*_*aad 3 android listview header

我有一个listView,所以我想添加一个粘性标题,以便它粘贴到listView的顶部,当listView中的另一个类别开始时,一个不同的标题取代它的位置,就像联系人一样,其中"a"为一个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;
}


}
Run Code Online (Sandbox Code Playgroud)

需要帮助.....

HpT*_*erm 7

StickyHeader由于StickyListHeadersgit并不能完全符合我的需求,所以我在写自己的时候花了很长时间.然而,StickyListHeaders帮助我理解如何最终使它工作,因此StickyListHeaders值得一提的作者.

必须将许多东西放在一起才能使标头工作.

首先,声明以下内容

private TextView mStickyHeader;
private TextView mStickyHeader2;
private int mCurrentStickyHeaderSection;
Run Code Online (Sandbox Code Playgroud)

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
        }
    });
Run Code Online (Sandbox Code Playgroud)

我假设您已经编写了一个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());
    }
}
Run Code Online (Sandbox Code Playgroud)

最后,布局必须包含a 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>
Run Code Online (Sandbox Code Playgroud)

更新

正如在这里的评论中所要求的那样是对whatIsThePositionOfTheItem和的解释whatIsTheSectionOfTheItem.这些方法必须归还的positionsection给定的项目.

在我的情况下,它很简单,我的数据已经包含sectionposition.实际上,我正在显示文本,并且该文本以section和开头position.所以我只是解析该文本来确定sectionposition.

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


net*_*ein 5

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

图书馆演示图片

你可以在这里查看:https://github.com/emilsjolander/StickyListHeaders