RecyclerView页眉和页脚

San*_*dra 52 android header footer android-5.0-lollipop android-recyclerview

也许之前已经问过这个问题,但我似乎无法找到准确的答案或解决方案.我开始使用RecyclerView,并使用LinearLayoutManager实现它.现在我想添加自定义页眉和页脚项目,这些项目与我的RecyclerView中的其他项目不同.页眉和页脚不应该是粘性的,我希望它们与其余项目一起滚动.有人可以指出一些例子如何做到这一点或只是分享想法.我会非常感激.谢谢

Bro*_*onx 51

在您的适配器中添加此类:

private class VIEW_TYPES {
        public static final int Header = 1;
        public static final int Normal = 2;
        public static final int Footer = 3;
}
Run Code Online (Sandbox Code Playgroud)

然后像这样覆盖以下方法:

@Override
public int getItemViewType(int position) {

    if(items.get(position).isHeader)
        return VIEW_TYPES.Header;
    else if(items.get(position).isFooter)
        return VIEW_TYPES.Footer;
    else
        return VIEW_TYPES.Normal;

}
Run Code Online (Sandbox Code Playgroud)

现在在onCreateViewHolder方法中根据视图类型扩展您的布局::

@Override
public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {

    View rowView;

    switch (i) {

        case VIEW_TYPES.Normal:
            rowView = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.normal, viewGroup, false);
            break;
        case VIEW_TYPES.Header:
            rowView = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.header, viewGroup, false);
            break;
        case VIEW_TYPES.Footer:
            rowView = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.footer, viewGroup, false);
            break;
        default:
            rowView = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.normal, viewGroup, false);
            break;
    }
    return new ViewHolder (rowView);
}
Run Code Online (Sandbox Code Playgroud)

现在在onBindViewHolder方法中根据视图持有者绑定您的布局:

@Override
    public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int position) {

        int viewType = getItemViewType(position);

        switch(viewType) {

            case VIEW_TYPES.Header: // handle row header
                break;
            case VIEW_TYPES.Footer: // handle row footer
                break;
            case VIEW_TYPES.Normal: // handle row item
                break;

        }

    }
Run Code Online (Sandbox Code Playgroud)

希望这可以提供帮助.

  • 嗨,页眉和页脚也是项目,因此您必须先添加页眉(检查它是否在第一个位置)然后添加您的项目,最后在最后一个位置添加页脚 (2认同)

Dav*_*jak 27

使用ItemDecorations并且不修改任何其他代码非常简单:

recyclerView.addItemDecoration(new HeaderDecoration(this,
                               recyclerView,  R.layout.test_header));
Run Code Online (Sandbox Code Playgroud)

保留一些绘图空间,膨胀您想要绘制的布局并在预留空间中绘制它.

装饰代码:

public class HeaderDecoration extends RecyclerView.ItemDecoration {

    private View mLayout;

    public HeaderDecoration(final Context context, RecyclerView parent, @LayoutRes int resId) {
        // inflate and measure the layout
        mLayout = LayoutInflater.from(context).inflate(resId, parent, false);
        mLayout.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
                View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
    }


    @Override
    public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
        super.onDraw(c, parent, state);
        // layout basically just gets drawn on the reserved space on top of the first view
        mLayout.layout(parent.getLeft(), 0, parent.getRight(), mLayout.getMeasuredHeight());
        for (int i = 0; i < parent.getChildCount(); i++) {
            View view = parent.getChildAt(i);
            if (parent.getChildAdapterPosition(view) == 0) {
                c.save();
                final int height = mLayout.getMeasuredHeight();
                final int top = view.getTop() - height;
                c.translate(0, top);
                mLayout.draw(c);
                c.restore();
                break;
            }
        }
    }

    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
        if (parent.getChildAdapterPosition(view) == 0) {
            outRect.set(0, mLayout.getMeasuredHeight(), 0, 0);
        } else {
            outRect.setEmpty();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 你如何使用它来添加页脚?当 LinearLayoutManager 水平时它也能工作吗? (2认同)

lop*_*ael 8

您可以使用此GitHub库以RecyclerView最简单的方式向您添加页眉或页脚.

您需要在项目中添加HFRecyclerView库,或者也可以从Gradle中获取它:

compile 'com.mikhaellopez:hfrecyclerview:1.0.0'
Run Code Online (Sandbox Code Playgroud)

该库基于@hister的作品

这是图像的结果:

预习


Dar*_*ish 8

recyclerview:1.2.0 引入了ConcatAdapter

ConcatAdapter 是一个新的 RecyclerView Adapter,可以线性组合多个适配器。

如何使用 ConcatAdapter?

将以下依赖项添加到您的build.gradle文件中

androidx.recyclerview:recyclerview:1.2.0-alpha04
Run Code Online (Sandbox Code Playgroud)

然后,如果您有多个适配器,则可以使用以下方法轻松合并它们

  MyAdapter adapter1 = ...;
 AnotherAdapter adapter2 = ...;
 ConcatAdapter merged = new ConcatAdapter(adapter1, adapter2);
 recyclerView.setAdapter(merged);
Run Code Online (Sandbox Code Playgroud)

对于上面的示例,ConcatAdapter 将显示来自适配器 1 和适配器 2 的项目。

在这里您可以找到完整的文档。

在这里找到完整的工作示例。

阅读这篇文章了解更多信息。

在这里你可以找到源代码。


Sea*_*ici 7

如果您只需要一个空白的页眉和页脚,这里有一个非常简单的方法来实现这一点(用 Kotlin 编写):

class HeaderFooterDecoration(private val headerHeight: Int, private val footerHeight: Int) : RecyclerView.ItemDecoration() {
    override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State) {
        val adapter = parent.adapter ?: return
        when (parent.getChildAdapterPosition(view)) {
            0 -> outRect.top = headerHeight
            adapter.itemCount - 1 -> outRect.bottom = footerHeight
            else -> outRect.set(0, 0, 0, 0)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这样称呼它:

recyclerView.addItemDecoration(HeaderFooterDecoration(headerHeightPx, footerHeightPx))
Run Code Online (Sandbox Code Playgroud)