Recyclerview StaggeredGridLayoutManager - 查找最后一个可见项目

时间:2017-03-22 10:17:37

标签: android android-recyclerview staggeredgridlayout

我正在使用带有Endless Scroll的StaggeredGridLayoutManager的Recyclerview。当列表的最后一项对用户可见时,我想进行网络呼叫。所以这是我的代码:

<html>
<head>

    <script type='text/javascript' src='js/jquery-1.4.2.min.js'></script>
<script>

$('#menu-button').click(function(){
     $('#hide-menu').toggleClass('show-menu');
});
</script>
<style>
body
    {
       overflow:hidden;
    }

.menu-button
    {
        border:1px solid #000;
        color:fff;
        display:inline-block;
        cursor:pointer;
    }

.hide-menu
{
    background-color:#336ca6;
    position: absolute;
    top:0;
    right:0;
    z-index: 1;
    width: 300px;
    height: 100%;
    -webkit-transform: translate3d(300px,0,0);
    -moz-transform: translate3d(300px,0,0);
    -o-transform: translate3d(300px,0,0);
    -ms-transform: translate3d(300px,0,0);
    transform: translate3d(300px,0,0);      
    -webkit-transition: all 0.3s linear;
    -moz-transition: all 0.3s linear;
    -ms-transition: all 0.3s linear;
    -o-transition: all 0.3s linear;
    transition: all 0.3s linear;
}

.show-menu      
{
    -webkit-transform: translate3d(0,0,0);
    -moz-transform: translate3d(0,0,0);
    -o-transform: translate3d(0,0,0);
    -ms-transform: translate3d(0,0,0);
    transform: translate3d(0,0,0);
 }  
</style>
</head>
<body>
<center>
<br>

<div style='display:none;'>
    <img src="images/loader.gif" />
</div>

<form action="" name = "form">  
    <input type="text" name="name" id="fn" Placeholder="Search Something..." style="width:300px; padding:8px;"/>
    <input type="submit" value="Search" id="menu-button"style="padding:8px;"/>
</form>
<br>

<div id = "s-results">
    <!-- Search results here! -->
</div>
<nav id="hide-menu" class="hide-menu">
<script type = "text/javascript">
$(document).ready(function(){
    $('#s-results').load('search.php').show();


    $('#search-btn').click(function(){
        showValues();
    });

    $(function() {
        $('form').bind('submit',function(){
            showValues(); 
            return false; 
        });
    });

    function showValues() {
        $('#s-results').html('<img src="images/loader.gif" />');  

        $.post('search.php', { name: form.name.value },

        function(result){
            $('#s-results').html(result).show();
        });
    }

});
</script>

</center>
</nav>
</body>
</html>

我在第一次通话时从服务器获得9个值。因此,当我移动到最后一个索引[8]时,lastVisibleItem将为8并且visibleThreshold为1,totalItemCount为9,因此下一次网络调用应该发生。现在实际发生的是,当屏幕第一次加载时,lastVisibleItem应该是1或2,但是它返回8,结果,loadMore()被调用。

logcat的:

   public RecyclerViewAdapter(Context context) {

            Log.d(Const.DEBUG, "RecyclerViewAdapter Constructor()");

            this.context = context;

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

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

                    totalItemCount = staggeredGridLayoutManager.getItemCount();
                    lastVisibleItems = staggeredGridLayoutManager.findLastVisibleItemPositions(new int[mStaggeredLayoutManager.getSpanCount()]);

                    Log.d(Const.DEBUG, "LastVisibleItems: " + Arrays.toString(lastVisibleItems));
                    Log.d(Const.DEBUG, "LastVisibleItems Count: " + lastVisibleItems.length);

                    if (staggeredGridLayoutManager.getSpanCount() == 1) {
                        lastVisibleItem = lastVisibleItems[0];
                    } else if (staggeredGridLayoutManager.getSpanCount() == 2) {
                        lastVisibleItem = Math.max(lastVisibleItems[0], lastVisibleItems[1]);
                    } else if (staggeredGridLayoutManager.getSpanCount() == 3) {
                        lastVisibleItem = Math.max(Math.max(lastVisibleItems[0], lastVisibleItems[1]), lastVisibleItems[2]);
                    }


                    if (!isRefreshing && (totalItemCount <= lastVisibleItem + visibleThreshold)) {

                        Log.d(Const.DEBUG, "isRefreshing: " + isRefreshing);
                        Log.d(Const.DEBUG, "totalItemCount: " + totalItemCount);
                        Log.d(Const.DEBUG, "lastVisibileItem: " + lastVisibleItem);
                        Log.d(Const.DEBUG, "visibileThreshold: " + visibleThreshold);

                        Log.d(Const.DEBUG, "calling LoadMore()");

                        if (mIOnLoadMoreListener != null) {
                            mIOnLoadMoreListener.onLoadMore();
                        }

                        isRefreshing = true;
                    }
                }
            });

        }

