简体   繁体   English

设置粘性标题和项目布局Recyclerview

[英]Set Sticky Header and Items Layouts Recyclerview

I want to build a complex layout using recyclerview android. 我想使用recyclerview android构建复杂的布局。 In the layout, I want to have a camera button to the top left fixed and a recyclerview wrapped around it with gallery images. 在布局中,我想固定一个相机按钮到左上角,并用图库图像将recyclerview包裹在其周围。 I have checked flexbox layout manager for recyclerview but it doesn't seem to match my use-case. 我已经为flexbox layout manager for recyclerview检查了flexbox layout manager for recyclerview但是它似乎与我的用例不匹配。

I want the header to be non-repeating and not to scroll with other items vertically. 我希望标题不重复并且不要垂直滚动其他项目。 Here's the layout for the header: 这是标题的布局:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/shareLayout"
android:layout_width="185dp"
android:layout_height="135dp"
android:layout_below="@id/trendingToolbar"
android:background="@color/black">

<ImageView
    android:id="@+id/cameraShareIV"
    android:layout_width="60dp"
    android:layout_height="60dp"
    android:layout_centerHorizontal="true"
    android:layout_marginTop="10dp"
    app:srcCompat="@drawable/camera_white" />

<RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_below="@id/cameraShareIV"
    android:layout_centerHorizontal="true">

    <TextView
        android:id="@+id/infoTxt"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_marginLeft="20dp"
        android:gravity="center_horizontal"
        android:text="@string/share_pic_video"
        android:textColor="@android:color/white"
        android:textSize="13sp"
        android:textStyle="bold" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/infoTxt"
        android:layout_marginLeft="16dp"
        android:text="@string/share_timeout_txt"
        android:textColor="@color/colorPrimaryDark"
        android:textSize="11sp"
        android:textStyle="bold" />

</RelativeLayout>

and in my activity, here's the XML: 在我的活动中,这是XML:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="base.android.com.thumbsapp.UI.Fragments.TrendingFragment">

<include layout="@layout/trending_toolbar"
    android:id="@+id/trendingToolbar"/>

<android.support.v7.widget.RecyclerView
    android:id="@+id/trendingRV"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_below="@id/trendingToolbar"/>

Previously, I had the header inside the activity XML but had no way to wrap a recyclerview around it. 以前,我在活动XML中包含标头,但无法在其周围包装recyclerview。 So, I have decide to use an adapter like below: 因此,我决定使用如下所示的适配器:

public class TrendingAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

private static final String TAG = TrendingAdapter.class.getSimpleName();

private Context context;
private List<Trending> itemList;

private static final int HEADER = 0;
private static final int ITEMS = 1;

@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View v;
    switch (viewType){
        case HEADER:
           v = LayoutInflater.from(parent.getContext()).inflate(R.layout.trending_header, parent, false);
           return new TrendingHeaderViewHolder(v);
        case ITEMS:
            v = LayoutInflater.from(parent.getContext()).inflate(R.layout.trending_items_layout, parent, false);
            return new TrendingItemsViewHolder(v);
    }
    return null;
}

@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
    Trending tr = itemList.get(position);
    if (holder instanceof TrendingHeaderViewHolder){
        ((TrendingHeaderViewHolder) holder).cameraShareIV.setOnClickListener( view -> {
            // TODO: 4/2/2018   select image from gallery
        });
    } else if (holder instanceof TrendingItemsViewHolder){
        // TODO: 4/2/2018 populate gallery items here with picasso  
    }
}

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

@Override
public int getItemViewType(int position) {
    return super.getItemViewType(position);
}
}

I'm confused how to make the header stick and also what to do for getItemViewType method . 我很困惑如何使标题保持getItemViewType method以及如何对getItemViewType method

Is this the right way to approach this? 这是解决这个问题的正确方法吗? Can anyone help out? 有人可以帮忙吗? Thanks. 谢谢。

To make things simple i suggest you to look into this library 为了简单起见,我建议您研究一下这个

In your XML Place RecylerView into StickyHeaderView ,choose horizontal or vertical orientation for your RecylerView 在你的XML将RecylerView到StickyHeaderView ,选择适合您的水平或垂直方向RecylerView

 <tellh.com.stickyheaderview_rv.StickyHeaderView
        android:id="@+id/stickyHeaderView"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <android.support.v7.widget.RecyclerView
            android:id="@+id/recyclerView"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="@android:color/white"
            android:scrollbars="vertical" />
    </tellh.com.stickyheaderview_rv.StickyHeaderView>

Create data bean class for each item type in RecyclerView. 在RecyclerView中为每种项目类型创建数据bean类。 They should extend DataBean . 他们应该扩展DataBean Override the method public boolean shouldSticky() to decide whether the item view should be suspended on the top. 重写方法public boolean shouldSticky()来决定是否应将项目视图挂在顶部。

public class User extends DataBean {
    private String login;
    private int id;
    private String avatar_url;
    private boolean shouldSticky;
    @Override
    public int getItemLayoutId(StickyHeaderViewAdapter adapter) {
        return R.layout.item_user;
    }
    public void setShouldSticky(boolean shouldSticky) {
        this.shouldSticky = shouldSticky;
    }
    // Decide whether the item view should be suspended on the top.
    @Override
    public boolean shouldSticky() {
        return shouldSticky;
    }
}
public class ItemHeader extends DataBean {
    private String prefix;
    @Override
    public int getItemLayoutId(StickyHeaderViewAdapter adapter) {
        return R.layout.header;
    }
    @Override
    public boolean shouldSticky() {
        return true;
    }
}

Create ViewBinder to bind different type views with specific data beans. 创建ViewBinder以将不同类型的视图与特定数据bean绑定。 As you see, provideViewHolder(View itemView) corresponds for onCreateViewHolder in RecyclerView , and bindView corresponds for onBindViewHolder in RecyclerView . 如您所见, provideViewHolder(View itemView)对应于RecyclerView onCreateViewHolder ,而bindView对应于RecyclerView onBindViewHolder

public class ItemHeaderViewBinder extends ViewBinder<ItemHeader, ItemHeaderViewBinder.ViewHolder> {
    @Override
    public ViewHolder provideViewHolder(View itemView) {
        return new ViewHolder(itemView);
    }
    @Override
    public void bindView(StickyHeaderViewAdapter adapter, ViewHolder holder, int position, ItemHeader entity) {
        holder.tvPrefix.setText(entity.getPrefix());
    }
    @Override
    public int getItemLayoutId(StickyHeaderViewAdapter adapter) {
        return R.layout.header;
    }
    static class ViewHolder extends ViewBinder.ViewHolder {
        TextView tvPrefix;
        public ViewHolder(View rootView) {
            super(rootView);
            this.tvPrefix = (TextView) rootView.findViewById(R.id.tv_prefix);
        }
    }
}

Instantiate StickyHeaderViewAdapter for RecyclerView and register ViewBinders for each item types. RecyclerView实例化StickyHeaderViewAdapter并为每种项目类型注册ViewBinders

rv = (RecyclerView) findViewById(R.id.recyclerView);
    rv.setLayoutManager(new LinearLayoutManager(this));
    List<DataBean> userList = new ArrayList<>();
    adapter = new StickyHeaderViewAdapter(userList)
            .RegisterItemType(new UserItemViewBinder())
            .RegisterItemType(new ItemHeaderViewBinder());
    rv.setAdapter(adapter);

对于此布局,我建议更好的选择是使用此标头视图https://github.com/edubarr/header-decor

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM