【问题标题】:findFirstVisibleItemPositions doesn't work for recycleview androidfindFirstVisibleItemPosition 不适用于 recyclerview android
【发布时间】:2015-04-05 23:48:53
【问题描述】:

我有这个代码:

mRecycleView.setOnScrollListener(new RecyclerView.OnScrollListener() {
    @Override
    public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
        super.onScrolled(recyclerView, dx, dy);
        int[] firstVisibleItemPositions = new int[getResources().getInteger(R.integer.news_numbers_column)]; 
        int pastVisiblesItems = ((StaggeredGridLayoutManager)getLayoutManager()).findFirstVisibleItemPositions(firstVisibleItemPositions)[0];
    }
});

当我滚动我的回收视图时,我收到了这个错误:

java.lang.NullPointerException: Attempt to invoke virtual method 'int android.support.v7.widget.OrientationHelper.getStartAfterPadding()' on a null object reference
at android.support.v7.widget.StaggeredGridLayoutManager$Span.findOneVisibleChild(StaggeredGridLayoutManager.java:2177)
at android.support.v7.widget.StaggeredGridLayoutManager$Span.findFirstVisibleItemPosition(StaggeredGridLayoutManager.java:2153)
at android.support.v7.widget.StaggeredGridLayoutManager.findFirstVisibleItemPositions(StaggeredGridLayoutManager.java:806)
at info.lanouvelletribune.apps.android.ui.fragments.NewsFragment$1.onScrollStateChanged(NewsFragment.java:90)
at android.support.v7.widget.RecyclerView.setScrollState(RecyclerView.java:751)
at android.support.v7.widget.RecyclerView.onInterceptTouchEvent(RecyclerView.java:1535)
at com.github.ksoichiro.android.observablescrollview.ObservableRecyclerView.onInterceptTouchEvent(ObservableRecyclerView.java:188)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2060)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2431)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2173)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2431)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2173)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2431)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2173)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2431)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2173)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2431)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2173)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2431)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2173)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2431)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2173)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2431)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2173)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2431)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2173)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2431)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2173)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2431)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2173)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2431)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2173)
at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:2390)
at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1741)
at android.app.Activity.dispatchTouchEvent(Activity.java:2826)
at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:2351)
at android.view.View.dispatchPointerEvent(View.java:8590)
at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:4098)
at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:3964)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3488)
at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3541)
at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3507)
at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3515)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3488)
at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3541)
at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3507)
at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:3617)
at android

如何处理此错误并获取第一个可见项目位置?

【问题讨论】:

  • 我猜它发生在第一次初始化时。现在,在调用 findFirstVisible 之前检查它是否有任何子节点,如果您可以在 b.android.com 上创建错误报告,那就太好了。

标签: java android android-recyclerview


【解决方案1】:

我用这段代码对其进行了测试,它适用于我

int positionView = ((LinearLayoutManager)recyclerView.getLayoutManager()).findFirstVisibleItemPosition();

我使用了回收视图参数。

【讨论】:

  • 如果你使用的是类似 StaggeredGridLayoutManager() 的东西,那么方法的签名就会改变。 {currentScrollPosition = (recyclerView?.layoutManager as StaggeredGridLayoutManager) .findLastCompletelyVisibleItemPositions(intArrayOf(0,1))[1]}
  • 对于 kotlin 使用 val positionView = (recyclerView.layoutManager as LinearLayoutManager).findFirstVisibleItemPosition()
【解决方案2】:

试试这个:

int position = layoutManager.findFirstVisibleItemPositions(null)[0];

其中layoutManager 是您在recyclerview 中设置的内容。

例如,

layoutManager = new StaggeredGridLayoutManager(2,StaggeredGridLayoutManager.VERTICAL);
mrecyclerView.setLayoutManager(layoutManager );

【讨论】:

  • 这个解决方案对我有用。请告诉我解决方案是否有问题。 layoutManager.findFirstVisibleItemPositions(null) 将返回一个新数组。 link
【解决方案3】:

