336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.
https://guides.codepath.com/android/Endless-Scrolling-with-AdapterViews-and-RecyclerView
위 URL을 가보시면 ListView와 GridView 그리고 RecyclerView에서 Last Position을 알아보는 소스가 공유 되어 있습니다.
아래 2016년 1월 버전보다 업데이트가 된 내용이라 공유 해드립니다.
(참고로 이전 버전은 ScrollListener를 초기화 하는데 문제가 있었습니다.)
아래 소스는 RecyclerView에 적용 할 수 있는 소스 입니다.
public abstract class EndlessRecyclerViewScrollListener extends RecyclerView.OnScrollListener { // The minimum amount of items to have below your current scroll position // before loading more. private int visibleThreshold = 5; // The current offset index of data you have loaded private int currentPage = 0; // The total number of items in the dataset after the last load private int previousTotalItemCount = 0; // True if we are still waiting for the last set of data to load. private boolean loading = true; // Sets the starting page index private int startingPageIndex = 0; RecyclerView.LayoutManager mLayoutManager; public EndlessRecyclerViewScrollListener(LinearLayoutManager layoutManager) { this.mLayoutManager = layoutManager; } public EndlessRecyclerViewScrollListener(GridLayoutManager layoutManager) { this.mLayoutManager = layoutManager; visibleThreshold = visibleThreshold * layoutManager.getSpanCount(); } public EndlessRecyclerViewScrollListener(StaggeredGridLayoutManager layoutManager) { this.mLayoutManager = layoutManager; visibleThreshold = visibleThreshold * layoutManager.getSpanCount(); } 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; } // This happens many times a second during a scroll, so be wary of the code you place here. // We are given a few useful parameters to help us work out if we need to load some more data, // but first we check if we are waiting for the previous load to finish. @Override public void onScrolled(RecyclerView view, int dx, int dy) { int lastVisibleItemPosition = 0; int totalItemCount = mLayoutManager.getItemCount(); if (mLayoutManager instanceof StaggeredGridLayoutManager) { int[] lastVisibleItemPositions = ((StaggeredGridLayoutManager) mLayoutManager).findLastVisibleItemPositions(null); // get maximum element within the list lastVisibleItemPosition = getLastVisibleItem(lastVisibleItemPositions); } else if (mLayoutManager instanceof GridLayoutManager) { lastVisibleItemPosition = ((GridLayoutManager) mLayoutManager).findLastVisibleItemPosition(); } else if (mLayoutManager instanceof LinearLayoutManager) { lastVisibleItemPosition = ((LinearLayoutManager) mLayoutManager).findLastVisibleItemPosition(); } // If the total item count is zero and the previous isn't, assume the // list is invalidated and should be reset back to initial state if (totalItemCount < previousTotalItemCount) { this.currentPage = this.startingPageIndex; this.previousTotalItemCount = totalItemCount; if (totalItemCount == 0) { this.loading = true; } } // If it’s still loading, we check to see if the dataset count has // changed, if so we conclude it has finished loading and update the current page // number and total item count. if (loading && (totalItemCount > previousTotalItemCount)) { loading = false; previousTotalItemCount = totalItemCount; } // If it isn’t currently loading, we check to see if we have breached // the visibleThreshold and need to reload more data. // If we do need to reload some more data, we execute onLoadMore to fetch the data. // threshold should reflect how many total columns there are too if (!loading && (lastVisibleItemPosition + visibleThreshold) > totalItemCount) { currentPage++; onLoadMore(currentPage, totalItemCount, view); loading = true; } } // Call this method whenever performing new searches public void resetState() { this.currentPage = this.startingPageIndex; this.previousTotalItemCount = 0; this.loading = true; } // Defines the process for actually loading more data based on page public abstract void onLoadMore(int page, int totalItemsCount, RecyclerView view); }
https://gist.github.com/nesquena/d09dc68ff07e845cc622
현재 2016년 11월 16일 사용해봤을 때 문제 없이 잘 돌아 갑니다.
참고하세요.
=========================== 2016년 1월 버전 ==============================
RecyclerView를 사용할 때, 마지막 포지션에 위치했는지 파악하는 좋은 리스너가 있어서 공유 드립니다.
https://gist.github.com/mipreamble/b6d4b3d65b0b4775a22e
/** * Custom Scroll listener for RecyclerView. * Based on implementation https://gist.github.com/ssinss/e06f12ef66c51252563e */ public abstract class EndlessRecyclerOnScrollListener extends RecyclerView.OnScrollListener { public static String TAG = "EndlessScrollListener"; private int previousTotal = 0; // The total number of items in the dataset after the last load private boolean loading = true; // True if we are still waiting for the last set of data to load. private int visibleThreshold = 5; // The minimum amount of items to have below your current scroll position before loading more. int firstVisibleItem, visibleItemCount, totalItemCount; private int currentPage = 1; RecyclerViewPositionHelper mRecyclerViewHelper; @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { super.onScrolled(recyclerView, dx, dy); mRecyclerViewHelper = RecyclerViewPositionHelper.createHelper(recyclerView); visibleItemCount = recyclerView.getChildCount(); totalItemCount = mRecyclerViewHelper.getItemCount(); firstVisibleItem = mRecyclerViewHelper.findFirstVisibleItemPosition(); if (loading) { if (totalItemCount > previousTotal) { loading = false; previousTotal = totalItemCount; } } if (!loading && (totalItemCount - visibleItemCount) <= (firstVisibleItem + visibleThreshold)) { // End has been reached // Do something currentPage++; onLoadMore(currentPage); loading = true; } } //Start loading public abstract void onLoadMore(int currentPage);
}
/** * RecyclerView position helper class for any LayoutManager. * * compile 'com.android.support:recyclerview-v7:22.0.0' */ import android.support.v7.widget.OrientationHelper; import android.support.v7.widget.RecyclerView; import android.view.View; public class RecyclerViewPositionHelper { final RecyclerView recyclerView; final RecyclerView.LayoutManager layoutManager; RecyclerViewPositionHelper(RecyclerView recyclerView) { this.recyclerView = recyclerView; this.layoutManager = recyclerView.getLayoutManager(); } public static RecyclerViewPositionHelper createHelper(RecyclerView recyclerView) { if (recyclerView == null) { throw new NullPointerException("Recycler View is null"); } return new RecyclerViewPositionHelper(recyclerView); } /** * Returns the adapter item count. * * @return The total number on items in a layout manager */ public int getItemCount() { return layoutManager == null ? 0 : layoutManager.getItemCount(); } /** * Returns the adapter position of the first visible view. This position does not include * adapter changes that were dispatched after the last layout pass. * * @return The adapter position of the first visible item or {@link RecyclerView#NO_POSITION} if * there aren't any visible items. */ public int findFirstVisibleItemPosition() { final View child = findOneVisibleChild(0, layoutManager.getChildCount(), false, true); return child == null ? RecyclerView.NO_POSITION : recyclerView.getChildAdapterPosition(child); } /** * Returns the adapter position of the first fully visible view. This position does not include * adapter changes that were dispatched after the last layout pass. * * @return The adapter position of the first fully visible item or * {@link RecyclerView#NO_POSITION} if there aren't any visible items. */ public int findFirstCompletelyVisibleItemPosition() { final View child = findOneVisibleChild(0, layoutManager.getChildCount(), true, false); return child == null ? RecyclerView.NO_POSITION : recyclerView.getChildAdapterPosition(child); } /** * Returns the adapter position of the last visible view. This position does not include * adapter changes that were dispatched after the last layout pass. * * @return The adapter position of the last visible view or {@link RecyclerView#NO_POSITION} if * there aren't any visible items */ public int findLastVisibleItemPosition() { final View child = findOneVisibleChild(layoutManager.getChildCount() - 1, -1, false, true); return child == null ? RecyclerView.NO_POSITION : recyclerView.getChildAdapterPosition(child); } /** * Returns the adapter position of the last fully visible view. This position does not include * adapter changes that were dispatched after the last layout pass. * * @return The adapter position of the last fully visible view or * {@link RecyclerView#NO_POSITION} if there aren't any visible items. */ public int findLastCompletelyVisibleItemPosition() { final View child = findOneVisibleChild(layoutManager.getChildCount() - 1, -1, true, false); return child == null ? RecyclerView.NO_POSITION : recyclerView.getChildAdapterPosition(child); } View findOneVisibleChild(int fromIndex, int toIndex, boolean completelyVisible, boolean acceptPartiallyVisible) { OrientationHelper helper; if (layoutManager.canScrollVertically()) { helper = OrientationHelper.createVerticalHelper(layoutManager); } else { helper = OrientationHelper.createHorizontalHelper(layoutManager); } final int start = helper.getStartAfterPadding(); final int end = helper.getEndAfterPadding(); final int next = toIndex > fromIndex ? 1 : -1; View partiallyVisible = null; for (int i = fromIndex; i != toIndex; i += next) { final View child = layoutManager.getChildAt(i); final int childStart = helper.getDecoratedStart(child); final int childEnd = helper.getDecoratedEnd(child); if (childStart < end && childEnd > start) { if (completelyVisible) { if (childStart >= start && childEnd <= end) { return child; } else if (acceptPartiallyVisible && partiallyVisible == null) { partiallyVisible = child; } } else { return child; } } } return partiallyVisible; }
}
위 두 소스만 있으면 되고, 저 리스너를 RecyclerView에 addOnScrollListener로 설정하면 됩니다.
OnLoadMore 함수로 리턴 받을 수가 있습니다.
## 여기서 잠깐!!
마지막 포지션 리스너로써도 좋지만 RecyclerViewPositionHelper 클래스가 정말 잘 만들어져 있습니다.
화면에서 처음 보이는 포지션, 마지막으로 보이는 포지션등 함수를 지원 함으로써,
어떠한 위치에 포지션이 있는지를 확인 할수 있습니다.
참고하세요.
'나의 플랫폼 > 안드로이드' 카테고리의 다른 글
[Android] Get current fragment (0) | 2016.01.21 |
---|---|
[Android] 강제로 AppbarLayout 열기 (0) | 2016.01.21 |
[Android] 화면 전체 사이즈 구하기 (0) | 2016.01.20 |
[Android] skipped frames the application may be doing too much work on its main thread (0) | 2016.01.20 |
[Android] String 에서 Html Tag만 제거하는 방법 (0) | 2016.01.13 |