当前位置: 首页 > 知识库问答 >
问题:

装饰回收器视图(使用 GridLayoutManager)以显示项目之间的分隔线

斜和硕
2023-03-14

什么是最好的和最简单的方法来装饰回收器视图有这样的外观

这里的主要挑战是仅在项目之间使用分隔线,而不是在项目和屏幕的左/右边框之间划分。

有什么想法吗?

共有3个答案

闾丘博超
2023-03-14

您可能已经得到了答案,但我仍在发布我的解决方案,以帮助其他人。这可以通过传递方向用于垂直、水平列表或栅格视图。

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.View;

public class DividerItemDecoration extends RecyclerView.ItemDecoration {

    private static final int[] ATTRS = new int[]{
            android.R.attr.listDivider
    };

    public static final int HORIZONTAL_LIST = LinearLayoutManager.HORIZONTAL;
    public static final int VERTICAL_LIST = LinearLayoutManager.VERTICAL;
    public static final int GRID = 2;

    private Drawable mDivider;

    private int mOrientation;

    public DividerItemDecoration(Context context, int orientation) {
        final TypedArray a = context.obtainStyledAttributes(ATTRS);
        mDivider = a.getDrawable(0);
        a.recycle();
        setOrientation(orientation);
    }

    public void setOrientation(int orientation) {
        if (orientation != HORIZONTAL_LIST && orientation != VERTICAL_LIST && orientation != GRID) {
            throw new IllegalArgumentException("invalid orientation");
        }
        mOrientation = orientation;
    }

    @Override
    public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
        if (mOrientation == VERTICAL_LIST) {
            drawVertical(c, parent);
        } else if(mOrientation == HORIZONTAL_LIST){
            drawHorizontal(c, parent);
        } else {
            drawVertical(c, parent);
            drawHorizontal(c, parent);
        }
    }

    public void drawVertical(Canvas c, RecyclerView parent) {
        if (parent.getChildCount() == 0) return;

        final int left = parent.getPaddingLeft();
        final int right = parent.getWidth() - parent.getPaddingRight();

        final View child = parent.getChildAt(0);
        if (child.getHeight() == 0) return;

        final RecyclerView.LayoutParams params =
                (RecyclerView.LayoutParams) child.getLayoutParams();
        int top = child.getBottom() + params.bottomMargin + mDivider.getIntrinsicHeight();
        int bottom = top + mDivider.getIntrinsicHeight();

        final int parentBottom = parent.getHeight() - parent.getPaddingBottom();
        while (bottom < parentBottom) {
            mDivider.setBounds(left, top, right, bottom);
            mDivider.draw(c);

            top += mDivider.getIntrinsicHeight() + params.topMargin + child.getHeight() + params.bottomMargin + mDivider.getIntrinsicHeight();
            bottom = top + mDivider.getIntrinsicHeight();
        }
    }

    public void drawHorizontal(Canvas c, RecyclerView parent) {
        final int top = parent.getPaddingTop();
        final int bottom = parent.getHeight() - parent.getPaddingBottom();

        final int childCount = parent.getChildCount();
        for (int i = 0; i < childCount; i++) {
            final View child = parent.getChildAt(i);
            final RecyclerView.LayoutParams params =
                    (RecyclerView.LayoutParams) child.getLayoutParams();
            final int left = child.getRight() + params.rightMargin + mDivider.getIntrinsicHeight();
            final int right = left + mDivider.getIntrinsicWidth();
            mDivider.setBounds(left, top, right, bottom);
            mDivider.draw(c);
        }
    }

    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
        if (mOrientation == VERTICAL_LIST) {
            outRect.set(0, 0, 0, mDivider.getIntrinsicHeight());
        } else if(mOrientation == HORIZONTAL_LIST) {
            outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0);
        } else {
            outRect.set(0, 0, mDivider.getIntrinsicWidth(), mDivider.getIntrinsicHeight());
        }
    }
}
朱宇航
2023-03-14

下面是一个更简单、更用户友好的实现:

public class MediaSpaceDecoration extends RecyclerView.ItemDecoration {
    private final int spacing;
    private final List<Integer> allowedViewTypes = Arrays.asList(
            R.layout.item_image,
            R.layout.item_blur);

    public MediaSpaceDecoration(int spacing) {
        this.spacing = spacing;
    }

    @Override
    public void getItemOffsets(Rect outRect,
                               View view,
                               RecyclerView parent,
                               RecyclerView.State state) {
        final int position = parent.getChildAdapterPosition(view);
        if (!isMedia(parent, position)) {
            return;
        }

        final int totalSpanCount = getTotalSpanCount(parent);
        int spanSize = getItemSpanSize(parent, position);
        if (totalSpanCount == spanSize) {
            return;
        }

        outRect.top = isInTheFirstRow(position, totalSpanCount) ? 0 : spacing;
        outRect.left = isFirstInRow(position, totalSpanCount) ? 0 : spacing / 2;
        outRect.right = isLastInRow(position, totalSpanCount) ? 0 : spacing / 2;
        outRect.bottom = 0; // don't need
    }

    private boolean isInTheFirstRow(int position, int spanCount) {
        return position < spanCount;
    }

    private boolean isFirstInRow(int position, int spanCount) {
        return position % spanCount == 0;
    }

    private boolean isLastInRow(int position, int spanCount) {
        return isFirstInRow(position + 1, spanCount);
    }

    private int getTotalSpanCount(RecyclerView parent) {
        final RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
        return layoutManager instanceof GridLayoutManager
            ? ((GridLayoutManager) layoutManager).getSpanCount()
            : 1;
    }

