How to show exactly ten rows in RecyclerView

Viewed 2228

I would like to always display exactly ten rows in a RecyclerView. RecyclerView does not have a configurable setting for this. One approach is to calculate the size of each row. I would like the table to take up half the screen and always show 0..10 items within that area. If more than 10 items the user would scrooll to see the items. Right now the default behavior of RecyclerView seems to be to keep pushing everything down as it grows.

2 Answers
@Override
public int getItemCount() {
    if(list.size()>10){
     return 10;
 }else{
 return list.size();
}
}

In your recycler view adapter class return get item count to 10 if size of array or list is greater than 10

Your guess is right it's working with a dynamic computation of row height, here is an example:

Simple class standing for data you want to display:

public class CustomItem {

    private int counter;

    public CustomItem(int counter) {
        this.counter = counter;
    }

    public int getCounter() {
        return counter;
    }

    public void setCounter(int counter) {
        this.counter = counter;
    }
}

And simple layout to display CustomItem in a list:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:background="@android:color/darker_gray">

    <TextView
        android:id="@+id/txvTest"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:padding="8dp"
        android:text="Test"/>

</RelativeLayout>

RecyclerAdapter for this class, you will see that we set row height programmatically in onBindViewHolder method:

public class CustomItemRecyclerAdapter extends RecyclerView.Adapter<CustomItemRecyclerAdapter.SimpleItemViewHolder> {

    private static int NB_OF_ITEM_TO_DISPLAY = 10;
    private List<CustomItem> customItems;
    private Context context;
    private int rowHeight;

    public class SimpleItemViewHolder extends RecyclerView.ViewHolder {

        TextView txvTest;
        RelativeLayout container;

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

            txvTest = (TextView) itemView.findViewById(R.id.txvTest);
            container = (RelativeLayout) itemView;
        }
    }

    public CustomItemRecyclerAdapter(Context context, List<CustomItem> customItems) {
        this.context = context;
        this.customItems = customItems;
    }

    public void setItemHeight(int parentHeightInPx){
        // Height of a row is just parent height divided by number of row to display
        this.rowHeight = parentHeightInPx / CustomItemRecyclerAdapter.NB_OF_ITEM_TO_DISPLAY;
        // Notify adapter because items will need to be redraw to use newly set height
        this.notifyDataSetChanged();
    }

    @Override
    public SimpleItemViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View itemView = LayoutInflater.from(context).inflate(R.layout.custom_item, parent, false);
        return new SimpleItemViewHolder(itemView);

    }

    @Override
    public void onBindViewHolder(SimpleItemViewHolder holder, int position) {
        CustomItem item = customItems.get(position);

        holder.txvTest.setText("Item " + item.getCounter());
        holder.txvTest.setBackgroundColor(item.getCounter());

        // Row size magic is here!
        RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, rowHeight);
        holder.container.setLayoutParams(params);
    }

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

}

Activity layout, with both a TextView used as placeholder for half the screen and the RecyclerView:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:orientation="vertical">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:background="@color/colorAccent"
        android:text="TEST"/>

    <android.support.v7.widget.RecyclerView
        android:id="@+id/a_main_rcv_items"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/colorPrimary"
        android:layout_weight="1"
        android:scrollbars="vertical"/>

</LinearLayout>

And Activity code with comments to understand how it works ;):

public class MainActivity extends AppCompatActivity {

    private RecyclerView recyclerView;
    private CustomItemRecyclerAdapter adapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Link to layout recycler view
        recyclerView = (RecyclerView) findViewById(R.id.a_main_rcv_items);

        // Create a simple linear layout manager and set it to recyclerview
        RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(this);
        recyclerView.setLayoutManager(layoutManager);

        // Create an instance of our custom Adapter
        adapter = new CustomItemRecyclerAdapter(MainActivity.this, generateItems(20));
        // Set this adapter
        recyclerView.setAdapter(adapter);

        // Listen for recycler view layout change event to get its height and then compute and set new rows height
        recyclerView.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
            @Override
            public void onLayoutChange(View view, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
                // Set item height using height of recyclerView
                adapter.setItemHeight(view.getHeight());
                // Need to simulate a scroll to force a redraw of recycler rows with new height... I have not find better for now...
                recyclerView.scrollBy(0,1);
            }
        });
    }

    private List<CustomItem> generateItems(int nb) {
        ArrayList<CustomItem> items = new ArrayList<>(nb);
        for (int i = 1; i < nb + 1; i++) {
            items.add(new CustomItem(i));
        }
        return items;
    }
}
Related