从中心项开始我的 RecyclerView 水平旋转木马
Start my RecyclerView Horizontal Carousel from the center item
我正在创建一个轮播 Horizontal RecyclerView 并缩放从 RecyclerView 的第一个项目开始的焦点项目。
自定义 CenterZoomLayoutManager 的代码:
public class CenterZoomLayoutManager extends LinearLayoutManager {
private final float mShrinkAmount = 0.15f;
private final float mShrinkDistance = 0.9f;
public CenterZoomLayoutManager(Context context, int orientation, boolean reverseLayout) {
super(context, orientation, reverseLayout);
}
@Override
public int scrollHorizontallyBy(int dx, RecyclerView.Recycler recycler, RecyclerView.State state) {
int orientation = getOrientation();
if (orientation == HORIZONTAL) {
int scrolled = super.scrollHorizontallyBy(dx, recycler, state);
float midpoint = getWidth() / 2.f;
float d0 = 0.f;
float d1 = mShrinkDistance * midpoint;
float s0 = 1.f;
float s1 = 1.f - mShrinkAmount;
for (int i = 0; i < getChildCount(); i++) {
View child = getChildAt(i);
float childMidpoint =
(getDecoratedRight(child) + getDecoratedLeft(child)) / 2.f;
float d = Math.min(d1, Math.abs(midpoint - childMidpoint));
float scale = s0 + (s1 - s0) * (d - d0) / (d1 - d0);
child.setScaleX(scale);
child.setScaleY(scale);
}
return scrolled;
} else return 0;
}
@Override
public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
super.onLayoutChildren(recycler, state);
scrollHorizontallyBy(0, recycler, state);
}
}
在我的 Fragment
中,我有以下内容:
private void onSetRecyclerView() {
recyclerView = fragmentView.findViewById(R.id.recyclerView);
if (recyclerView != null) {
RecyclerView.LayoutManager layoutManager = new CenterZoomLayoutManager(context, LinearLayoutManager.HORIZONTAL,
false);
recyclerView.scrollToPosition(storeList.size() / 2);
final SnapHelper snapHelper = new LinearSnapHelper();
snapHelper.attachToRecyclerView(recyclerView);
recyclerView.setLayoutManager(layoutManager);
recyclerView.setAdapter(adapter);
}
}
我想从 中心项目 开始我的 RecyclerView,而不是从起始位置开始。
罪魁祸首:
在我的 CenterZoomLayoutManager
中,我将像素偏移开始设置为 0 像素 到 scrollHorizontallyBy(0, recycler, state)
。
问题:
我找不到将 recyclerView.scrollToPosition(storeList.size() / 2)
创建的偏移像素传递给 CenterZoomLayoutManager
的方法。我试图搜索不同的内置方法来获取 X 偏移量,但到目前为止还没有成功。
解决方案是更改 LinearSnapHelper
附加到 RecyclerView
的时间。以下是重新设计的 onSetRecyclerView()
,它将 RecyclerView
的中心项目对齐到屏幕中心。请注意 LinearSnapHelper
直到 RecyclerView
被布局并适当滚动后才会被附加。您不需要在 onLayoutChildren()
.
中进行任何滚动
private void onSetRecyclerView() {
recyclerView = findViewById(R.id.recyclerView);
CenterZoomLayoutManager layoutManager =
new CenterZoomLayoutManager(this, LinearLayoutManager.HORIZONTAL, false);
recyclerView.setLayoutManager(layoutManager);
recyclerView.setAdapter(adapter);
// Scroll to the position we want to snap to
layoutManager.scrollToPosition(storeList.size() / 2);
// Wait until the RecyclerView is laid out.
recyclerView.post(new Runnable() {
@Override
public void run() {
// Shift the view to snap near the center of the screen.
// This does not have to be precise.
int dx = (recyclerView.getWidth() - recyclerView.getChildAt(0).getWidth()) / 2;
recyclerView.scrollBy(-dx, 0);
// Assign the LinearSnapHelper that will initially snap the near-center view.
LinearSnapHelper snapHelper = new LinearSnapHelper();
snapHelper.attachToRecyclerView(recyclerView);
}
});
}
这是我的测试应用程序初始屏幕的显示方式。有 201 "stores."
我正在创建一个轮播 Horizontal RecyclerView 并缩放从 RecyclerView 的第一个项目开始的焦点项目。
自定义 CenterZoomLayoutManager 的代码:
public class CenterZoomLayoutManager extends LinearLayoutManager {
private final float mShrinkAmount = 0.15f;
private final float mShrinkDistance = 0.9f;
public CenterZoomLayoutManager(Context context, int orientation, boolean reverseLayout) {
super(context, orientation, reverseLayout);
}
@Override
public int scrollHorizontallyBy(int dx, RecyclerView.Recycler recycler, RecyclerView.State state) {
int orientation = getOrientation();
if (orientation == HORIZONTAL) {
int scrolled = super.scrollHorizontallyBy(dx, recycler, state);
float midpoint = getWidth() / 2.f;
float d0 = 0.f;
float d1 = mShrinkDistance * midpoint;
float s0 = 1.f;
float s1 = 1.f - mShrinkAmount;
for (int i = 0; i < getChildCount(); i++) {
View child = getChildAt(i);
float childMidpoint =
(getDecoratedRight(child) + getDecoratedLeft(child)) / 2.f;
float d = Math.min(d1, Math.abs(midpoint - childMidpoint));
float scale = s0 + (s1 - s0) * (d - d0) / (d1 - d0);
child.setScaleX(scale);
child.setScaleY(scale);
}
return scrolled;
} else return 0;
}
@Override
public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
super.onLayoutChildren(recycler, state);
scrollHorizontallyBy(0, recycler, state);
}
}
在我的 Fragment
中,我有以下内容:
private void onSetRecyclerView() {
recyclerView = fragmentView.findViewById(R.id.recyclerView);
if (recyclerView != null) {
RecyclerView.LayoutManager layoutManager = new CenterZoomLayoutManager(context, LinearLayoutManager.HORIZONTAL,
false);
recyclerView.scrollToPosition(storeList.size() / 2);
final SnapHelper snapHelper = new LinearSnapHelper();
snapHelper.attachToRecyclerView(recyclerView);
recyclerView.setLayoutManager(layoutManager);
recyclerView.setAdapter(adapter);
}
}
我想从 中心项目 开始我的 RecyclerView,而不是从起始位置开始。
罪魁祸首:
在我的 CenterZoomLayoutManager
中,我将像素偏移开始设置为 0 像素 到 scrollHorizontallyBy(0, recycler, state)
。
问题:
我找不到将 recyclerView.scrollToPosition(storeList.size() / 2)
创建的偏移像素传递给 CenterZoomLayoutManager
的方法。我试图搜索不同的内置方法来获取 X 偏移量,但到目前为止还没有成功。
解决方案是更改 LinearSnapHelper
附加到 RecyclerView
的时间。以下是重新设计的 onSetRecyclerView()
,它将 RecyclerView
的中心项目对齐到屏幕中心。请注意 LinearSnapHelper
直到 RecyclerView
被布局并适当滚动后才会被附加。您不需要在 onLayoutChildren()
.
private void onSetRecyclerView() {
recyclerView = findViewById(R.id.recyclerView);
CenterZoomLayoutManager layoutManager =
new CenterZoomLayoutManager(this, LinearLayoutManager.HORIZONTAL, false);
recyclerView.setLayoutManager(layoutManager);
recyclerView.setAdapter(adapter);
// Scroll to the position we want to snap to
layoutManager.scrollToPosition(storeList.size() / 2);
// Wait until the RecyclerView is laid out.
recyclerView.post(new Runnable() {
@Override
public void run() {
// Shift the view to snap near the center of the screen.
// This does not have to be precise.
int dx = (recyclerView.getWidth() - recyclerView.getChildAt(0).getWidth()) / 2;
recyclerView.scrollBy(-dx, 0);
// Assign the LinearSnapHelper that will initially snap the near-center view.
LinearSnapHelper snapHelper = new LinearSnapHelper();
snapHelper.attachToRecyclerView(recyclerView);
}
});
}
这是我的测试应用程序初始屏幕的显示方式。有 201 "stores."