[英]How to snap to particular position of LinearSnapHelper in horizontal RecyclerView?
How can I snap to particular position for LinearSnapHelper() in horizontal RecyclerView?如何在水平 RecyclerView 中为 LinearSnapHelper() 捕捉到特定的 position? There is a function scrolltoposition for RecyclerView which scroll to that position but did not keep it in center for this snaphelper.
RecyclerView 有一个 function scrolltoposition 滚动到该 position 但没有将其保持在此 snaphelper 的中心。
I am looking for something like below image.我正在寻找类似下图的东西。 So when I set to particular position, it will keep it in center.
因此,当我设置为特定的 position 时,它将保持居中。 I dont find anything related to select position for SnapHelper
我没有找到与 SnapHelper 的 select position相关的任何内容
i find this , but this doesn't help me.我找到了这个,但这对我没有帮助。 Any help would be appreciated.
任何帮助,将不胜感激。
If I understand your question, you are looking for a way to jump to a position and have that position centered in the RecyclerView
.如果我理解您的问题,您正在寻找一种方法来跳转到 position 并让 position 以
RecyclerView
为中心。
Maybe you have tried RecyclerView.scrollToPosition()
but that doesn't snap to the view.也许您已经尝试过
RecyclerView.scrollToPosition()
但这并没有捕捉到视图。 You may also have tried RecyclerView.smoothScrollToPosition()
and that works better but you may want to avoid all the movement if you have a lot of items and are scrolling a long way.您可能也尝试过
RecyclerView.smoothScrollToPosition()
并且效果更好,但是如果您有很多项目并且滚动很长的路,您可能希望避免所有移动。
The reason that scrollToPosition()
doesn't work is that it doesn't trigger the LinearSnapHelper
which uses a scroll listener to detect when to snap. scrollToPosition()
不起作用的原因是它不会触发使用滚动侦听器来检测何时捕捉的LinearSnapHelper
。 Since smoothScrollToPosition()
does trigger the LinearSnapHelper
, we will use scrollToPosition()
to get us in the area of the target view then use smoothScrollToPosition()
to get the view centered as follows:由于
smoothScrollToPosition()
确实触发了LinearSnapHelper
,我们将使用scrollToPosition()
让我们进入目标视图的区域,然后使用smoothScrollToPosition()
让视图居中,如下所示:
private RecyclerView mRecycler;
private void newScrollTo(final int pos) {
RecyclerView.ViewHolder vh = mRecycler.findViewHolderForLayoutPosition(pos);
if (vh != null) {
// Target view is available, so just scroll to it.
mRecycler.smoothScrollToPosition(pos);
} else {
// Target view is not available. Scroll to it.
mRecycler.addOnScrollListener(new RecyclerView.OnScrollListener() {
// From the documentation:
// This callback will also be called if visible item range changes after a layout
// calculation. In that case, dx and dy will be 0.This callback will also be called
// if visible item range changes after a layout calculation. In that case,
// dx and dy will be 0.
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
mRecycler.removeOnScrollListener(this);
if (dx == 0) {
newScrollTo(pos);
}
}
});
mRecycler.scrollToPosition(pos);
}
}
Sample app示例应用
MainActivity.java MainActivity.java
public class MainActivity extends AppCompatActivity {
private final LinearLayoutManager mLayoutManager = new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false);
private final List<String> mItems = new ArrayList<>();
private RecyclerView mRecycler;
private final int mItemCount = 2000;
private final Handler mHandler = new Handler();
private final LinearSnapHelper mLinearSnapHelper = new LinearSnapHelper();
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
for (int i = 0; i < mItemCount; i++) {
mItems.add(i + "");
}
mRecycler = findViewById(R.id.recyclerView);
final RecyclerViewAdapter adapter = new RecyclerViewAdapter(null);
adapter.setItems(mItems);
mRecycler.setLayoutManager(mLayoutManager);
mRecycler.setAdapter(adapter);
mLinearSnapHelper.attachToRecyclerView(mRecycler);
newScrollTo(1);
// fireScrollTo();
}
private int maxScrolls = mItemCount;
private void fireScrollTo() {
if (--maxScrolls > 0) {
int pos = (int) (Math.random() * mItemCount);
newScrollTo(pos);
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
fireScrollTo();
}
}, 2000);
}
}
private void newScrollTo(final int pos) {
mRecycler.smoothScrollToPosition(pos);
RecyclerView.ViewHolder vh = mRecycler.findViewHolderForLayoutPosition(pos);
if (vh != null) {
// Target view is available, so just scroll to it.
mRecycler.smoothScrollToPosition(pos);
} else {
// Target view is not available. Scroll to it.
mRecycler.addOnScrollListener(new RecyclerView.OnScrollListener() {
// From the documentation:
// This callback will also be called if visible item range changes after a layout
// calculation. In that case, dx and dy will be 0.This callback will also be called
// if visible item range changes after a layout calculation. In that case,
// dx and dy will be 0.
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
mRecycler.removeOnScrollListener(this);
if (dx == 0) {
newScrollTo(pos);
}
}
});
mRecycler.scrollToPosition(pos);
}
}
}
activity_main.xml activity_main.xml
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<View
android:layout_width="3px"
android:layout_height="match_parent"
android:background="@android:color/holo_red_light"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
android:paddingStart="660px"
android:paddingEnd="660px"/>
</android.support.constraint.ConstraintLayout>
RecyclerViewAdapter.java RecyclerViewAdapter.java
class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private List<String> mItems;
RecyclerViewAdapter(List<String> items) {
mItems = items;
}
@Override
public @NonNull
RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(android.R.layout.simple_list_item_1, parent, false);
view.getLayoutParams().width = 220;
view.getLayoutParams().height = 220;
// view.setPadding(220 * 3, 0, 220 * 3, 0);
((TextView) view).setGravity(Gravity.CENTER);
return new ItemViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
ItemViewHolder vh = (ItemViewHolder) holder;
String itemText = mItems.get(position);
vh.mItemTextView.setText(itemText);
int bgColor = (position % 2 == 0)
? android.R.color.holo_blue_light
: android.R.color.holo_green_light;
holder.itemView.setBackgroundColor(
holder.itemView.getContext().getResources().getColor(bgColor));
}
@Override
public int getItemCount() {
return (mItems == null) ? 0 : mItems.size();
}
@Override
public int getItemViewType(int position) {
return TYPE_ITEM;
}
static class ItemViewHolder extends RecyclerView.ViewHolder {
private TextView mItemTextView;
ItemViewHolder(View item) {
super(item);
mItemTextView = item.findViewById(android.R.id.text1);
}
}
public void setItems(List<String> items) {
mItems = items;
}
@SuppressWarnings("unused")
private final static String TAG = "RecyclerViewAdapter";
private final static int TYPE_ITEM = 1;
}
Add this where ever you want to scroll your recycler view
将此添加到您想要滚动回收站视图的任何位置
recyclerView.scrollToPosition(position)
recyclerView.post {
var view = recyclerView.layoutManager?.findViewByPosition(position);
if (view == null) {
// do nothing
}
var snapDistance = snapHelper.calculateDistanceToFinalSnap(recyclerView.layoutManager!!, view!!)
if (snapDistance?.get(0) != 0 || snapDistance[1] != 0) {
recyclerView.scrollBy(snapDistance?.get(0)!!, snapDistance?.get(1));
}
}
By using this LinearSnap Helper which is attached to your recycler view
通过使用附加到您的回收站视图的此 LinearSnap Helper
var snapHelper = LinearSnapHelper()
snapHelper.attachToRecyclerView(recyclerView)
For horizontal RecyclerView, you should use PagerSnapHelper()
instead of LinearSnapHelper()
.对于水平 RecyclerView,您应该使用
PagerSnapHelper()
而不是LinearSnapHelper()
。
Just did some research and trace the SnapHelper's source code, it turns out the solution could be very simple:刚刚做了一些研究并追踪了 SnapHelper 的源代码,结果发现解决方案可能非常简单:
class MyPagerSnapHelper: PagerSnapHelper() {
fun smoothScrollToPosition(layoutManager: RecyclerView.LayoutManager, position: Int) {
val smoothScroller = createScroller(layoutManager) ?: return
smoothScroller.targetPosition = position
layoutManager.startSmoothScroll(smoothScroller)
}
}
And then you can pass RecyclerView's LayoutManager and target position here然后你可以在这里传递 RecyclerView 的 LayoutManager 和目标 position
snapHelper.smoothScrollToPosition(recyclerView.layoutManager!!, index)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.