【问题标题】:RecyclerView findLastCompletelyVisibleItemPosition always returns last elementRecyclerView findLastCompletelyVisibleItemPosition 总是返回最后一个元素
【发布时间】:2019-08-30 23:37:41
【问题描述】:

关于 StackOverflow 的第一个问题!

我有一个无限滚动 RecyclerView,前面有几个其他视图,都在一个 NestedScrollView 中。

每当我在 RecyclerView 的布局管理器上调用 findLastCompletelyVisibleItemPosition 时,我都会获得加载到 RecyclerView 中的最后一个元素的位置……即使屏幕上只有第一个元素可见。我相信这是因为 RecyclerView 位于 NestedScrollView 中——该项目正在显示,但我必须向下滚动才能查看它——但我肯定是错的。

Fragment OnViewCreated 中 RecyclerView 的初始化:

    @Override
    public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

    //... irrelevant code ... //

   photosRecyclerView = view.findViewById(R.id.profile_recyclerview_photos);
   // Add LayoutManager to RecyclerView.
   GridLayoutManager manager = new GridLayoutManager(getContext(), 2);
   photosRecyclerView.setLayoutManager(manager);
   // Smoothes scrolling from NestedScrollView.
   photosRecyclerView.setNestedScrollingEnabled(false);
   // Add adapter to RecyclerView.
   profileRecyclerViewAdapter = new ProfileRecyclerViewAdapter(getContext(), photoList);
   photosRecyclerView.setAdapter(profileRecyclerViewAdapter);

ScrollListener 附加到 RecyclerView :


    private void initScrollListener() {

        photosRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
                super.onScrollStateChanged(recyclerView, newState);
            }

            @Override
            public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
                super.onScrolled(recyclerView, dx, dy);

                final GridLayoutManager gridLayoutManager = (GridLayoutManager) recyclerView.getLayoutManager();

                Log.d(TAG, "" +  gridLayoutManager.findLastCompletelyVisibleItemPosition());

                if (!loadingPhotos) {
                  if (gridLayoutManager.findLastCompletelyVisibleItemPosition() == photoList.size()-1  && hasMorePhotos) {
                        Log.d(TAG, "Attempting to load more images.");
                        loadMore();
                        loadingPhotos = true;
                    }

                }
            }

        });
    }

片段的布局:

<androidx.core.widget.NestedScrollView android:layout_height="match_parent"
    android:layout_width="match_parent"
    xmlns:android="http://schemas.android.com/apk/res/android">

<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@color/colorPrimaryDark"
    tools:context=".ProfileFragment">


  <------- RANDOM OTHER VIEWS -------->

   <androidx.recyclerview.widget.RecyclerView
      android:id="@+id/profile_recyclerview_photos"
      android:layout_marginTop="10dp"
      android:layout_width="0dp"
      android:layout_height="wrap_content"
      app:layout_constraintStart_toStartOf="@+id/profile_guideline_verticalstart"
      app:layout_constraintEnd_toEndOf="@+id/profile_guideline_verticalend"
      app:layout_constraintTop_toBottomOf="@id/profile_textview_photoslabel"/>

  </androidx.constraintlayout.widget.ConstraintLayout>

</androidx.core.widget.NestedScrollView>

您的帮助将不胜感激!

【问题讨论】:

    标签: java android android-recyclerview


    【解决方案1】:

    经过一些研究——在来自this answer 的大量帮助下,我意识到这种行为是由于 RecyclerView 的高度设置为包裹内容。这会导致它立即加载所有项目,因此最后一个“完全可见”的项目是 RecyclerView 中的最后一个项目。

    【讨论】:

    • 你是怎么解决的?你是怎么解决这个问题的?
    【解决方案2】:

    您可以尝试使用约束布局并将recyclerview高度更改为0dp。

    它会解决你的问题

    【讨论】:

      【解决方案3】:

      我最近遇到了回收站视图的问题,尝试了所有可能的解决方案,但仍然失败。所以我想出了这个轻量级的解决方案。

      binding.currencies.apply {
              adapter = currencyPagingAdapter
          }.addOnScrollListener(object : RecyclerView.OnScrollListener() {
              override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
                  super.onScrollStateChanged(recyclerView, newState)
      
                  val lm = recyclerView.layoutManager as LinearLayoutManager
                  val lv = lm.getChildAt(lm.itemCount - 1)
      
                  val scrollBounds = Rect()
                  recyclerView.getHitRect(scrollBounds)
      
                  if (lv != null) {
                      if (lv.getLocalVisibleRect(scrollBounds)) {
                          Log.d("TAG", "onScrollStateChanged: visible")
                      } else {
                          Log.d("TAG", "onScrollStateChanged: not visible")
                      }
      
                  }
      
              }
          })
      

      【讨论】:

        【解决方案4】:

        遇到了同样的问题,我通过检测nestedScrollView 何时结束来解决了我的问题!

        nestedScrollView.getViewTreeObserver().addOnScrollChangedListener(new ViewTreeObserver.OnScrollChangedListener() {
            @Override
            public void onScrollChanged() {
                if (nestedScrollView != null) {
                    if (nestedScrollView.getChildAt(0).getBottom() <= (nestedScrollView.getHeight() + nestedScrollView.getScrollY())) {
                        //scroll view is at bottom
                        if (isAnythingToLoad && rowsArrayList.size() > 8) {
                            //bottom of list!
                            loadMore();
                        }
                    }
                }
            }
        })
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-08-05
          • 2015-04-29
          • 1970-01-01
          • 1970-01-01
          • 2012-07-21
          • 1970-01-01
          相关资源
          最近更新 更多