使用这两种方法:

    /**
     * @return Last visible item position for staggeredGridLayoutManager
     */
    private int getLastVisibleItem(int[] lastVisibleItemPositions) {
        int maxSize = 0;
        for (int position : lastVisibleItemPositions) {
            if (position > maxSize) {
                maxSize = position;
            }
        }
        return maxSize;
    }

    /**
     * @return First visible item position for staggeredGridLayoutManager
     */
    private int getFirstVisibleItem(int[] firstVisibleItemPositions) {
        int minSize = 0;
        if (firstVisibleItemPositions.length > 0) {
            minSize = firstVisibleItemPositions[0];
            for (int position : firstVisibleItemPositions) {
                if (position < minSize) {
                    minSize = position;
                }
            }
        }
        return minSize;
    }

和getLastVisibleItem方法如下:

                    int[] lastVisibleItemPositions = ((StaggeredGridLayoutManager) layoutManager).findLastVisibleItemPositions(null);
                    int[] firstVisibleItemPositions = ((StaggeredGridLayoutManager) layoutManager).findFirstVisibleItemPositions(null);
                    // get maximum element within the list
                    lastVisibleItem = getLastVisibleItem(lastVisibleItemPositions);
                    firstVisibleItem = getFirstVisibleItem(firstVisibleItemPositions);

【讨论】:

    【解决方案4】:

    你可以用这个:

    int[] firstVisibleItemPositions = new int[yourNumberOfColumns];
    int pastVisiblesItems = layoutManager.findFirstVisibleItemPositions(firstVisibleItem‌​Positions)[0];
    

    【讨论】:

      【解决方案5】:

      这是 RecyclerView StaggeredGridLayoutManager 中的一个错误:

      https://code.google.com/p/android/issues/detail?id=180521

      https://code.google.com/p/android/issues/detail?id=181461

      解决方法是尝试/捕获异常:

      try {
          ((StaggeredGridLayoutManager)getLayoutManager()).findFirstVisibleItemPositions(firstVisibleItemPositions);
      } catch (NullPointerException ex) {
          // workaround for RecyclerView bug. assume not laid out, so no items visible
          firstVisibleItemPositions[0] = RecyclerView.NO_POSITION;
          firstVisibleItemPositions[1] = RecyclerView.NO_POSITION;
      }
      

      【讨论】:

        【解决方案6】:

        如果您使用的是 StaggeredGridLayoutManager,您可以找到 findLastVisibleItemPositions,如下所示:

        int visibleThreshold =1;
        final StaggeredGridLayoutManager linearLayoutManager = (StaggeredGridLayoutManager) mRecyclerViewAllPost.getLayoutManager();
            mRecyclerViewAllPost.addOnScrollListener(new RecyclerView.OnScrollListener() {
                @Override
                public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                    super.onScrolled(recyclerView, dx, dy);
        
                    int[] lastVisibleItemPositions = linearLayoutManager.findLastVisibleItemPositions(null);
                    int lastVisibleItem = getLastVisibleItem(lastVisibleItemPositions);
                    int totalItemCount = linearLayoutManager.getItemCount();
                    if (!isLoading && totalItemCount <= (lastVisibleItem + visibleThreshold)) {
                        print("load more item ");
                        isLoading = true;
                    }
                }
            });
        

        getLastVisibleItem方法如下:

        public int getLastVisibleItem(int[] lastVisibleItemPositions) {
            int maxSize = 0;
            for (int i = 0; i < lastVisibleItemPositions.length; i++) {
                if (i == 0) {
                    maxSize = lastVisibleItemPositions[i];
                }
                else if (lastVisibleItemPositions[i] > maxSize) {
                    maxSize = lastVisibleItemPositions[i];
                }
            }
            return maxSize;
        }
        

        【讨论】:

        • 请你告诉我,如果实现这个方法,我可以把这个'new StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.VERTICAL)'放在哪里
        • @VasantRaval layoutManager = new StaggeredGridLayoutManager(2,StaggeredGridLayoutManager.VERTICAL); mrecyclerView.setLayoutManager(layoutManager); stackoverflow.com/a/29529952/2897365
        【解决方案7】:

        你可以这样试试:

        StaggeredGridLayoutManager staggeredGridLayoutManager = (StaggeredGridLayoutManager) recyclerView.getLayoutManager();
        

        或者你可以直接使用你的staggeredlayoutManager对象而不是上面的对象:

        int[] into = staggeredGridLayoutManager .findLastVisibleItemPositions(null);
        List<Integer> intoList = new ArrayList<>();
        
        for (int i : into) 
        {
         intoList.add(i);
        }
        
        
        
        int firstVisbleoitem= Collections.max(intoList);
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-09-04
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多