是否有与RecyclerView相同的addHeaderView?

Vic*_*oid 279 android android-view android-recyclerview

我正在为回收者视图寻找相当于addHeaderView的东西.基本上我想要一个带有2个按钮的图像作为标题添加到列表视图中.是否有不同的方法将标题视图添加到回收站视图?指导的一个例子会很有帮助

编辑2(添加片段布局):

添加日志语句后,似乎getViewType只接收到0的位置.这导致onCreateView只加载一个布局:

10-26 16:32:53.766    5449-5449/co.testapp I/logger info? Adapter-> getItemCount: 5
10-26 16:32:53.766    5449-5449/co.testapp I/logger info? Adapter-> getItemCount: 5
10-26 16:32:53.766    5449-5449/co.testapp I/logger info? Adapter-> getItemCount: 5
10-26 16:32:53.766    5449-5449/co.testapp I/logger info? Adapter-> getItemCount: 5
10-26 16:32:53.766    5449-5449/co.testapp I/logger info? Adapter-> getItemCount: 5
10-26 16:32:53.766    5449-5449/co.testapp I/logger info? Adapter-> getItemCount: 5
10-26 16:32:53.766    5449-5449/co.testapp I/logger info? Adapter-> getItemCount: 5
10-26 16:32:53.766    5449-5449/co.testapp I/logger info? Adapter-> getItemCount: 5
10-26 16:32:53.766    5449-5449/co.testapp I/logger info? Adapter-> getItemCount: 5
10-26 16:32:53.766    5449-5449/co.testapp I/logger info? Adapter-> getItemCount: 5
10-26 16:32:53.766    5449-5449/co.testapp I/logger info? Adapter-> getItemCount: 5
10-26 16:32:53.766    5449-5449/co.testapp I/logger info? Adapter-> getItemViewType position: 0
10-26 16:32:53.766    5449-5449/co.testapp I/logger info? Adapter-> getItemViewType position: 0
10-26 16:32:53.766    5449-5449/co.testapp I/logger info? Adapter-> getItemViewType position: 0
10-26 16:32:53.766    5449-5449/co.testapp I/logger info? Adapter-> onCreateViewHolder, viewtype: 0
10-26 16:32:53.766    5449-5449/co.testapp I/logger info? Adapter-> onBindViewHolder, viewType: 0
Run Code Online (Sandbox Code Playgroud)

加载CommentFragment的片段转换:

@Override
public void onPhotoFeedItemClick(View view, int position) {
    if (fragmentManager == null)
        fragmentManager = getSupportFragmentManager();

FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();

    if (view.getId() == R.id.button_comment){
        CommentFragment commentFragment = CommentFragment.newInstance("","", position);
        fragmentTransaction.add(R.id.main_activity, commentFragment,"comment_fragment_tag");
        fragmentTransaction.addToBackStack(Constants.TAG_COMMENTS);
        fragmentTransaction.commit();
    }
}
Run Code Online (Sandbox Code Playgroud)

片段的onCreateView:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {

    View view = inflater.inflate(R.layout.fragment_comment, container, false);
    mRecyclerView = (RecyclerView) view.findViewById(R.id.list_recylclerview);
    mRecyclerView.setLayoutManager(new LinearLayoutManager(_context));
    mRecyclerView.setItemAnimator(new DefaultItemAnimator());
    mAdapter = new CommentAdapter(R.layout.row_list_comments, R.layout.row_header_comments, _context, comments);
    mRecyclerView.setAdapter(mAdapter);
    return view;
}
Run Code Online (Sandbox Code Playgroud)

包含recycleview的片段:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    tools:context="co.testapp.fragments.CommentFragment"
    android:background="@color/white">
        <RelativeLayout
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:orientation="vertical">
            <android.support.v7.widget.RecyclerView
                xmlns:android="http://schemas.android.com/apk/res/android"
                android:id="@+id/list_recylclerview"
                android:layout_width="match_parent"
                android:layout_height="200dp" />
        </RelativeLayout>
