简体   繁体   English

如何在水平 RecyclerView 中捕捉到 LinearSnapHelper 的特定 position?

[英]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.

相关问题 如何使用LinearSnapHelper以编程方式捕捉到Recycler视图上的位置 - How to programmatically snap to position on Recycler view with LinearSnapHelper LinearSnapHelper不会捕捉RecyclerView的边缘项目 - LinearSnapHelper doesn't snap on edge items of RecyclerView RecyclerView 水平滚动对齐居中 - RecyclerView horizontal scroll snap in center 如何在水平回收站视图中获取当前位置? - How to get current position in horizontal recyclerview? 如何在recyclerview内的特定位置添加分隔符? - How to add separator at particular position inside recyclerview? 如何将水平滚动视图移动到特定位置? - How to move Horizontal Scroll View to a particular position? 如何滚动到scrollview内的recyclerview中的特定位置? - How to scroll to a particular position in recyclerview inside scrollview? 滚动到(启用垂直和水平滚动)网格布局中的特定位置 - RecyclerView - Android - Scroll to Particular Position in (Vertical & Horizontal Scroll Enabled) Grid Layout - RecyclerView - Android 水平和垂直 recyclerview 项目位置 - Horizontal and Vertical recyclerview item position 在recyclerview中滚动到特定类别位置 - scroll to particular category position in recyclerview
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM