gpt4 book ai didi

android - 如何正确地将水平 RecyclerView 中的第一个和最后一个项目居中

转载 作者:行者123 更新时间:2023-12-05 09:36:52 31 4
gpt4 key购买 nike

StackOverflow 包含很多这样的问题,但到目前为止绝对没有 100% 有效的解决方案。

我尝试了这些解决方案:

RecyclerView ItemDecoration - How to draw a different width divider for every viewHolder?

first item center aligns in SnapHelper in RecyclerView

Horizontally center first item of RecyclerView

LinearSnapHelper doesn't snap on edge items of RecyclerView

Android Centering Item in RecyclerView

How to make recycler view start adding items from center?

How to have RecyclerView snapped to center and yet be able to scroll to all items, while the center is "selected"?

How to snap to particular position of LinearSnapHelper in horizontal RecyclerView?


并且每次第一个项目都无法正确居中。

我正在使用的示例代码

    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 方法看起来是最好的,但对于第一个项目,它立即表现平平。

最佳答案

我一直在使用来自 Pawel's answerCenterLinearLayoutManager到目前为止,它几乎完美地工作。我说几乎,不是因为它不能立即正常工作,而是因为我最终在使用上述布局管理器的同一 RecyclerView 中使用了 LinearSnapHelper .

因为 snap 助手依赖于了解 RecyclerView 填充来计算它的正确中心,所以只为第一个项目设置填充会抛出这个过程,导致第一个项目(和后续项目直到最后一个一个实际显示)从中心偏移。

我的解决方案是确保在显示第一个项目时从一开始就正确设置两个内边距。

所以这样:

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

变成这样

if (!reverseLayout) {
if (lp == 0) recyclerView.updatePaddingRelative(start = hPadding, end = hPadding) // here we set the same padding for both sides
if (lp == itemCount - 1) recyclerView.updatePaddingRelative(end = hPadding)
} else {
if (lp == 0) recyclerView.updatePaddingRelative(end = hPadding, start = hPadding) // here we set the same padding for both sides
if (lp == itemCount - 1) recyclerView.updatePaddingRelative(start = hPadding)
}

而且我假设同样的逻辑也必须应用于垂直 block 。

我相信这现在可以进一步优化,所以上面的最后一个 block 看起来像这样:

if (lp == 0) recyclerView.updatePaddingRelative(start = hPadding, end = hPadding) // here we set the same padding for both sides
if (lp == itemCount - 1) {
if (!reverseLayout) recyclerView.updatePaddingRelative(end = hPadding)
if (reverseLayout) recyclerView.updatePaddingRelative(start = hPadding)
}

注意:我最终发现,如果我使用的项目之间的宽度差异很大,那么当最后一个项目加载时,我在这里提到的同样的问题也会发生,这是有道理的,因为那时我们在不同的一侧设置了填充比另一个,再次摆脱了原生中心计算。

这个的解决方案是在第一个项目和最后一个项目加载时为两侧设置相同的填充

recyclerView.updatePaddingRelative(start = hPadding, end = hPadding)

就是这样,没有像前面示例中那样的 if。

当然,这仍然不能解决当显示的项目太少以至于第一个和最后一个项目可见时的问题,但是当我设法找到针对该特定情况的解决方案时,我会更新它在这里。

关于android - 如何正确地将水平 RecyclerView 中的第一个和最后一个项目居中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64853649/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com