【问题标题】:How to determine column position in staggered grid layout manager如何确定交错网格布局管理器中的列位置
【发布时间】:2016-05-13 07:41:54
【问题描述】:

我正在对照片列表使用交错的回收站视图布局。我希望两侧的间距为零,同时两列之间仍有空间。我正在使用项目装饰子类来获取所附照片中的间距。我知道我可以控制左右间距,但问题是我永远不知道照片在哪一列。交错布局管理器似乎做了一些自己的重新排序。我试过使用getChildAdapterPosition,但它似乎返回了数据源数组中的位置,而不是布局中照片的实际位置。知道我应该如何处理吗?

【问题讨论】:

  • 这也是我目前正在尝试弄清楚的。经理根据视图大小定位视图,您永远无法确定奇数位置在左侧,偶数位置在右侧。这就是我试图在我的项目装饰器中解决它的方法,通过检查位置 % 2 == 0 然后设置 rect.left 边距......但它不是那样工作的,因为在某些情况下位置为 6 的项目可以在右边,有时在左边。
  • 没有代表对@Vasilisfoo 的回答发表评论。警告那些使用getSpanIndex() 的人:如果您之前有setGapStrategy()GAP_HANDLING_MOVE_ITEMS_BETWEEN_SPANS,那么您的跨度索引通常会返回错误值,因为在设置跨度索引后项目会四处移动。

标签: android staggeredgridlayout


【解决方案1】:

我设法让它工作。就我而言,我不需要屏幕左右边缘的任何边框。我只需要中间和底部的边框。解决方案是获取类型为 StaggeredGridLayoutManager.LayoutParams 的视图的布局参数。在这些参数中,您可以获得 spanIndex ,它告诉您视图在哪个索引上。因此,如果您的 spanCount 为 2,则左视图的 spanIndex 为 0,右视图的 spanIndex 为 1。

这是我的代码,也许对你有帮助。

public class SpaceItemDecoration extends RecyclerView.ItemDecoration {
    private int space;

    public SpaceItemDecoration(int space) {
        this.space = space;
    }


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

        StaggeredGridLayoutManager.LayoutParams lp = (StaggeredGridLayoutManager.LayoutParams) view.getLayoutParams();
        int spanIndex = lp.getSpanIndex();

        if (position > 0) {
            if (spanIndex == 1) {
                outRect.left = space;
            } else {
                outRect.right = space;
            }

            outRect.bottom = space * 2;
        }
    }
}

在我的情况下,首先我必须获得位置,因为在索引 0 上我有一个标题视图,它没有任何边框。之后,我得到了跨度索引,并根据它在该视图上设置了我需要的边框。最后,我为每个视图设置了底部边框。

【讨论】:

  • 谢谢,我一直在尝试破解我的布局,它有一种标题视图类型、子标题视图类型和项目视图类型。这是一个非常优雅的解决方案,也适用于常规 GridLayoutManager。
  • 你有这个代码的工作示例吗?我在我的项目中尝试过,由于某些我不明白的原因,spanIndex 始终为 0。似乎 StaggeredGridLayoutManager 在决定子视图属于哪个跨度之前调用了 getItemOffsets。
【解决方案2】:

所以我能够使用的一个解决方案是使用物品装饰器,但它肯定有点奇怪/hacky 的感觉。

基本上,您将根据其列位置(或类似的东西)调整项目的外部矩形。我的理解是外部矩形或多或少是您要更改的间距。试试下面的代码,显然你需要做出自己的调整和逻辑来“计算”项目所在的列,但这应该足以弄清楚,希望:

recyclerView.addItemDecoration(new RecyclerView.ItemDecoration() {
        public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
            int left = outRect.left;
            int right = outRect.right;
            int top = outRect.top;
            int bottom = outRect.bottom;
            int idx = parent.getChildPosition(view);
            int perRow = gridLayoutManager.getSpanCount();

            int adj = blahh... // some adjustment

            if (idx < itemsPerRow) {
                // on first row, adjust top if needed
            }

           if(idx % perRow == 0){
                // on first column, adjust. Left magically adjusts bottom, so adjust it too...
                left += adj;
                bottom -= adj;
           }

           if(idx % itemsPerRow == perRow - 1){
               // on last column, adjust. Right magically adjusts bottom, so adjust it too...
               right += adjustment;
               bottom -= adjustment;
           }

            outRect.set(left, top, right, bottom);
        }
    });

同样,这很老套,需要反复试验才能正确。

我尝试过的另一个成功的解决方案是为不同的列定义不同的视图。在您的情况下,列将在左侧和右侧具有不同的负边距视图,以获得您想要的效果。

作为旁注,我假设您在卡片视图上使用了立面图。我注意到的一件事是,如果卡片视图没有海拔,而是您自己处理(是的,我知道,不是自己不处理海拔的重点),那么大部分困难都会消失,事情开始表现,可能是因为高程/阴影计算。但无论如何......希望这至少有点帮助......

【讨论】:

  • 嘿,itemsPerRowinstantiated 在哪里?谢谢
  • 帮我获取列号和行号
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-18
  • 1970-01-01
  • 1970-01-01
  • 2018-02-28
相关资源
最近更新 更多