</RelativeLayout>
Run Code Online (Sandbox Code Playgroud)

评论行布局:

<?xml version="1.0" encoding="utf-8"?>

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent" android:layout_margin="10dp"
    android:background="@color/white">
    <!--Profile Picture-->
    <ImageView
        android:layout_width="80dp"
        android:layout_height="80dp"
        android:id="@+id/profile_picture"
        android:background="@color/blue_testapp"/>
    <!--Name-->
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="10dp"
        android:text="First Name Last Name"
        android:textSize="16dp"
        android:textColor="@color/blue_testapp"
        android:id="@+id/name_of_poster"
        android:layout_toRightOf="@id/profile_picture"
        />
    <!--Comment-->
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="10dp"
        android:layout_marginTop="-5dp"
        android:text="This is a test comment"
        android:textSize="14dp"
        android:textColor="@color/black"
        android:id="@+id/comment"
        android:layout_below="@id/name_of_poster"
        android:layout_toRightOf="@id/profile_picture"/>
</RelativeLayout>
Run Code Online (Sandbox Code Playgroud)

标题

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:layout_width="match_parent"
              android:layout_height="match_parent">
    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="300dp"
        android:id="@+id/header_photo"
        android:layout_gravity="center_horizontal"/>
</LinearLayout>
Run Code Online (Sandbox Code Playgroud)

适配器代码(感谢myter让我入门):

public class CommentAdapter extends RecyclerView.Adapter<ViewHolder>{

    private final int rowCardLayout;
    public static Context mContext;
    private final int headerLayout;
    private final String [] comments;
    private static final int HEADER = 0;
    private static final int OTHER = 0;

    public CommentAdapter(int rowCardLayout, int headerLayout, Context context, String [] comments) {
        this.rowCardLayout = rowCardLayout;
        this.mContext = context;
        this.comments = comments;
        this.headerLayout = headerLayout;
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
        logger.i("onCreateViewHolder, viewtype: " + i); //viewtype always returns 0 so OTHER layout is never inflated
        if (i == HEADER) {
            View v = LayoutInflater.from(viewGroup.getContext()).inflate(headerLayout, viewGroup, false);
            return new ViewHolderHeader(v);
        }
        else if (i == OTHER){
            View v = LayoutInflater.from(viewGroup.getContext()).inflate(rowCardLayout, viewGroup, false);
            return new ViewHolderComments(v);
        }
        else 
          throw new RuntimeException("Could not inflate layout");
    }

    @Override
    public void onBindViewHolder(ViewHolder viewHolder, int i) {
        logger.i("onBindViewHolder, viewType: " + i);

        if (viewHolder instanceof ViewHolderComments)
            ((ViewHolderComments) viewHolder).comment.setText(comments[i].toString());
        if (viewHolder instanceof ViewHolderHeader)
           ((ViewHolderHeader) viewHolder).header.setImageResource(R.drawable.image2);
        else {
            logger.e("no instance of viewholder found");
        }
    }

    @Override
    public int getItemCount() {
        int count = comments.length + 1;
        logger.i("getItemCount: " + count);
        return count;
    }

    @Override
    public int getItemViewType(int position) {
        logger.i("getItemViewType position: " + position);
        if (position == HEADER)
            return HEADER;
        else
            return OTHER;
    }

    public static class ViewHolderComments extends RecyclerView.ViewHolder {
        public TextView comment;
        public ImageView image;

        public ViewHolderComments(View itemView) {
            super(itemView);
            comment = (TextView) itemView.findViewById(R.id.comment);
            image = (ImageView) itemView.findViewById(R.id.image);
        }
    }

    public static class ViewHolderHeader extends RecyclerView.ViewHolder {
        public final ImageView header;

