Recyclerview with a different last item as “add” item

僤鯓⒐⒋嵵緔 提交于 2020-01-03 08:51:07

问题


I am trying to create a layout with a list of items, where the last item is a button to add a new item of the "standard" type. It should be something like Google Keep lists, with a permanent "add" item at the end of the list. Google Keep list example

I have tried two ways to achieve it. The first one is very simple, but I find a problem. The second one is not that simple, and the performance is worse. In addition, I think with the second way I am using RecyclerView in a way that is not intended, and I think I could find performance issues due to that.

How would you do it?

First way

The first one should be the easiest, that is adding in the same layout a RecyclerView followed by a ViewGroup containing the "add" item. As parent I use a LinearLayout with the RecyclerView and an Include tag referenced to the "add" item layout. This is actually inside a CoordinatorLayout because I use a BottomSheet to pick the new "standard" item to be added.

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/colorBackgroundLight"
    android:orientation="vertical">

    <!-- Other Views -->

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

    <include
        layout="@layout/itemAdd"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
</LinearLayout>

The problem is that the "add" item is positioned below the RecyclerView, and both disappear when the RecyclerView is empty.

Second way

Then I tried the second way, that is creating the "add" item from the RecyclerView.Adapter. Doing it this way is working so far, although I am sure that this cannot be the best way to do it. I will paste the code and below it I explain the reasoning behind.

Adapter

public class MyAdapter extends RecyclerView.Adapter<MyViewHolder> {
    private final LayoutInflater mInflater;
    private BottomSheetBehavior bottomSheetBehavior;
    private int count = 0;
    private final List<Object> mDataset;

    // Standard constructor. I get the mInflater from Context here

    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        final View itemView;
        if (count>=mDataset.size()) {
            itemView = mInflater.inflate(R.layout.item_add, parent, false);
            itemView.setTag("ADD");
        }
        else{
            itemView = mInflater.inflate(R.layout.item_sandard, parent, false);
            itemView.setTag(null);
        }
        count += 1;
        return new MyViewHolder(itemView, bottomSheetBehavior);
    }

    @Override
    public void onBindViewHolder(MyViewHolder holder, int position) {
        if (position<mDataset.size()) {
            final Object object = mDataset.get(position);
            holder.bind(object); // I bind it on the ViewHolder
        }
    }

    @Override
    public int getItemCount() {
        return mDataset.size()+1;
    }
}

To do so I have created a private variable mCount that I use to count the amount of ViewHolder created. Then I start my onCreateViewHolder method with an if statment, where I check if I have already created the ViewHolderfor the last "standard" item of my mDataset. Depending on it I inflate the "standard" view or the "add" view. Then I would have to be updating mCount values each time the user adds or deletes an item (not implemented yet). I also add a tag to the view to get which View I am using at the ViewHolder without big troubles.

I have to change the onBindViewHolder because in case I am inflating the "add" view, I don't want to bind anything as the view is already defined.

I also have to modify the getItemCount method to return the size of my mDataset plus 1 for the "add" view.

Finally I have to be sending the BottomSheetBehaviour instance all the way to the ViewHolder through the Adapter to be able to open the BottomSheet with the onClick defined in the ViewHolder, which I don't think is very efficient.

ViewHolder

public class MyViewHolder extends RecyclerView.ViewHolder{
    private final TextView mText;
    private final ImageButton mButton;


    public MyViewHolder(View itemView, final BottomSheetBehavior bottomSheetBehavior) {
        super(itemView);

        if (itemView.getTag() == "ADD"){
            mText = null;
            mButton = null;
            // I also set the OnClickListener to open the BottomSheet
        }
        else{
            // Set mText and an OnClickListener to the button. I use the Adapter here
        }
    }

    // The bind method goes here 
}

Here I get the tag from the View, and depending on it I set a different listener.

来源:https://stackoverflow.com/questions/35927007/recyclerview-with-a-different-last-item-as-add-item

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!