也许这个问题以前已经被问过,但我似乎找不到确切的答案或解决方案。 我开始使用RecyclerView,并使用LinearLayoutManager实现它。 现在我想添加自定义标题和页脚项,它们与我的RecyclerView中的其他项目不同。 标题和页脚不应该是粘性的,我希望它们随着其他项目一起滚动。 有人能指出如何做到这一点的示例或共享想法吗? 我会非常感激。谢谢
也许这个问题以前已经被问过,但我似乎找不到确切的答案或解决方案。 我开始使用RecyclerView,并使用LinearLayoutManager实现它。 现在我想添加自定义标题和页脚项,它们与我的RecyclerView中的其他项目不同。 标题和页脚不应该是粘性的,我希望它们随着其他项目一起滚动。 有人能指出如何做到这一点的示例或共享想法吗? 我会非常感激。谢谢
在你的适配器中添加这个类:
private class VIEW_TYPES {
public static final int Header = 1;
public static final int Normal = 2;
public static final int Footer = 3;
}
然后像这样覆盖以下方法:
@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;
}
现在在onCreateViewHolder方法中,根据视图类型填充您的布局:
现在在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);
}
现在在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;
}
}
希望这可以帮到你。
使用ItemDecorations非常容易,而且无需修改任何其他代码:
recyclerView.addItemDecoration(new HeaderDecoration(this,
recyclerView, R.layout.test_header));
预留绘图的空间,填充你想要绘制的布局并在预留的空间中进行绘制。
Decoration的代码:
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();
}
}
}
mLayout
是一个视图 - 只需将其添加到视图中即可?可以添加一个getter或修改构造函数。(还要看你在哪里调用findViewById...因为该视图既没有附加到recyclerView也没有附加到片段中) - David Medenjak如果您只需要一个空白的页眉和页脚,以下是一种非常简单的方法(使用 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)
}
}
}
这样称呼它:
recyclerView.addItemDecoration(HeaderFooterDecoration(headerHeightPx, footerHeightPx))
RecyclerView
添加页眉或页脚。compile 'com.mikhaellopez:hfrecyclerview:1.0.0'
此库基于 @hister 的工作
这是一个图像结果:
recyclerview:1.2.0引入了ConcatAdapter
ConcatAdapter是一种新的RecyclerView适配器,可以线性地组合多个适配器。
将以下依赖项添加到您的build.gradle
文件中
androidx.recyclerview:recyclerview:1.2.0-alpha04
如果你有多个适配器,你可以轻松地使用合并它们:
MyAdapter adapter1 = ...;
AnotherAdapter adapter2 = ...;
ConcatAdapter merged = new ConcatAdapter(adapter1, adapter2);
recyclerView.setAdapter(merged);
@Override
public void onBindViewHolder(final PersonViewHolder personViewHolder, int i) {
if(i==List.size()) // Last item in recycle view
personViewHolder.tv_footer.setVisibility(VISIBLE);// Make footer visible now }
@Override
public int getItemViewType(int position) {
return position;
}
对于Header也做同样的操作。 这里i==0,代表列表中的第一个项目。
对我来说,这是最简单的解决方案。
这里是RecyclerView的一些标题项修饰
通过一些修改,你可以将其变成页脚
public class HeaderItemDecoration extends RecyclerView.ItemDecoration {
private View customView;
public HeaderItemDecoration(View view) {
this.customView = view;
}
@Override
public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
super.onDraw(c, parent, state);
customView.layout(parent.getLeft(), 0, parent.getRight(), customView.getMeasuredHeight());
for (int i = 0; i < parent.getChildCount(); i++) {
View view = parent.getChildAt(i);
if (parent.getChildAdapterPosition(view) == 0) {
c.save();
final int height = customView.getMeasuredHeight();
final int top = view.getTop() - height;
c.translate(0, top);
customView.draw(c);
c.restore();
break;
}
}
}
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
if (parent.getChildAdapterPosition(view) == 0) {
customView.measure(View.MeasureSpec.makeMeasureSpec(parent.getMeasuredWidth(), View.MeasureSpec.AT_MOST),
View.MeasureSpec.makeMeasureSpec(parent.getMeasuredHeight(), View.MeasureSpec.AT_MOST));
outRect.set(0, customView.getMeasuredHeight(), 0, 0);
} else {
outRect.setEmpty();
}
}
}
recyclerView.addItemDecoration(new HeaderItemDecoration(aTextView), 0)
。 - Umberto Covino另一种方法是将标题和RecyclerView包装在一个CoordinatorLayout中:
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:elevation="0dp">
<View
android:id="@+id/header"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_scrollFlags="scroll" />
</android.support.design.widget.AppBarLayout>
<android.support.v7.widget.RecyclerView
android:id="@+id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
点击这里。 我扩展了RecyclerView.Adapter,使添加页眉和页脚变得更加容易。
class HFAdapter extends HFRecyclerViewAdapter<String, HFAdapter.DataViewHolder>{
public HFAdapter(Context context) {
super(context);
}
@Override
public DataViewHolder onCreateDataItemViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.data_item, parent, false);
return new DataViewHolder(v);
}
@Override
public void onBindDataItemViewHolder(DataViewHolder holder, int position) {
holder.itemTv.setText(getData().get(position));
}
class DataViewHolder extends RecyclerView.ViewHolder{
TextView itemTv;
public DataViewHolder(View itemView) {
super(itemView);
itemTv = (TextView)itemView.findViewById(R.id.itemTv);
}
}
}
//add header
View headerView = LayoutInflater.from(this).inflate(R.layout.header, recyclerView, false);
hfAdapter.setHeaderView(headerView);
//add footer
View footerView = LayoutInflater.from(this).inflate(R.layout.footer, recyclerView, false);
hfAdapter.setFooterView(footerView);
//remove
hfAdapter.removeHeader();
hfAdapter.removeFooter();