How to show exact number of items in RecyclerView?

One solution is to set width of each child programmatically like.

view.getLayoutParams().width = getScreenWidth() / VIEWS_COUNT_TO_DISPLAY;

And the screen size like this:

DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics).widthPixels;

The solution that I have provided below helps in displaying pre-defined number of child items('numOfCardViewItemsOnScreen') in a recyclerView on the screen, also calculates the margins between these items to space them evenly, by taking into account the supplied margin between the items & recyclerView's end margin's (i.e, 'marginAtRecyclerViewsEnds')

Note that I have tested this in devices between 5.0" to 7.0" inch devices & obtained consistent result.

private fun configureCardViewLayoutParams(cardView: CardView, numOfCardViewItemsOnScreen: Int, marginAtRecyclerViewsEnds: Float, marginLeftParam: Float, marginRightParam: Float, marginTopParam: Float, marginBottomParam: Float): ViewGroup.MarginLayoutParams {
    val numOfGapsInBetweenItems = numOfCardViewItemsOnScreen - 1
    var combinedGapWidth = ((marginLeftParam + marginRightParam) * numOfGapsInBetweenItems) + (marginAtRecyclerViewsEnds * 2)
    //Provided approx. adjustment of 2dp to prevent the extreme edges of the card from being cut-off
    combinedGapWidth += 2
    val combinedGapWidthDp = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, combinedGapWidth, cardView.resources.displayMetrics).toInt()
    //Since margins/gaps are provided in-between the items, these have to be taken to account & subtracted from the width in-order to obtain even spacing
    cardView.layoutParams.width = (getScreenWidth(cardView.context as MainActivity) - combinedGapWidthDp) / numOfCardViewItemsOnScreen

    //Margins in-between the items
    val marginLeftOfItem = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, marginLeftParam, cardView.resources.displayMetrics).toInt()
    val marginRightOfItem = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, marginRightParam, cardView.resources.displayMetrics).toInt()
    val marginTopOfItem = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, marginTopParam, cardView.resources.displayMetrics).toInt()
    val marginBottomOfItem = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, marginBottomParam, cardView.resources.displayMetrics).toInt()

    //Providing the above margins to the CardView
    val cardViewMarginParams: ViewGroup.MarginLayoutParams = cardView.layoutParams as ViewGroup.MarginLayoutParams
    cardViewMarginParams.setMargins(marginLeftOfItem, marginTopOfItem, marginRightOfItem, marginBottomOfItem)
    return cardViewMarginParams
}

The below method helps in calculating the screenWidth as the name implies

private fun getScreenWidth(activity: MainActivity): Int {
    var width: Int = 0
    val size = Point()
    val windowManager = activity.getSystemService(Context.WINDOW_SERVICE) as WindowManager
    width = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
        val bounds = windowManager.currentWindowMetrics.bounds
        bounds.width()
    } else {
        val display: Display? = windowManager.defaultDisplay
        display?.getSize(size)
        size.x
    }
    return width
}

Finally inside onCreateViewHolder, utilise the configureCardViewLayoutParams method depicted above & pass in the desired arguments

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyRecyclerViewHolder {
    val view = LayoutInflater.from(parent.context).inflate(R.layout.row_item_layout, parent, false)
    view.layoutParams = configureCardViewLayoutParams(view as CardView, 4, 12f, 4f, 4f, 8f, 8f)
    return MyRecyclerViewHolder(view)
}

For the sake of quick understanding, I have also provided the child items xml layout (row_item_layout.xml) So as you can see from the below xml, the root view of our child item layout is a CardView.

<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView
    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"
    android:elevation="5dp"
    android:foregroundGravity="center">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <ImageView
            android:id="@+id/imageView1"
            android:layout_width="30dp"
            android:layout_height="28dp"
            android:layout_marginTop="22dp"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            tools:src="@tools:sample/avatars" />

        <TextView
            android:id="@+id/textView1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="7dp"
            android:layout_marginTop="18dp"
            android:layout_marginEnd="7dp"
            android:layout_marginBottom="16dp"
            android:ellipsize="end"
            android:gravity="center"
            android:maxLines="2"
            android:text="@{accountOptionsModel.title}"
            android:textSize="14sp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/imageView1"
            tools:text="@tools:sample/full_names" />
    </androidx.constraintlayout.widget.ConstraintLayout>


</androidx.cardview.widget.CardView>

There is no special logic within the getCount(), just return the entire list size

override fun getItemCount(): Int = myList.size

Below screenshots are from devices of 5.0", 6.3", 7.02" respectively

Consists of 5.0", 6.3", 7.02" respectively

enter image description here


In a general way to achieve this there is no straight forward property that recycler view comes with.

The way this is achievable is by sending in the parent width to the adapter..

In a suedo way..

    Parent width = parent container width;

    InitialiseRecyclerAdapter(parent width) {
         on create view holder {
                 Set the width of ur item layout with a width that divides ur parent width in equal parts;
          }
}

I have done the above task as following approach, please refers the following code

On my onCreateViewHolder() method of my RecycleView Adapter, i find out the width of the screen and than divided into 3 sections.Please check it once.

@Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View itemView = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.MY_ITEM_TO_INFALTE, parent, false);

        itemView.getLayoutParams().width = (int) (getScreenWidth() / NUMBERS_OF_ITEM_TO_DISPLAY); /// THIS LINE WILL DIVIDE OUR VIEW INTO NUMBERS OF PARTS

        return new MyCreationItemAdapter.MyViewHolder(itemView);
    }

From above code getScreenWidth() method which we use on above is as follow,please check it.

public int getScreenWidth() {

        WindowManager wm = (WindowManager) activity.getSystemService(Context.WINDOW_SERVICE);
        Display display = wm.getDefaultDisplay();
        Point size = new Point();
        display.getSize(size);

        return size.x;
    }