How to make RecyclerView's grid item to have equal height and width?

谁都会走 提交于 2019-12-10 02:19:24

问题


I define my RecyclerView as grid by setting its layout with GridLayoutManger that has a span count of 3 which are already working fine. I also add an item decorator to my recycler view which will manage the spacing between grid items, this also works fine.

public class GridSpacingItemDecoration extends RecyclerView.ItemDecoration {

    private int spanCount;
    private int spacing;
    private boolean includeEdge;

    public GridSpacingItemDecoration(int spanCount, int spacing, boolean includeEdge) {
        this.spanCount = spanCount;
        this.spacing = spacing;
        this.includeEdge = includeEdge;
    }

    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
        int position = parent.getChildAdapterPosition(view); // item position
        int column = position % spanCount; // item column

        if (includeEdge) {
            outRect.left = spacing - column * spacing / spanCount; // spacing - column * ((1f / spanCount) * spacing)
            outRect.right = (column + 1) * spacing / spanCount; // (column + 1) * ((1f / spanCount) * spacing)

            if (position < spanCount) { // top edge
                outRect.top = spacing;
            }
            outRect.bottom = spacing; // item bottom
        } else {
            outRect.left = column * spacing / spanCount; // column * ((1f / spanCount) * spacing)
            outRect.right = spacing - (column + 1) * spacing / spanCount; // spacing - (column + 1) * ((1f /    spanCount) * spacing)
            if (position >= spanCount) {
                outRect.top = spacing; // item top
            }
        }
    }
}

My implementation for adding item decoration to my Recycler View:

mBuddiesGrid = (RecyclerView) findViewById(R.id.buddies_grid);
        mLayoutManager = new GridLayoutManager(getApplicationContext(), 3);
        mBuddiesGrid.addItemDecoration(new GridSpacingItemDecoration(3, (int) dpToPx(10) , true));
        mBuddiesAdapter = new BuddiesGridAdapter(getApplicationContext(), new Buddies());
        mBuddiesGrid.setLayoutManager(mLayoutManager);

My grid item xml layout :

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

    <ImageView
        android:layout_weight="1"
        android:cropToPadding="false"
        android:id="@+id/profile_picture"
        android:scaleType="centerCrop"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <TextView
        android:text="Theodore"
        android:includeFontPadding="false"
        android:textColor="@android:color/black"
        android:id="@+id/name"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
</LinearLayout>

By adding spaces between grid item will adjust the grid item's width which can possibly cause of not getting the proportion size of my item view. What I want to obtain is to resize my grid item height equal to its width dynamically. How can I do it?


回答1:


One way you can ensure equal width/height is to use a custom view which calculates the height based on its width when onMeasure() is called. The neat thing with this is that other than creating the custom view, there's no coding involved.

Here's a custom view extending LinearLayout:

public class SquareLayout extends LinearLayout {

    public SquareLayout(Context context) {
        super(context);
    }

    public SquareLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public SquareLayout(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    protected void onMeasure(int width, int height) {
        // note we are applying the width value as the height
        super.onMeasure(width, width);
    }

}

Here's an altered version of your grid item layout, using the above custom LinearLayout:

<com.yourpackage.name.views.SquareLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <ImageView
        android:id="@+id/profile_picture"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:cropToPadding="false"
        android:scaleType="centerCrop" />

    <TextView
        android:id="@+id/name"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:includeFontPadding="false"
        android:textColor="@android:color/black"
        android:text="Theodore"/>

</com.yourpackage.name.views.SquareLayout>



回答2:


I've done this using ConstraintLayout:

<androidx.constraintlayout.widget.ConstraintLayout
    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="wrap_content"
    >

    <ImageView
        android:layout_width="match_parent"
        android:layout_height="0dp"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintDimensionRatio="1:1"
        tools:src="@drawable/ic_chat_bubble_black_24dp"
        />

</androidx.constraintlayout.widget.ConstraintLayout>



回答3:


You may write code in "onBindViewHolder" function in recycler view holder. In that you can get view tree observer of recycler view and change width or(and) height of recycler item view.



来源:https://stackoverflow.com/questions/32063565/how-to-make-recyclerviews-grid-item-to-have-equal-height-and-width

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