如何在水平RecyclerView中正确对齐第一个和最后一个项目的中心

阴影

StackOverflow遇到这样的问题,但是到目前为止,绝对没有解决方案可以100%起作用。

我尝试了以下解决方案:

RecyclerView ItemDecoration-如何为每个viewHolder绘制不同的宽度分隔线?

第一个项目中心在RecyclerView中的SnapHelper中对齐

将RecyclerView的第一项水平居中

LinearSnapHelper不能捕捉RecyclerView的边缘项目

RecyclerView中的Android居中项

如何使Recycler View开始从中心添加项目?

如何将RecyclerView捕捉到中心并在“选择”中心的同时滚动到所有项目?

如何在水平RecyclerView中捕捉到LinearSnapHelper的特定位置?


但是,每次第一个项目都无法正确居中。

我正在使用的示例代码

    recyclerView.addItemDecoration(new RecyclerView.ItemDecoration() {
        @Override
        public void getItemOffsets(
            @NonNull Rect outRect,
            @NonNull View view,
            @NonNull RecyclerView parent,
            @NonNull RecyclerView.State state
        ) {

            super.getItemOffsets(outRect, view, parent, state);

            final int count = state.getItemCount();
            final int position = parent.getChildAdapterPosition(view);

            if (position == 0 || position == count - 1) {

                int offset = (int) (parent.getWidth() * 0.5f - view.getWidth() * 0.5f);

                if (position == 0) {
                    setupOutRect(outRect, offset, true);
                } else if (position == count - 1) {
                    setupOutRect(outRect, offset, false);
                }

            }

        }

        private void setupOutRect(Rect rect, int offset, boolean start) {
            if (start) {
                rect.left = offset;
            } else {
                rect.right = offset;
            }
        }

    });

经过调查,我发现,这是因为在该时间getItemOffsetsview.getWidth是0,它并没有被测量呢。

我试图强制对其进行测量,但是每一次它给出的尺寸都不正确,就不会像它实际占用的尺寸那样小。

我也尝试使用该addOnGlobalLayoutListener技巧,但到调用它的时间并具有正确的宽度时,outRect它已经被消耗了,因此丢失了。

我不想设置任何固定的大小,因为中的项目RecyclerView可以具有不同的大小,因此无法提前设置其填充。

我也不想添加“鬼影”项目来填充空间,并且这些内容也无法很好地实现滚动体验。

如何使它正常工作?

理想情况下,该ItemDecorator方法看起来是最好的,但是对于第一个项目,它马上就落空了。

帕维尔

您也可以更改RecyclerView自身的填充以达到此效果(只要clipToPadding已禁用)。我们可以拦截第一个布局阶段,LayoutManager因此即使是初次布局项目时也可以使用更新的填充:

添加此布局管理器:

open class CenterLinearLayoutManager : LinearLayoutManager {
    constructor(context: Context) : super(context)
    constructor(context: Context, orientation: Int, reverseLayout: Boolean) : super(context, orientation, reverseLayout)
    constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int, defStyleRes: Int) : super(context, attrs, defStyleAttr, defStyleRes)

    private lateinit var recyclerView: RecyclerView

    override fun onLayoutChildren(recycler: RecyclerView.Recycler, state: RecyclerView.State) {
        // always measure first item, its size determines starting offset
        // this must be done before super.onLayoutChildren
        if (childCount == 0 && state.itemCount > 0) {
            val firstChild = recycler.getViewForPosition(0)
            measureChildWithMargins(firstChild, 0, 0)
            recycler.recycleView(firstChild)
        }
        super.onLayoutChildren(recycler, state)
    }

    override fun measureChildWithMargins(child: View, widthUsed: Int, heightUsed: Int) {
        val lp = (child.layoutParams as RecyclerView.LayoutParams).absoluteAdapterPosition
        super.measureChildWithMargins(child, widthUsed, heightUsed)
        if (lp != 0 && lp != itemCount - 1) return
        // after determining first and/or last items size use it to alter host padding
        when (orientation) {
            HORIZONTAL -> {
                val hPadding = ((width - child.measuredWidth) / 2).coerceAtLeast(0)
                if (!reverseLayout) {
                    if (lp == 0) recyclerView.updatePaddingRelative(start = hPadding)
                    if (lp == itemCount - 1) recyclerView.updatePaddingRelative(end = hPadding)
                } else {
                    if (lp == 0) recyclerView.updatePaddingRelative(end = hPadding)
                    if (lp == itemCount - 1) recyclerView.updatePaddingRelative(start = hPadding)
                }
            }
            VERTICAL -> {
                val vPadding = ((height - child.measuredHeight) / 2).coerceAtLeast(0)
                if (!reverseLayout) {
                    if (lp == 0) recyclerView.updatePaddingRelative(top = vPadding)
                    if (lp == itemCount - 1) recyclerView.updatePaddingRelative(bottom = vPadding)
                } else {
                    if (lp == 0) recyclerView.updatePaddingRelative(bottom = vPadding)
                    if (lp == itemCount - 1) recyclerView.updatePaddingRelative(top = vPadding)
                }
            }
        }
    }

    // capture host recyclerview
    override fun onAttachedToWindow(view: RecyclerView) {
        recyclerView = view
        super.onAttachedToWindow(view)
    }
}