        public ViewHolderHeader(View itemView){
            super(itemView);
            header = (ImageView) itemView.findViewById(R.id.header_photo);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

使用上面的代码,只显示标题布局,因为viewType始终为0.它看起来像这样.如果我强制其他布局,它看起来像这样:

EC8*_*4B4 449

有一种简单的方法,listview.addHeaderView()但您可以通过在适配器中为标头添加类型来实现此目的.

这是一个例子

public class HeaderAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
    private static final int TYPE_HEADER = 0;
    private static final int TYPE_ITEM = 1;
    String[] data;

    public HeaderAdapter(String[] data) {
        this.data = data;
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        if (viewType == TYPE_ITEM) {
            //inflate your layout and pass it to view holder
            return new VHItem(null);
        } else if (viewType == TYPE_HEADER) {
            //inflate your layout and pass it to view holder
            return new VHHeader(null);
        }

        throw new RuntimeException("there is no type that matches the type " + viewType + " + make sure your using types correctly");
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        if (holder instanceof VHItem) {
            String dataItem = getItem(position);
            //cast holder to VHItem and set data
        } else if (holder instanceof VHHeader) {
            //cast holder to VHHeader and set data for header.
        }
    }

    @Override
    public int getItemCount() {
        return data.length + 1;
    }

    @Override
    public int getItemViewType(int position) {
        if (isPositionHeader(position))
            return TYPE_HEADER;

        return TYPE_ITEM;
    }

    private boolean isPositionHeader(int position) {
        return position == 0;
    }

    private String getItem(int position) {
        return data[position - 1];
    }

    class VHItem extends RecyclerView.ViewHolder {
        TextView title;

        public VHItem(View itemView) {
            super(itemView);
        }
    }

    class VHHeader extends RecyclerView.ViewHolder {
        Button button;

        public VHHeader(View itemView) {
            super(itemView);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

链接到要点 - >这里

  • `private String getItem(int position){return data [position + 1]; 导致NPE.由于我们的位置已增加1,由于标题,我们必须减去1以从我们的数据[]中获取正确的项目.`private String getItem(int position){return data [position - 1]; }` (13认同)
  • @nsL你可以使用这种方法,另外为`GridLayoutManager`添加`setSpanSizeLookup`,所以你的标题将占用所有列 (4认同)
  • 一切似乎都没问题,它应该工作,但是让回收者视图MATCH_PARENT看看是否有任何变化.如果它可能使回收者查看该布局的根(它对性能有好处). (2认同)
  • 如果您的网格只是一个简单的网格,只需使用LinearLayoutManager并在一行中显示项目.它被称为桶行我见过谷歌在他们的一些应用程序中使用它. (2认同)

Dav*_*jak 57

简单且可重复使用 ItemDecoration

静态标题可以很容易地与添加的ItemDecoration无需任何进一步的修改.

// add the decoration. done.
HeaderDecoration headerDecoration = new HeaderDecoration(/* init */);
recyclerView.addItemDecoration(headerDecoration);
Run Code Online (Sandbox Code Playgroud)

装饰也是可重复使用的,因为不需要修改适配器或根本不需要RecyclerView.

下面提供的示例代码将需要一个视图添加到顶部,这可以像其他一切一样膨胀.它看起来像这样:

HeaderDecoration示例

静电为什么?

如果您只需显示文本和图像,此解决方案适合您 - 用户无法进行交互,例如按钮或查看寻呼机,因为它只会被绘制到列表顶部.

空列表处理

如果没有装饰视图,则不会绘制装饰.您仍然需要自己处理一个空列表.(一种可能的解决方法是将虚拟项添加到适配器.)

代码

您可以在GitHub上找到完整的源代码,包括Builder帮助初始化装饰器,或者只使用下面的代码并将自己的值提供给构造函数.

请务必layout_height为您的观点设置正确的.例如match_parent可能无法正常工作.

public class HeaderDecoration extends RecyclerView.ItemDecoration {

    private final View mView;
    private final boolean mHorizontal;
    private final float mParallax;
    private final float mShadowSize;
    private final int mColumns;
    private final Paint mShadowPaint;

    public HeaderDecoration(View view, boolean scrollsHorizontally, float parallax, float shadowSize, int columns) {
        mView = view;
        mHorizontal = scrollsHorizontally;
        mParallax = parallax;
        mShadowSize = shadowSize;
        mColumns = columns;

        if (mShadowSize > 0) {
            mShadowPaint = new Paint();
            mShadowPaint.setShader(mHorizontal ?
                    new LinearGradient(mShadowSize, 0, 0, 0,
                            new int[]{Color.argb(55, 0, 0, 0), Color.argb(55, 0, 0, 0), Color.argb(3, 0, 0, 0)},
                            new float[]{0f, .5f, 1f},
                            Shader.TileMode.CLAMP) :
                    new LinearGradient(0, mShadowSize, 0, 0,
                            new int[]{Color.argb(55, 0, 0, 0), Color.argb(55, 0, 0, 0), Color.argb(3, 0, 0, 0)},
                            new float[]{0f, .5f, 1f},
                            Shader.TileMode.CLAMP));
        } else {
            mShadowPaint = null;
        }
    }

    @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
        mView.layout(parent.getLeft(), 0, parent.getRight(), mView.getMeasuredHeight());

        for (int i = 0; i < parent.getChildCount(); i++) {
            View view = parent.getChildAt(i);
            if (parent.getChildAdapterPosition(view) == 0) {
                c.save();
                if (mHorizontal) {
                    c.clipRect(parent.getLeft(), parent.getTop(), view.getLeft(), parent.getBottom());
                    final int width = mView.getMeasuredWidth();
                    final float left = (view.getLeft() - width) * mParallax;
                    c.translate(left, 0);
                    mView.draw(c);
                    if (mShadowSize > 0) {
                        c.translate(view.getLeft() - left - mShadowSize, 0);
                        c.drawRect(parent.getLeft(), parent.getTop(), mShadowSize, parent.getBottom(), mShadowPaint);
                    }
                } else {
                    c.clipRect(parent.getLeft(), parent.getTop(), parent.getRight(), view.getTop());
                    final int height = mView.getMeasuredHeight();
                    final float top = (view.getTop() - height) * mParallax;
                    c.translate(0, top);
                    mView.draw(c);
                    if (mShadowSize > 0) {
                        c.translate(0, view.getTop() - top - mShadowSize);
                        c.drawRect(parent.getLeft(), parent.getTop(), parent.getRight(), mShadowSize, mShadowPaint);
                    }
                }
                c.restore();
                break;
            }
        }
    }

    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
        if (parent.getChildAdapterPosition(view) < mColumns) {
            if (mHorizontal) {
                if (mView.getMeasuredWidth() <= 0) {
                    mView.measure(View.MeasureSpec.makeMeasureSpec(parent.getMeasuredWidth(), View.MeasureSpec.AT_MOST),
                            View.MeasureSpec.makeMeasureSpec(parent.getMeasuredHeight(), View.MeasureSpec.AT_MOST));
                }
                outRect.set(mView.getMeasuredWidth(), 0, 0, 0);
            } else {
                if (mView.getMeasuredHeight() <= 0) {
                    mView.measure(View.MeasureSpec.makeMeasureSpec(parent.getMeasuredWidth(), View.MeasureSpec.AT_MOST),
                            View.MeasureSpec.makeMeasureSpec(parent.getMeasuredHeight(), View.MeasureSpec.AT_MOST));
                }
                outRect.set(0, mView.getMeasuredHeight(), 0, 0);
            }
        } else {
            outRect.setEmpty();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意: GitHub项目是我个人的游乐场.它不是看一遍测试,这就是为什么没有图书馆.

它有什么作用?

An ItemDecoration是对列表项的附加绘图.在这种情况下,装饰被绘制到第一个项目的顶部.

测量并布置视图,然后将其绘制到第一个项目的顶部.如果添加了视差效果,它也会被剪切到正确的边界.

  • 如何在标题的onClickListener? (3认同)
  • 谢谢,效果很好!使用此方法的唯一缺点是 RecyclerView 中至少需要有 1 行。 (2认同)

Bar*_*ski 43

随意使用我的图书馆,可在这里.

它允许您View为任何RecyclerView使用LinearLayoutManagerGridLayoutManager仅使用简单方法调用创建标头.

在此输入图像描述


小智 25

将显示您在Recycler视图中为项目生成标题.与标头的Recycler视图

步骤1-在gradle文件中添加依赖项.

compile 'com.android.support:recyclerview-v7:23.2.0'
// CardView
compile 'com.android.support:cardview-v7:23.2.0'
Run Code Online (Sandbox Code Playgroud)

Cardview用于装饰目的.

第二步 - 制作三个xml文件.一个用于主要活动.第二个用于标题布局.第三个用于列表项布局.

activity_main.xml中

<android.support.v7.widget.RecyclerView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/my_recycler_view"
    android:scrollbars="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />
Run Code Online (Sandbox Code Playgroud)

header.xml

<android.support.v7.widget.CardView
    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="wrap_content"
    app:cardElevation="2dp">

    <TextView
        android:id="@+id/txtHeader"
        android:gravity="center"
        android:textColor="#000000"
        android:textSize="@dimen/abc_text_size_large_material"
        android:background="#DCDCDC"
        android:layout_width="match_parent"
        android:layout_height="50dp" />

</android.support.v7.widget.CardView>
Run Code Online (Sandbox Code Playgroud)

list.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    xmlns:app="http://schemas.android.com/tools"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <android.support.v7.widget.CardView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:cardElevation="1dp">

        <TextView
            android:id="@+id/txtName"
            android:text="abc"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />

    </android.support.v7.widget.CardView>

</LinearLayout>
Run Code Online (Sandbox Code Playgroud)

第3步 - 创建三个bean类.

Header.java

public class Header extends ListItem {
    private String header;

    public String getHeader() {
        return header;
    }
    public void setHeader(String header) {
        this.header = header;
    }
}
Run Code Online (Sandbox Code Playgroud)

ContentItem.java

public class ContentItem extends ListItem {

    private String name;
    private String rollnumber;

    @Override
    public String getName() {
        return name;
    }

    @Override
    public void setName(String name) {
        this.name = name;
    }

    public String getRollnumber() {
        return rollnumber;
    }

    public void setRollnumber(String rollnumber) {
        this.rollnumber = rollnumber;
    }
}
Run Code Online (Sandbox Code Playgroud)

ListItem.java

public class ListItem {
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    private int id;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }
}
Run Code Online (Sandbox Code Playgroud)

步骤4-创建名为MyRecyclerAdapter.java的适配器

public class MyRecyclerAdapter extends  RecyclerView.Adapter<RecyclerView.ViewHolder> {
    private static final int TYPE_HEADER = 0;
    private static final int TYPE_ITEM = 1;

    //Header header;
    List<ListItem> list;
    public MyRecyclerAdapter(List<ListItem> headerItems) {
        this.list = headerItems;
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        LayoutInflater inflater = LayoutInflater.from(parent.getContext());
        if (viewType == TYPE_HEADER) {
            View v = inflater.inflate(R.layout.header, parent, false);
            return  new VHHeader(v);
        } else {
            View v = inflater.inflate(R.layout.list, parent, false);
            return new VHItem(v);
        }
        throw new IllegalArgumentException();
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        if (holder instanceof VHHeader) {
           // VHHeader VHheader = (VHHeader)holder;
            Header  currentItem = (Header) list.get(position);
            VHHeader VHheader = (VHHeader)holder;
            VHheader.txtTitle.setText(currentItem.getHeader());
        } else if (holder instanceof VHItem) 
            ContentItem currentItem = (ContentItem) list.get(position);
            VHItem VHitem = (VHItem)holder;
            VHitem.txtName.setText(currentItem.getName());
        }
    }

    @Override
    public int getItemViewType(int position) {
        if (isPositionHeader(position))
            return TYPE_HEADER;
        return TYPE_ITEM;
    }

    private boolean isPositionHeader(int position) {
        return list.get(position) instanceof Header;
    }

    @Override
    public int getItemCount() {
        return list.size();
    }

    class VHHeader extends RecyclerView.ViewHolder{
        TextView txtTitle;
        public VHHeader(View itemView) {
            super(itemView);
            this.txtTitle = (TextView) itemView.findViewById(R.id.txtHeader);
        }
    }
    class VHItem extends RecyclerView.ViewHolder{
        TextView txtName;
        public VHItem(View itemView) {
            super(itemView);
            this.txtName = (TextView) itemView.findViewById(R.id.txtName);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

步骤5-在MainActivity中添加以下代码:

public class MainActivity extends AppCompatActivity {
    RecyclerView recyclerView;
    List<List<ListItem>> arraylist;
    MyRecyclerAdapter adapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        recyclerView = (RecyclerView)findViewById(R.id.my_recycler_view);
        LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
        adapter = new MyRecyclerAdapter(getList());
        recyclerView.setLayoutManager(linearLayoutManager);
        recyclerView.setAdapter(adapter);
    }

    private ArrayList<ListItem> getList() {
        ArrayList<ListItem> arrayList = new ArrayList<>();
        for(int j = 0; j <= 4; j++) {
            Header header = new Header();
            header.setHeader("header"+j);
            arrayList.add(header);
            for (int i = 0; i <= 3; i++) {
                ContentItem item = new ContentItem();
                item.setRollnumber(i + "");
                item.setName("A" + i);
                arrayList.add(item);
            }
        }
        return arrayList;
    }

}
Run Code Online (Sandbox Code Playgroud)

函数getList()动态生成标题和列表项的数据.


Gus*_*avo 8

您可以使用SectionedRecyclerViewAdapter库来实现它,它具有"Sections"的概念,其中Section包含页眉,页脚和内容(项目列表).在您的情况下,您可能只需要一个部分,但您可以拥有多个部分:

在此输入图像描述

1)创建自定义Section类:

class MySection extends StatelessSection {

    List<String> myList = Arrays.asList(new String[] {"Item1", "Item2", "Item3" });

    public MySection() {
        // call constructor with layout resources for this Section header, footer and items 
        super(R.layout.section_header, R.layout.section_footer,  R.layout.section_item);
    }

    @Override
    public int getContentItemsTotal() {
        return myList.size(); // number of items of this section
    }

    @Override
    public RecyclerView.ViewHolder getItemViewHolder(View view) {
        // return a custom instance of ViewHolder for the items of this section
        return new MyItemViewHolder(view);
    }

    @Override
    public void onBindItemViewHolder(RecyclerView.ViewHolder holder, int position) {
        MyItemViewHolder itemHolder = (MyItemViewHolder) holder;

        // bind your view here
        itemHolder.tvItem.setText(myList.get(position));
    }
}
Run Code Online (Sandbox Code Playgroud)

2)为项目创建自定义ViewHolder:

class MyItemViewHolder extends RecyclerView.ViewHolder {

    private final TextView tvItem;

    public MyItemViewHolder(View itemView) {
        super(itemView);

        tvItem = (TextView) itemView.findViewById(R.id.tvItem);
    }
}
Run Code Online (Sandbox Code Playgroud)

3)使用SectionedRecyclerViewAdapter设置ReclyclerView

// Create an instance of SectionedRecyclerViewAdapter 
SectionedRecyclerViewAdapter sectionAdapter = new SectionedRecyclerViewAdapter();

MySection mySection = new MySection();

// Add your Sections
sectionAdapter.addSection(mySection);

// Set up your RecyclerView with the SectionedRecyclerViewAdapter
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recyclerview);
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
recyclerView.setAdapter(sectionAdapter);
Run Code Online (Sandbox Code Playgroud)


Val*_*kov 8

如果您想报头在多个列表便于重用,看看版本1.2.0recyclerview库。它引入了ConcatAdapter类,该类将多个适配器连接成一个。因此,您可以创建一个头适配器并轻松地将其与任何其他适配器结合,例如:

myRecyclerView.adapter = ConcatAdapter(headerAdapter, listAdapter)
Run Code Online (Sandbox Code Playgroud)

公告的文章包含一个示例如何显示在页眉和页脚使用加载进度ConcatAdapter

目前,当我发布此答案1.2.0时,库的版本处于 alpha 阶段,因此 api 可能会更改。您可以在此处查看状态。

  • 我知道一路滚动到这里是值得的。所有过时的答案都让我头疼 (3认同)

rus*_*t0R 6

我知道这是一个老问题,但无论如何都想提供答案。

有一个ConcatAdapter文档在这里)可以为您解决问题。您所要做的就是定义标题视图布局并使用单个项目创建一个虚拟适配器在 Kotlin 中实际上只需要几行

class HeaderAdapter(private val inflater: LayoutInflater) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
    
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = object : RecyclerView.ViewHolder(inflater.inflate(yourViewLayoutId, parent, false)) {}

    override fun onBindViewHolder(viewHolder: RecyclerView.ViewHolder, position: Int) {}

    override fun getItemCount() = 1
}
Run Code Online (Sandbox Code Playgroud)

之后,您所要做的就是将标头适配器和原始适配器添加到ConcatAdapter

recyclerView.adapter = ConcatAdapter(headerAdapter, adapter)
Run Code Online (Sandbox Code Playgroud)

有关更多详细信息和高级案例,请参阅文档。


mat*_*ato 5

基于这篇文章,我创建了一个 RecyclerView.Adapter 的子类,它支持任意数量的页眉和页脚。

https://gist.github.com/mheras/0908873267def75dc746

虽然看起来是个解决方案,但我也觉得这个东西应该由LayoutManager来管理。不幸的是,我现在需要它,而且我没有时间从头开始实现 StaggeredGridLayoutManager(甚至没有扩展它)。

我仍在测试它,但如果您愿意,可以尝试一下。如果您发现任何问题,请告诉我。


Dav*_*eas 5

本机API没有这种“ addHeader”功能,但是具有“ addItem”的概念。

我在FlexibleAdapter项目中也可以包括此页眉的特定功能,并可以扩展页脚。我称它为Scrollable页眉和页脚

他们如何工作:

可滚动页眉和页脚是与其他所有页眉一起滚动的特殊项,但它们不属于主要项(业务项),并且始终由主要项旁边的适配器处理。这些项目始终位于第一个和最后一个位置。

在此处输入图片说明

关于它们有很多话要说,最好阅读详细的Wiki页面

此外,FlexibleAdapter允许您创建页眉/节,还可以使它们具有粘性以及数十个其他功能,例如可扩展项,无限滚动,UI扩展等...全部都在一个库中!


Cri*_*tan 5

您可以将标题和RecyclerView放在NestedScrollView中:

<android.support.v4.widget.NestedScrollView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        >

        <include
            layout="@layout/your_header"/>

        <android.support.v7.widget.RecyclerView
            android:id="@+id/list_recylclerview"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            />

    </LinearLayout>

</android.support.v4.widget.NestedScrollView>
Run Code Online (Sandbox Code Playgroud)

为了使滚动正常工作,您需要在RecyclerView上禁用嵌套滚动:

myRecyclerView.setNestedScrollingEnabled(false);
Run Code Online (Sandbox Code Playgroud)

  • 永远不要这样做.这似乎工作正常.但它实际上做的是将滚动传递给srollView.因此,recyclerView本身不会做任何事情.没有视图回收.如果您在recyclerView中获得太多项目,应用程序将崩溃,因为现在它的行为就像一个简单的scrollView. (44认同)
  • 或使用android:nestedScrollingEnabled =“ false” (3认同)
  • @VipulKumar的评论完全正确.当您在另一个scrollview中使用recyclerview时,将不会有任何回收,它将创建所有项目. (2认同)