自动滚动到RecyclerView

时间:2017-07-04 18:28:45

标签: android xamarin scroll android-recyclerview xamarin.android

我有一个片段,其布局文件中包含RecyclerView。 RecyclerView在聊天中保存消息。很自然地,当聊天片段被打开时,我需要RecyclerView滚动到底部。

我尝试直接在RecyclerView上滚动:

var mRecyclerView = view.FindViewById<RecyclerView>
mRecyclerView.ScrollToPosition(mMessages.Count-1);

第二种方法:

LinearLayoutManager mLinearLayoutManager = new LinearLayoutManager(Application.Context);
mRecyclerView.SetLayoutManager(mLinearLayoutManager);
mLinearLayoutManager.ScrollToPosition(mMessages.Count - 1);      

第三种方法:

LinearLayoutManager mLinearLayoutManager = new LinearLayoutManager(Application.Context);
mRecyclerView.SetLayoutManager(mLinearLayoutManager);
mLinearLayoutManager.ScrollToPositionWithOffset(mMessages.Count - 1, 0);

不幸的是,两种情况都没有发生。任何建议将不胜感激!

7 个答案:

答案 0 :(得分:10)

请使用smoothScrollToPosition来解决您的问题。 我总是使用smoothScrollToPosition重定向到任何位置。

确保mMessages尺寸符合您的想法。

实施例,

RecyclerView rv = (RecyclerView)findViewById(R.id.recyclerView);
rv.smoothScrollToPosition(mMessages.count-1);

答案 1 :(得分:4)

您可以设置setStackFromEnd=true来设置视图以显示最后一个元素,布局方向将保持不变。

修改后我已更新:就像这样:

   LinearLayoutManager mLinearLayoutManager = new LinearLayoutManager(Application.Context);
   mLinearLayoutManager.setStackFromEnd(true); 
   mRecyclerView.SetLayoutManager(mLinearLayoutManager);
   mRecyclerView.scrollToPosition(mMessages.Count-1);

请查看the documentation

编辑:问题是您是在调用scrollToPosition而未将任何布局管理器设置为recyclerview。

考虑到RecyclerView类中的scrollToPosition函数,您的情况很有意义。

/**
     * Convenience method to scroll to a certain position.
     *
     * RecyclerView does not implement scrolling logic, rather forwards the call to
     * {@link android.support.v7.widget.RecyclerView.LayoutManager#scrollToPosition(int)}
     * @param position Scroll to this adapter position
     * @see android.support.v7.widget.RecyclerView.LayoutManager#scrollToPosition(int)
     */
    public void scrollToPosition(int position) {
        if (mLayoutFrozen) {
            return;
        }
        stopScroll();
        if (mLayout == null) {
            Log.e(TAG, "Cannot scroll to position a LayoutManager set. " +
                    "Call setLayoutManager with a non-null argument.");
            return;
        }
        mLayout.scrollToPosition(position);
        awakenScrollBars();
    }
  

无法滚动以定位LayoutManager集。使用非null参数调用setLayoutManager。

答案 2 :(得分:2)

我相信你并没有以正确的方式称呼它。您还必须传递LinearLayoutManager以及recycler视图才能使其正常工作。在这里我是如何使它工作的

print ("enter file name")
f = input()
file = open(f)
z = file.read()
numdict = {}
my_num = 0
with open(f) as file:
    [word for line in z for word in line.split()]
for word in z:
    if not word in numdict:
        numdict[word] = []

    numdict[word].append(my_num)

print("word" , "frequency")
for key in sorted(numdict):
    print(key, len(numdict[key]))

答案 3 :(得分:2)

很简单 更改您的代码

    RecyclerView recyclerView = findViewById(R.id.recyclerView);
    LinearLayoutManager layoutManager = new LinearLayoutManager(this);
    layoutManager.setStackFromEnd(true);
    recyclerView.setLayoutManager(layoutManager);
    recyclerView.setAdapter(mAdapter);
    recyclerView.smoothScrollToPosition(mAdapter.getItemCount());

如果您在recyclerView的父级中提供了ScrollView或NestedScrollView,则它将不起作用。因为只有当recyclerView没有像ScrollView这样的父布局时,它才起作用。希望它能解决您的错误。

答案 4 :(得分:1)

我发现了问题,请在设置LayoutManager后设置RecyclerView scrollToPosition或smoothScrollToPosition。

RecyclerView recyclerView = findViewById(R.id.recyclerView);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.scrollToPosition(mMessages.count - 1);

希望它对您有帮助。

答案 5 :(得分:0)

如果您在 recyclerView 的父级中提供了 ScrollView 或 NestedScrollView,请尝试以下操作:

parentNestedScrollView.smoothScrollTo(0, parentNestedScrollView.bottom)

有时这可能不起作用,因为会在适配器显示新项目之前尝试更新滚动位置,因此我们需要使用延迟:

 popupView.postDelayed({
        parentNestedScrollView.smoothScrollTo(0, parentNestedScrollView.bottom)
 }, 200)

答案 6 :(得分:0)

  1. 如果您想直接滚动到最后一项,您可以使用此代码。

binding.recyclerView.smoothScrollToPosition(adapter.itemCount-1)

  1. 如果你想为 recyclerview 添加连续滚动,你可以使用这个类。
public class AutoScrollRecyclerView extends RecyclerView {
    private static long delayTime = 45;// How long after the interval to perform scrolling
    AutoPollTask autoPollTask;// Scroll thread
    private boolean running; // Is it rolling?
    private boolean canRun;// Can it be automatically scrolled, depending on whether the data exceeds the screen

    public AutoScrollRecyclerView(Context context) {
        super(context);
    }

    public AutoScrollRecyclerView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        autoPollTask = new AutoPollTask(this);// Instantiate the scroll refresh thread
    }

    static class AutoPollTask implements Runnable {
        private final WeakReference<AutoScrollRecyclerView> mReference;

        // Use weak references to hold external class references to prevent memory leaks
        public AutoPollTask(AutoScrollRecyclerView reference) {
            this.mReference = new WeakReference<>(reference);
        }

        @Override
        public void run() {
            AutoScrollRecyclerView recyclerView = mReference.get();// Get the recyclerview object
            if (recyclerView != null && recyclerView.running && recyclerView.canRun) {
                recyclerView.scrollBy(2, 2);// Note the difference between scrollBy and scrollTo
                //delayed to send
                recyclerView.postDelayed(recyclerView.autoPollTask, delayTime);
            }
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent e) {
        switch (e.getAction()) {
            case MotionEvent.ACTION_DOWN:
                /*if (running)
                    stop();*/
                break;
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
            case MotionEvent.ACTION_OUTSIDE:
                /*if (canRun)
                    start();*/
                break;
        }
        return super.onTouchEvent(e);
    }

    //Open: If it is running, stop first -> then open
    public void start() {
        if (running)
            stop();
        canRun = true;
        running = true;
        postDelayed(autoPollTask, delayTime);
    }
    
    public void stop() {
        running = false;
        removeCallbacks(autoPollTask);
    }
}