然后将其用于您的RecyclerView:

recyclerView.layoutManager = CenterLinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false)
recyclerView.clipToPadding = false // disabling clip to padding is critical

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

UWP ListView,第一个项目和最后一个项目的不同项目模板

来自分类Dev

如何在第一个和最后一个日期之间填充日期?

来自分类Dev

禁用“猫头鹰轮播”中第一个和最后一个项目的弹跳

来自分类Dev

检索ListView或GridView中第一个和最后一个可见项目的索引?

来自分类Dev

在 UICollectionView 的中心设置第一个和最后一个 UICollectionViewCell 的位置

来自分类Dev

如何居中水平UICollectionView的第一个和最后一个单元格?

来自分类Dev

如何在Owl Carousel 2的可见项目中为第一个项目和最后一个项目添加类?

来自分类Dev

Android RecyclerView查找ItemDecoration的第一个和最后一个视图

来自分类Dev

如何传递最后一个项目时自动循环到第一个项目的数组中的最后N个值?

来自分类Dev

Yii2 ListView中的第一个和最后一个项目

来自分类Dev

如何在ul元素中将第一个li左对齐和第二个li中心对齐

来自分类Dev

如何在Android的回收器视图中显示对第一个项目的选择?

来自分类Dev

如何在PostgreSQL中的一行上获取第一个和最后一个值

来自分类Dev

如何在第一个和最后一个div上删除左边距和右边距

来自分类Dev

如何在foreach循环中检测第一个和最后一个元素?

来自分类Dev

如何在Perl中获取xml元素的第一个和最后一个子元素

来自分类Dev

如何在第一个和最后一个列表项处停止切换功能?

来自分类Dev

如何在Android Datepicker中获取月份的第一个和最后一个日期

来自分类Dev

如何在Hive中按时间顺序选择第一个和最后一个记录?

来自分类Dev

如何在javascript中获取对象的第一个,最后一个和其他值?

来自分类Dev

如何在C ++中交换队列的第一个和最后一个元素?

来自分类Dev

如何在Ruby字符串上拆分第一个和最后一个元素?

来自分类Dev

如何在第一个孩子前面移动最后一个孩子

来自分类Dev

如何在 matplotlib 图中包含第一个/最后一个日期

来自分类Dev

MySQL为每个项目的最后一个用户过滤第一个日期

来自分类Dev

如何从list <string>获取第一个和最后一个值?

来自分类Dev

如何访问字典中的第一个和最后一个元素?

来自分类Dev

如何忽略xpath中的第一个和最后一个元素

来自分类Dev

父母和第一个/最后一个孩子的边际崩溃如何工作?

Related 相关文章

  1. 1

    UWP ListView,第一个项目和最后一个项目的不同项目模板

  2. 2

    如何在第一个和最后一个日期之间填充日期?

  3. 3

    禁用“猫头鹰轮播”中第一个和最后一个项目的弹跳

  4. 4

    检索ListView或GridView中第一个和最后一个可见项目的索引?

  5. 5

    在 UICollectionView 的中心设置第一个和最后一个 UICollectionViewCell 的位置

  6. 6

    如何居中水平UICollectionView的第一个和最后一个单元格?

  7. 7

    如何在Owl Carousel 2的可见项目中为第一个项目和最后一个项目添加类?

  8. 8

    Android RecyclerView查找ItemDecoration的第一个和最后一个视图

  9. 9

    如何传递最后一个项目时自动循环到第一个项目的数组中的最后N个值?

  10. 10

    Yii2 ListView中的第一个和最后一个项目

  11. 11

    如何在ul元素中将第一个li左对齐和第二个li中心对齐

  12. 12

    如何在Android的回收器视图中显示对第一个项目的选择?

  13. 13

    如何在PostgreSQL中的一行上获取第一个和最后一个值

  14. 14

    如何在第一个和最后一个div上删除左边距和右边距

  15. 15

    如何在foreach循环中检测第一个和最后一个元素?

  16. 16

    如何在Perl中获取xml元素的第一个和最后一个子元素

  17. 17

    如何在第一个和最后一个列表项处停止切换功能?

  18. 18

    如何在Android Datepicker中获取月份的第一个和最后一个日期

  19. 19

    如何在Hive中按时间顺序选择第一个和最后一个记录?

  20. 20

    如何在javascript中获取对象的第一个,最后一个和其他值?

  21. 21

    如何在C ++中交换队列的第一个和最后一个元素?

  22. 22

    如何在Ruby字符串上拆分第一个和最后一个元素?

  23. 23

    如何在第一个孩子前面移动最后一个孩子

  24. 24

    如何在 matplotlib 图中包含第一个/最后一个日期

  25. 25

    MySQL为每个项目的最后一个用户过滤第一个日期

  26. 26

    如何从list <string>获取第一个和最后一个值?

  27. 27

    如何访问字典中的第一个和最后一个元素?

  28. 28

    如何忽略xpath中的第一个和最后一个元素

  29. 29

    父母和第一个/最后一个孩子的边际崩溃如何工作?

热门标签

归档