    private int getItemSpanSize(RecyclerView parent, int position) {
        final RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
        return layoutManager instanceof GridLayoutManager
            ? ((GridLayoutManager) layoutManager).getSpanSizeLookup().getSpanSize(position)
            : 1;
    }

    private boolean isMedia(RecyclerView parent, int viewPosition) {
        final RecyclerView.Adapter adapter = parent.getAdapter();
        final int viewType = adapter.getItemViewType(viewPosition);
        return allowedViewTypes.contains(viewType);
    }
}
柴嘉年
2023-03-14

我不知道你为什么需要它,但是这个UI很容易用RecyclerView装饰器实现。

<!--Integer Value that number of column in RecyclerView-->
<integer name="photo_list_preview_columns">3</integer>

<!-- inter spacing between RecyclerView's Item-->
<dimen name="photos_list_spacing">10dp</dimen>

您可以根据需要更改photo_list_preview_columns和photos_list_spacing。

mRecylerView.addItemDecoration(new ItemDecorationAlbumColumns(
    getResources().getDimensionPixelSize(R.dimen.photos_list_spacing), 
    getResources().getInteger(R.integer.photo_list_preview_columns)));

和装饰器(需要一些重构)

import android.graphics.Rect;
import android.support.v7.widget.RecyclerView;
import android.view.View;

public class ItemDecorationAlbumColumns extends RecyclerView.ItemDecoration {

    private int mSizeGridSpacingPx;
    private int mGridSize;

    private boolean mNeedLeftSpacing = false;

    public ItemDecorationAlbumColumns(int gridSpacingPx, int gridSize) {
        mSizeGridSpacingPx = gridSpacingPx;
        mGridSize = gridSize;
    }

    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
        int frameWidth = (int) ((parent.getWidth() - (float) mSizeGridSpacingPx * (mGridSize - 1)) / mGridSize);
        int padding = parent.getWidth() / mGridSize - frameWidth;
        int itemPosition = ((RecyclerView.LayoutParams) view.getLayoutParams()).getViewAdapterPosition();
        if (itemPosition < mGridSize) {
            outRect.top = 0;
        } else {
            outRect.top = mSizeGridSpacingPx;
        }
        if (itemPosition % mGridSize == 0) {
            outRect.left = 0;
            outRect.right = padding;
            mNeedLeftSpacing = true;
        } else if ((itemPosition + 1) % mGridSize == 0) {
            mNeedLeftSpacing = false;
            outRect.right = 0;
            outRect.left = padding;
        } else if (mNeedLeftSpacing) {
            mNeedLeftSpacing = false;
            outRect.left = mSizeGridSpacingPx - padding;
            if ((itemPosition + 2) % mGridSize == 0) {
                outRect.right = mSizeGridSpacingPx - padding;
            } else {
                outRect.right = mSizeGridSpacingPx / 2;
            }
        } else if ((itemPosition + 2) % mGridSize == 0) {
            mNeedLeftSpacing = false;
            outRect.left = mSizeGridSpacingPx / 2;
            outRect.right = mSizeGridSpacingPx - padding;
        } else {
            mNeedLeftSpacing = false;
            outRect.left = mSizeGridSpacingPx / 2;
            outRect.right = mSizeGridSpacingPx / 2;
        }
        outRect.bottom = 0;
    }
}
 类似资料:
  • 在我的应用程序中,我使用了一个回收器视图,它包含了许多项目,我想在项目之间显示一个点分隔线(分隔符),但它不起作用。我尝试创建一个可绘制的形状,但在添加DividerItemDecurity之后,在回收器视图项之间没有显示空间或线条。我也尝试过创建自定义DividerItemDecoration类,但对我来说都不起作用。注意:目前在我的可绘制形状被设置为矩形,我也尝试了线条。如何实现。任何帮助都将

  • 我正面临一个奇怪的错误,其中recyclerview只显示了一个项目。下面是我的recyclerview适配器的代码: 我已经在其他应用程序中使用了这段代码,它的工作非常完美。我已经检查了聊天数据,这也是完美的。 这里是指向git repo布局文件的链接:布局文件

  • 嗨,我正在学习本教程: http://www.journaldev.com/10024/android-recyclerview-and-cardview-example-tutorial 现在我面临一个奇怪的问题中每个项之间的余量太大了。 如何减少放置在中的每个项目之间的余量?

  • 我想得到下图所示的除法器: 我希望所有列的宽度相同,但行间距不同。现在我的第一列和最后一列被剪成这样: 以下是我的< code>ItemDecoration: 我怎样才能解决这个问题?谢谢

  • 当我按下后退按钮时,这个ShoppingActivity会被破坏,当我再次访问该activity时,我发现我的回收器视图项目被替换了两次。我该如何解决这个问题? ShoppingActivity.java这里编写的所有代码和volley类也在这里调用,当我按下后退键并再次访问该活动时,我发现我的回收器视图项被替换了 @override protected void onCreate(Bundle

  • 我使用GridLayoutManager实现了一个RecyclerView。 根据数据集中的项目数,spanCount在1-4之间。项目宽度根据跨距计数而变化。如果spancount为4或以上,spancount保留为4。 如果我有5个项目,那么剩下1个项目(1行4个项目,剩下1个项目),位于屏幕左侧,单独一行。我希望它能居中。 我已经尝试设置剩余的项目的边距的编程,并包装这两个回收器视图和个别项