上面的代码有什么问题?需要帮助请叫我。相同的代码之前运作良好。

3 个答案:

答案 0 :(得分:2)

试试这个。

    private int pastVisiblesItems, visibleItemCount, totalItemCount;
        private boolean loading = true;   
        private StaggeredGridLayoutManager layoutManager;
        private RecyclerView recyclerView ;

    @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            layoutManager=new StaggeredGridLayoutManager(2,1);
            recyclerView = (RecyclerView) findViewById(R.id.recycler_view);   
            recyclerView.setLayoutManager(layoutManager);
            recycleView.addOnScrollListener(new RecyclerView.OnScrollListener() {
                    @Override
                    public void onScrolled(RecyclerView recyclerView, int dx, int dy) {

                        if (dy > 0) //for vertical scrolling
                        {

                        } else if (dy < 0) {

                        }
                        if (dx > 0)//for horizontal scrolling
                        {
                           visibleItemCount = layoutManager.getChildCount();
                            totalItemCount = layoutManager.getItemCount();
                            pastVisiblesItems = layoutManager.findFirstVisibleItemPosition();

                            if (loading) {
                                if ((visibleItemCount + pastVisiblesItems) >= totalItemCount) {
                                    loading = false;                        
                                    loadMore();  //desired function call                      
                                }
                            }
                        } 
                    }
                });
    }

API调用成功后请不要忘记 loading = true

希望它有所帮助......

答案 1 :(得分:0)

private void recyclerViewOnScroll(RecyclerView recyclerView, final StaggeredGridLayoutManager staggeredGridLayoutManager) {
        recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                super.onScrolled(recyclerView, dx, dy);

                if (dy > 0) {

                    totalItemCount = staggeredGridLayoutManager.getItemCount();
                    if (lastPositions == null)
                        lastPositions = new int[staggeredGridLayoutManager.getSpanCount()];
                    lastPositions = staggeredGridLayoutManager.findLastCompletelyVisibleItemPositions(lastPositions);
                    lastVisibleItem = Math.max(lastPositions[0], lastPositions[1]);//findMax(lastPositions);

                    if (!loading && totalItemCount >= 20 && totalItemCount <= (lastVisibleItem + visibleThreshold)) {
                        // End has been reached
                        if (onLoadMoreListener != null) {
                            onLoadMoreListener.onLoadMore();
                        }
                        loading = true;
                    }
                }
            }
        });
    }

答案 2 :(得分:0)

以下代码对我有用:

//return true if it's last item visited
 private boolean isLastItemDisplaying(RecyclerView recyclerView) {
    if (recyclerView.getAdapter().getItemCount() != 0) {
        //int lastVisibleItemPosition = ((StaggeredGridLayoutManager)recyclerView.getLayoutManager()).findLastVisibleItemPositions();
        int[] lastVisibleItemPositions = ((StaggeredGridLayoutManager) Objects.requireNonNull(recyclerView.getLayoutManager())).findLastVisibleItemPositions(null);
        // get maximum element within the list
        int lastVisibleItemPosition = getLastVisibleItem(lastVisibleItemPositions);
        return lastVisibleItemPosition != RecyclerView.NO_POSITION && lastVisibleItemPosition == recyclerView.getAdapter().getItemCount() - 1;
    }
    return false;
}



//get last item
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;
}