RecyclerView LinearLayoutManager set item count

2020-08-01 19:07发布

问题:

In GridLayoutManager i am able to set span count and that makes the items inside the view to resize to be able to fit that span count horizontally.

I have a LinearLayoutManager and i want to use it the same way, have a fixed number of items visible and resize them to fit.

I use both linear and grid on same view and shows items depending of the screen size. I can't seem to find a way to get both layouts showing the same amount of items.

回答1:

UPDATED

My previous answer was to use ItemsAdapter to set each items width, from the code design stand point this is not the best solution. Proper way to do that is to extend LinearLayoutManager, since it is LayoutManager responsibility to layout item views.

Gist: https://gist.github.com/modjke/b652021679a2ed1935645a18102ab799

Code:

//usage: 
//int itemsPerPage = 7;
//layoutManager = new LinearLayoutPagerManager(context, LinearLayoutManager.HORIZONTAL, false, itemsPerPage);
//recyclerView.setLayoutManager(layoutManager);
public class LinearLayoutPagerManager extends LinearLayoutManager {

private int mItemsPerPage;

public int getItemsPerPage()
{
    return mItemsPerPage;
}


public LinearLayoutPagerManager(Context context, int orientation, boolean reverseLayout, int itemsPerPage) {
    super(context, orientation, reverseLayout);

    mItemsPerPage = itemsPerPage;
}

@Override
public boolean checkLayoutParams(RecyclerView.LayoutParams lp) {
    return super.checkLayoutParams(lp) && lp.width == getItemSize();
}

@Override
public RecyclerView.LayoutParams generateDefaultLayoutParams() {
    return setProperItemSize(super.generateDefaultLayoutParams());
}

@Override
public RecyclerView.LayoutParams generateLayoutParams(ViewGroup.LayoutParams lp) {
    return setProperItemSize(super.generateLayoutParams(lp));
}

private RecyclerView.LayoutParams setProperItemSize(RecyclerView.LayoutParams lp) {
    int itemSize = getItemSize();
    if (getOrientation() == HORIZONTAL) {
        lp.width = itemSize;
    } else {
        lp.height = itemSize;
    }
    return lp;
}

private int getItemSize() {
    int pageSize = getOrientation() == HORIZONTAL ? getWidth() : getHeight();
    return Math.round((float) pageSize / mItemsPerPage);
}

}

PREVIOUS ANSWER

You can set exact item count in your adapter by providing a width for each item. This works only if all your items have equal width, do not forget to set

recyclerView.setHasFixedSize(true);

on your RecyclerView

final static int ITEMS_PER_PAGE = 7;

@Override
public ItemViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    int itemWidth = parent.getWidth() / ITEMS_PER_PAGE;

    View itemView = LayoutInflater.from(parent.getContext())
                    .inflate(R.layout.your_layout, parent, false);

    ViewGroup.LayoutParams layoutParams = itemView.getLayoutParams();
    layoutParams.width = itemWidth;
    itemView.setLayoutParams(layoutParams);
    return new ItemViewHolder(itemView);
}


回答2:

I know this was asked a while ago, but I've found a much simpler solution.

Just create your own LayoutManager and overwrite the method getChildCount()

The result should be something like this:

@Override
public int getChildCount() {
   return super.getChildCount() > 3 ? 3 : super.getChildCount();
}

That way, when you add this LayoutManager to the Recyclerview, it will just display 3 items at a time, no matter how many items the adapter has.

And, if you want a Pager like experience when scrolling just add a SnapHelper

SnapHelper snapHelper = new PagerSnapHelper();
snapHelper.attachToRecyclerView(mRecyclerView);


回答3:

Here is the kotlin version of Mihail Ignatiev's Answer

class LinearLayoutPagerManager(context: Context,orientation: Int,reverseLayout: Boolean, private val itemsPerPage: Int) : LinearLayoutManager(context,orientation,reverseLayout) {

    override fun checkLayoutParams(lp: RecyclerView.LayoutParams?): Boolean {
        return super.checkLayoutParams(lp) && lp!!.width == getItemSize()
    }

    override fun generateDefaultLayoutParams(): RecyclerView.LayoutParams {
        return setProperItemSize(super.generateDefaultLayoutParams())
    }

    override fun generateLayoutParams(lp: ViewGroup.LayoutParams): RecyclerView.LayoutParams {
        return setProperItemSize(super.generateLayoutParams(lp))
    }

    private fun setProperItemSize(lp: RecyclerView.LayoutParams): RecyclerView.LayoutParams {
        val itemSize = getItemSize()
        if (orientation == LinearLayoutManager.HORIZONTAL) {
            lp.width = itemSize
        } else {
            lp.height = itemSize
        }
        return lp
    }

    private fun getItemSize(): Int {
        val pageSize = if (orientation == LinearLayoutManager.HORIZONTAL) width else height
        return Math.round(pageSize.toFloat() / itemsPerPage)
    }


}