web-dev-qa-db-ja.com

千鳥格子レイアウトマネージャーで列の位置を決定する方法

写真のリストには、スタッガードリサイクラービューレイアウトを使用しています。 2つの列の間にスペースを残したまま、側面の間隔をゼロにします。添付の写真に表示されている間隔を取得するために、アイテム装飾サブクラスを使用しています。左右の間隔を制御できることはわかっていますが、問題は、写真がどの列にあるかわからないことです。千鳥配置のレイアウトマネージャーが独自の並べ替えを行っているようです。 getChildAdapterPositionを使用してみましたが、レイアウト内の写真の実際の位置ではなく、データソース配列内の位置が返されるようです。これにどのようにアプローチすべきか考えていますか? enter image description here

18

私はそれをうまく動かすことができました。私の場合、画面の左端または右端に境界線は必要ありません。真ん中と下にボーダーが必要です。解決策は、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には、境界線のないヘッダーViewがあるためです。その後、スパンインデックスを取得し、それに応じて、そのビューに必要な境界線を設定します。そして最後に、すべてのビューに下の境界線を設定しました。

36
Tooroop

だから私が使用できた1つの解決策はアイテムデコレータを使用することでしたが、それは間違いなく少し奇妙でハッキーな感じです。

基本的に、列の位置(または同様のもの)に基づいてアイテムの外側の長方形を調整します。私の理解では、外側の長方形は多かれ少なかれ変更したい間隔です。以下のコードを試してみてください。明らかに、アイテムがどの列にあるかを「計算」するために独自の調整とロジックを行う必要がありますが、うまくいけば、これで十分です。

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);
        }
    });

繰り返しますが、これはハッキーであり、正しく行うには試行錯誤が必要です。

私が成功を収めて試したもう1つの解決策は、列ごとに異なるビューを定義することです。あなたの場合、列には、必要な効果を得るために、左右に異なる負のマージンを持つビューがあります。

ちなみに、カードビューで標高を使用していると仮定します。私が気づいたことの1つは、カードビューに標高がなく、代わりに自分で処理する場合(ええ、私は知っています、自分で標高を処理しないことはポイントではありません)、この困難の多くはなくなり、物事が動作し始めます、おそらく標高/影の計算が原因です。しかしとにかく...これが少なくともいくらか役立つことを願っています...