【问题标题】:Automatically scroll to bottom of RecyclerView自动滚动到 RecyclerView 底部
【发布时间】:2017-07-04 18:28:45
【问题描述】:

我有一个片段,它的布局文件中有一个 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);

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

【问题讨论】:

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


    【解决方案1】:

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

    确保mMessages 的大小符合您的想法。

    例子,

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

    【讨论】:

    • 确保 mMessages 的大小和你想的一样。 你是什么意思? SmoothScrollToPosition 没有解决我的问题。
    • 确保mMessages 的大小大于包含项目的屏幕
    • 你的意思是视图实际上是可滚动的?在这种情况下,是的。
    【解决方案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 这样的父布局时才有效。希望它能解决您的错误。

    【讨论】:

      【解决方案3】:

      您可以设置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 集。使用非空参数调用 setLayoutManager。

      【讨论】:

      • 如果对您有帮助。请批准我的回答。
      【解决方案4】:

      我相信你没有以正确的方式调用它。您还必须通过 LinearLayoutManager 以及回收器视图才能使其工作。这是我如何使它工作的

      mLayoutManager.smoothScrollToPosition(mRecyclerView, null, array.size() - 1);
      

      【讨论】:

      • 也许这与 Android 与 java 与 Xamarin 的行为方式不同有关,但 null 在 Xamarin 中给出了空对象引用异常。
      【解决方案5】:

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

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

      希望对你有所帮助。

      【讨论】:

      • @rasperryPi 看看吧。
      【解决方案6】:

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

      parentNestedScrollView.smoothScrollTo(0, parentNestedScrollView.bottom)
      

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

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

      【讨论】:

        【解决方案7】:
        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);
            }
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2021-08-24
          • 1970-01-01
          • 1970-01-01
          • 2016-11-13
          • 2016-09-15
          • 2018-08-21
          • 2012-01-18
          • 1970-01-01
          相关资源
          最近更新 更多