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

时间:2018-05-19 11:53:17

标签: android

我在RecyclerView中使用PagerSnapHelper。 RecyclerView中的第一个项目位于屏幕左侧位置。 我需要中心对齐的第一个项目。

LinearLayoutManager layoutManager = new LinearLayoutManager(getContext(), LinearLayoutManager.HORIZONTAL, false);
PagerSnapHelper snapHelper = new PagerSnapHelper();
binding.recyclerView.setOnFlingListener(null);
snapHelper.attachToRecyclerView(binding.recyclerView);
binding.recyclerView.setLayoutManager(layoutManager);
binding.recyclerView.setHasFixedSize(true);
binding.recyclerView.setItemAnimator(new DefaultItemAnimator());
binding.recyclerView.setAdapter(mAdapter);

enter image description here

2 个答案:

答案 0 :(得分:9)

您可以使用ItemDecoration,以下代码可用于第一个和最后一个项目,并且还支持边距。

import android.content.Context;
import android.graphics.Point;
import android.graphics.Rect;
import android.support.v7.widget.RecyclerView;
import android.view.Display;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;

public class OffsetItemDecoration extends RecyclerView.ItemDecoration {

    private Context ctx;

    public OffsetItemDecoration(Context ctx) {

        this.ctx = ctx;
    }

    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {

        super.getItemOffsets(outRect, view, parent, state);
        int offset = (int) (getScreenWidth() / (float) (2)) - view.getLayoutParams().width / 2;
        ViewGroup.MarginLayoutParams lp = (ViewGroup.MarginLayoutParams) view.getLayoutParams();
        if (parent.getChildAdapterPosition(view) == 0) {
            ((ViewGroup.MarginLayoutParams) view.getLayoutParams()).leftMargin = 0;
            setupOutRect(outRect, offset, true);
        } else if (parent.getChildAdapterPosition(view) == state.getItemCount() - 1) {
            ((ViewGroup.MarginLayoutParams) view.getLayoutParams()).rightMargin = 0;
            setupOutRect(outRect, offset, false);
        }
    }

    private void setupOutRect(Rect rect, int offset, boolean start) {

        if (start) {
            rect.left = offset;
        } else {
            rect.right = offset;
        }
    }

    private int getScreenWidth() {

        WindowManager wm = (WindowManager) ctx.getSystemService(Context.WINDOW_SERVICE);
        Display display = wm.getDefaultDisplay();
        Point size = new Point();
        display.getSize(size);
        return size.x;
    }
}

答案 1 :(得分:1)

这是已接受答案的一个简单版本,由于它不涉及屏幕宽度,因此也更加灵活:

class BoundsOffsetDecoration : ItemDecoration() {
    override fun getItemOffsets(outRect: Rect,
                                view: View,
                                parent: RecyclerView,
                                state: RecyclerView.State) {
        super.getItemOffsets(outRect, view, parent, state)

        val itemPosition = parent.getChildAdapterPosition(view)

        // It is crucial to refer to layoutParams.width (view.width is 0 at this time)!
        val itemWidth = view.layoutParams.width
        val offset = (parent.width - itemWidth) / 2

        if (itemPosition == 0) {
            outRect.left = offset
        } else if (itemPosition == state.itemCount - 1) {
            outRect.right = offset
        }
    }
}

如果您需要更多详细信息,我已经写了Medium post,描述了使用RecyclerView和SnapHelper逐步实现这种轮播的实现。