RecyclerView로 무한 목록을 구현하는 방법은 무엇입니까?
는 싶다니습바꾸를 바꾸고 싶습니다.ListView
저는 그것을 사용하고 싶습니다.onScroll
의RecyclerView
사용자가 목록 끝까지 스크롤했는지 확인합니다.
사용자가 목록 끝으로 스크롤하여 REST 서비스에서 새 데이터를 가져올 수 있는지 어떻게 알 수 있습니까?
@Kushal 덕분에 이렇게 구현했습니다.
private boolean loading = true;
int pastVisiblesItems, visibleItemCount, totalItemCount;
mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
if (dy > 0) { //check for scroll down
visibleItemCount = mLayoutManager.getChildCount();
totalItemCount = mLayoutManager.getItemCount();
pastVisiblesItems = mLayoutManager.findFirstVisibleItemPosition();
if (loading) {
if ((visibleItemCount + pastVisiblesItems) >= totalItemCount) {
loading = false;
Log.v("...", "Last Item Wow !");
// Do pagination.. i.e. fetch new data
loading = true;
}
}
}
}
});
추가하는 것을 잊지 마십시오.
LinearLayoutManager mLayoutManager;
mLayoutManager = new LinearLayoutManager(this);
mRecyclerView.setLayoutManager(mLayoutManager);
이 변수들을 만드세요.
private int previousTotal = 0;
private boolean loading = true;
private int visibleThreshold = 5;
int firstVisibleItem, visibleItemCount, totalItemCount;
재생기 보기에 대해 스크롤을 설정합니다.
mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
visibleItemCount = mRecyclerView.getChildCount();
totalItemCount = mLayoutManager.getItemCount();
firstVisibleItem = mLayoutManager.findFirstVisibleItemPosition();
if (loading) {
if (totalItemCount > previousTotal) {
loading = false;
previousTotal = totalItemCount;
}
}
if (!loading && (totalItemCount - visibleItemCount)
<= (firstVisibleItem + visibleThreshold)) {
// End has been reached
Log.i("Yaeye!", "end called");
// Do something
loading = true;
}
}
});
참고: 사용 중인지 확인하십시오.
LinearLayoutManager
로의 레이아웃 로서.RecyclerView
.
LinearLayoutManager mLayoutManager;
mLayoutManager = new LinearLayoutManager(this);
mRecyclerView.setLayoutManager(mLayoutManager);
그리드의 경우
GridLayoutManager mLayoutManager;
mLayoutManager = new GridLayoutManager(getActivity(), spanCount);
mRecyclerView.setLayoutManager(mLayoutManager);
당신의 끝없는 두루마리들과 즐거운 시간 보내세요!!^.^
업데이트: mRecyclerView.
setOnScrollListener()는 더 이상 사용되지 않습니다. 다음으로 대체하십시오.mRecyclerView.addOnScrollListener()
그러면 경고는 사라질 것입니다!이 SO 질문에서 더 많은 내용을 읽을 수 있습니다.
안드로이드가 이제 공식적으로 코틀린을 지원하기 때문에, 여기 동일한 것에 대한 업데이트가 있습니다.
온스크롤 수신기 만들기
class OnScrollListener(val layoutManager: LinearLayoutManager, val adapter: RecyclerView.Adapter<RecyclerAdapter.ViewHolder>, val dataList: MutableList<Int>) : RecyclerView.OnScrollListener() {
var previousTotal = 0
var loading = true
val visibleThreshold = 10
var firstVisibleItem = 0
var visibleItemCount = 0
var totalItemCount = 0
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
super.onScrolled(recyclerView, dx, dy)
visibleItemCount = recyclerView.childCount
totalItemCount = layoutManager.itemCount
firstVisibleItem = layoutManager.findFirstVisibleItemPosition()
if (loading) {
if (totalItemCount > previousTotal) {
loading = false
previousTotal = totalItemCount
}
}
if (!loading && (totalItemCount - visibleItemCount) <= (firstVisibleItem + visibleThreshold)) {
val initialSize = dataList.size
updateDataList(dataList)
val updatedSize = dataList.size
recyclerView.post { adapter.notifyItemRangeInserted(initialSize, updatedSize) }
loading = true
}
}
}
다음과 같이 RecyclerView에 추가합니다.
recyclerView.addOnScrollListener(OnScrollListener(layoutManager, adapter, dataList))
전체 코드 예제를 보려면 이 Github repo를 참조하십시오.
마지막 항목이 완전히 표시될 때만 알림을 받으려는 사용자는 다음을 사용할 수 있습니다.View.canScrollVertically()
.
다음은 제 구현입니다.
public abstract class OnVerticalScrollListener
extends RecyclerView.OnScrollListener {
@Override
public final void onScrolled(RecyclerView recyclerView, int dx, int dy) {
if (!recyclerView.canScrollVertically(-1)) {
onScrolledToTop();
} else if (!recyclerView.canScrollVertically(1)) {
onScrolledToBottom();
} else if (dy < 0) {
onScrolledUp();
} else if (dy > 0) {
onScrolledDown();
}
}
public void onScrolledUp() {}
public void onScrolledDown() {}
public void onScrolledToTop() {}
public void onScrolledToBottom() {}
}
참고: 사용할 수 있습니다.recyclerView.getLayoutManager().canScrollVertically()
API < 14를 지원하려면.
여기 또 다른 접근법이 있습니다.모든 레이아웃 관리자와 함께 작동합니다.
- 어댑터 클래스 추상화
- 그런 다음 어댑터 클래스에 추상 메서드를 만듭니다(예: load()).
- 인바운드 뷰홀더가 마지막인 경우 위치를 확인하고 호출 부하()
- 활동 또는 조각에서 어댑터 개체를 만드는 동안 load() 함수를 재정의합니다.
- 오버라이드 로드 기능에서 load more 호출을 구현합니다.
자세한 이해를 위해 블로그 게시물과 예제 프로젝트를 작성했습니다. 여기에서 http://sab99r.com/blog/recyclerview-endless-load-more/ .
나의 어댑터.java
public abstract class MyAdapter extends RecyclerView.Adapter<ViewHolder>{
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
//check for last item
if ((position >= getItemCount() - 1))
load();
}
public abstract void load();
}
내 활동.java
public class MainActivity extends AppCompatActivity {
List<Items> items;
MyAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
...
adapter=new MyAdapter(items){
@Override
public void load() {
//implement your load more here
Item lastItem=items.get(items.size()-1);
loadMore();
}
};
}
}
제 대답은 Noor의 수정된 버전입니다.는 에서합습다에서 했습니다.ListView
가 가내있었곳던▁i를 먹었던 곳.EndlessScrollListener
찾을 수에 대한 (SO 많은서쉽찾수있음을)RecyclerView
그래서 저는 a를 원했습니다.EndlessRecyclScrollListener
내 과거 청취자를 쉽게 업데이트할 수 있습니다.
여기 코드가 있습니다. 도움이 되길 바랍니다.
public abstract class EndlessScrollRecyclListener extends RecyclerView.OnScrollListener
{
// The total number of items in the dataset after the last load
private int previousTotalItemCount = 0;
private boolean loading = true;
private int visibleThreshold = 5;
int firstVisibleItem, visibleItemCount, totalItemCount;
private int startingPageIndex = 0;
private int currentPage = 0;
@Override
public void onScrolled(RecyclerView mRecyclerView, int dx, int dy)
{
super.onScrolled(mRecyclerView, dx, dy);
LinearLayoutManager mLayoutManager = (LinearLayoutManager) mRecyclerView
.getLayoutManager();
visibleItemCount = mRecyclerView.getChildCount();
totalItemCount = mLayoutManager.getItemCount();
firstVisibleItem = mLayoutManager.findFirstVisibleItemPosition();
onScroll(firstVisibleItem, visibleItemCount, totalItemCount);
}
public void onScroll(int firstVisibleItem, int visibleItemCount, int totalItemCount)
{
// 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;
currentPage++;
}
// 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.
if (!loading && (totalItemCount - visibleItemCount) <= (firstVisibleItem +
visibleThreshold))
{
onLoadMore(currentPage + 1, totalItemCount);
loading = true;
}
}
// Defines the process for actually loading more data based on page
public abstract void onLoadMore(int page, int totalItemsCount);
}
저는 매우 간단합니다.
private boolean mLoading = false;
mList.setOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
int totalItem = mLinearLayoutManager.getItemCount();
int lastVisibleItem = mLinearLayoutManager.findLastVisibleItemPosition();
if (!mLoading && lastVisibleItem == totalItem - 1) {
mLoading = true;
// Scrolled to bottom. Do something here.
mLoading = false;
}
}
});
비동기 작업에 주의: 비동기 작업이 끝날 때 mLoading을 변경해야 합니다.그것이 도움이 되기를 바랍니다!
코틀린의 확장 기능의 힘으로, 코드는 훨씬 더 우아하게 보일 수 있습니다.원하는 위치에 저장(확장기 안에 있음)functions.kt 파일):
/**
* WARNING: This assumes the layout manager is a LinearLayoutManager
*/
fun RecyclerView.addOnScrolledToEnd(onScrolledToEnd: () -> Unit){
this.addOnScrollListener(object: RecyclerView.OnScrollListener(){
private val VISIBLE_THRESHOLD = 5
private var loading = true
private var previousTotal = 0
override fun onScrollStateChanged(recyclerView: RecyclerView,
newState: Int) {
with(layoutManager as LinearLayoutManager){
val visibleItemCount = childCount
val totalItemCount = itemCount
val firstVisibleItem = findFirstVisibleItemPosition()
if (loading && totalItemCount > previousTotal){
loading = false
previousTotal = totalItemCount
}
if(!loading && (totalItemCount - visibleItemCount) <= (firstVisibleItem + visibleThreshold)){
onScrolledToEnd()
loading = true
}
}
}
})
}
그리고 다음과 같이 사용합니다.
youRecyclerView.addOnScrolledToEnd {
//What you want to do once the end is reached
}
이 해결책은 Kushal Sharma의 대답에 기반을 두고 있습니다.그러나 다음과 같은 이유로 이 기능이 약간 더 좋습니다.
- 그것은 사용합니다.
onScrollStateChanged
에onScroll
이게 더 좋은 이유는onScroll
, RecyclerView에서는 어떤 종류의 움직임이 있을 때마다 호출됩니다.onScrollStateChanged
RecyclerView 상태가 변경된 경우에만 호출됩니다.용사를 합니다.onScrollStateChanged
CPU 시간을 절약하고 결과적으로 배터리를 절약할 수 있습니다. - 이것은 확장 기능을 사용하기 때문에 사용자가 가지고 있는 모든 재활용 보기에서 사용할 수 있습니다.고객 코드는 한 줄에 불과합니다.
대부분의 대답은 다음과 같이 가정하고 있습니다.RecyclerView
를 사용합니다.LinearLayoutManager
또는GridLayoutManager
아니 심지어는StaggeredGridLayoutManager
또는 스크롤이 수직 또는 수평이지만 아무도 완전히 일반적인 답변을 게시하지 않았다고 가정합니다.
ViewHolder
의 어댑터는 분명히 좋은 솔루션이 아닙니다.에 1개 의 호스트가 있을 수 RecyclerView
그것을 사용합니다.그것은 그들의 내용을 "적응"합니다.RecyclerView(현재 사용자에게 표시되는 내용을 담당하는 클래스이지 콘텐츠를 제공하는 클래스만 담당하는 어댑터가 아닙니다)여야 합니다.RecyclerView
로드할 항목이 더 필요함을 시스템에 알려야 합니다.
여기에 RecycerView(RecycerView)의 추상화된 클래스만 사용하는 솔루션이 있습니다.레이아웃 관리자 및 재활용 보기.어댑터):
/**
* Listener to callback when the last item of the adpater is visible to the user.
* It should then be the time to load more items.
**/
public abstract class LastItemListener extends RecyclerView.OnScrollListener {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
// init
RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();
RecyclerView.Adapter adapter = recyclerView.getAdapter();
if (layoutManager.getChildCount() > 0) {
// Calculations..
int indexOfLastItemViewVisible = layoutManager.getChildCount() -1;
View lastItemViewVisible = layoutManager.getChildAt(indexOfLastItemViewVisible);
int adapterPosition = layoutManager.getPosition(lastItemViewVisible);
boolean isLastItemVisible = (adapterPosition == adapter.getItemCount() -1);
// check
if (isLastItemVisible)
onLastItemVisible(); // callback
}
}
/**
* Here you should load more items because user is seeing the last item of the list.
* Advice: you should add a bollean value to the class
* so that the method {@link #onLastItemVisible()} will be triggered only once
* and not every time the user touch the screen ;)
**/
public abstract void onLastItemVisible();
}
// --- Exemple of use ---
myRecyclerView.setOnScrollListener(new LastItemListener() {
public void onLastItemVisible() {
// start to load more items here.
}
}
간단명료하게 말하면 이렇게 하는 것입니다.
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener()
{
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy)
{
if(!recyclerView.canScrollVertically(1) && dy != 0)
{
// Load more results here
}
}
});
승인된 답변이 완벽하게 작동하지만 아래 솔루션은 setOnScrollListener가 사용되지 않으므로 addOnScrollListener를 사용하고 변수의 수와 조건을 줄입니다.
final LinearLayoutManager layoutManager = new LinearLayoutManager(context);
feedsRecyclerView.setLayoutManager(layoutManager);
feedsRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
if (dy > 0) {
if ((layoutManager.getChildCount() + layoutManager.findFirstVisibleItemPosition()) >= layoutManager.getItemCount()) {
Log.d("TAG", "End of list");
//loadMore();
}
}
}
});
질문에 대한 답변이 매우 많지만, 무한 목록 뷰를 만든 경험을 공유하고자 합니다.우리는 최근 특정 지점까지 목록을 무한 스크롤하여 사이클에서 작동할 수 있는 커스텀 캐러셀 레이아웃 매니저를 구현했습니다.여기 깃허브에 대한 자세한 설명이 있습니다.
사용자 지정 레이아웃 관리자를 만드는 방법에 대한 짧지만 유용한 권장 사항과 함께 이 기사를 살펴보시기 바랍니다. http://cases.azoft.com/create-custom-layoutmanager-android/
좋아요, BindView를 사용해서 해봤어요.RecyclerView의 홀더 메서드입니다.어댑터.
어댑터:
public interface OnViewHolderListener {
void onRequestedLastItem();
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
...
if (position == getItemCount() - 1) onViewHolderListener.onRequestedLastItem();
}
조각(또는 활동):
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
contentView = inflater.inflate(R.layout.comments_list, container, false);
recyclerView = (RecyclerView) mContentView.findViewById(R.id.my_recycler_view);
adapter = new Adapter();
recyclerView.setAdapter(adapter);
...
adapter.setOnViewHolderListener(new Adapter.OnViewHolderListener() {
@Override
public void onRequestedLastItem() {
//TODO fetch new data from webservice
}
});
return contentView;
}
recyclerList.setOnScrollListener(new RecyclerView.OnScrollListener()
{
@Override
public void onScrolled(RecyclerView recyclerView, int dx,int dy)
{
super.onScrolled(recyclerView, dx, dy);
}
@Override
public void onScrollStateChanged(RecyclerView recyclerView,int newState)
{
int totalItemCount = layoutManager.getItemCount();
int lastVisibleItem = layoutManager.findLastVisibleItemPosition();
if (totalItemCount> 1)
{
if (lastVisibleItem >= totalItemCount - 1)
{
// End has been reached
// do something
}
}
}
});
저는 더 많이 사용하도록 노력할 것입니다.LayoutManager
(예:)LinearLayoutManager
및 override ) 및정의재scrollVerticallyBy()
방법.먼저, 전화를 걸겠습니다.super
반환된 정수 값을 확인합니다.이 값다음과같을경우이경우▁to와 ,0
그런 다음 하단 또는 상단 테두리에 도달합니다.그럼 제가 사용하겠습니다.findLastVisibleItemPosition()
어떤 경계에 도달했는지 확인하고 필요한 경우 더 많은 데이터를 로드하는 방법입니다.생각일 뿐이야.
또한 오버스크롤을 허용하고 "로드" 표시기를 표시할 수 있는 방법에서 값을 반환할 수도 있습니다.
에서 이 했습니다.onBindViewHolder
의 의방의 RecyclerView.Adapter
학급.
if (position == mItems.size() - 1 && mCurrentPage <= mTotalPageCount) {
if (mCurrentPage == mTotalPageCount) {
mLoadImagesListener.noMorePages();
} else {
int newPage = mCurrentPage + 1;
mLoadImagesListener.loadPage(newPage);
}
}
이 코드를 사용하면 RecyclerView가 마지막 항목에 도달하면 현재 페이지와 인터페이스의 콜백이 증가합니다. 이 인터페이스는 api에서 더 많은 데이터를 로드하고 새 결과를 어댑터에 추가하는 역할을 합니다.
이것이 명확하지 않다면 더 완전한 예를 게시할 수 있습니까?
여기에서 StagedGridLayoutManager를 사용하는 사용자는 제가 구현한 것과 같은 이점이 있습니다.
private class ScrollListener extends RecyclerView.OnScrollListener {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
firstVivisibleItems = mLayoutManager.findFirstVisibleItemPositions(firstVivisibleItems);
if(!recyclerView.canScrollVertically(1) && firstVivisibleItems[0]!=0) {
loadMoreImages();
}
}
private boolean loadMoreImages(){
Log.d("myTag", "LAST-------HERE------");
return true;
}
}
이 이름이 지정된 페이지에 대해 사용하기 쉬운 라이브러리가 있습니다.ListView 및 RecyclerView(LinearLayout, GridLayout 및 StagedGridLayout)를 모두 지원합니다.
여기 Github의 프로젝트 링크가 있습니다.
로딩 이벤트를 감지하는 방법은 스크롤을 감지하는 것이 아니라 마지막 뷰가 첨부되었는지 확인하는 것입니다.마지막 뷰가 첨부되었다면 더 많은 콘텐츠를 로드하는 타이밍으로 간주합니다.
class MyListener implements RecyclerView.OnChildAttachStateChangeListener {
RecyclerView mRecyclerView;
MyListener(RecyclerView view) {
mRecyclerView = view;
}
@Override
public void onChildViewAttachedToWindow(View view) {
RecyclerView.Adapter adapter = mRecyclerView.getAdapter();
RecyclerView.LayoutManager mgr = mRecyclerView.getLayoutManager();
int adapterPosition = mgr.getPosition(view);
if (adapterPosition == adapter.getItemCount() - 1) {
// last view was attached
loadMoreContent();
}
@Override
public void onChildViewDetachedFromWindow(View view) {}
}
추상 클래스를 만들고 RecyclerView를 확장합니다.OnScrollListener
public abstract class EndlessRecyclerOnScrollListener extends RecyclerView.OnScrollListener { private int previousTotal = 0; private boolean loading = true; private int visibleThreshold; private int firstVisibleItem, visibleItemCount, totalItemCount; private RecyclerView.LayoutManager layoutManager; public EndlessRecyclerOnScrollListener(RecyclerView.LayoutManager layoutManager, int visibleThreshold) { this.layoutManager = layoutManager; this.visibleThreshold = visibleThreshold; } @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { super.onScrolled(recyclerView, dx, dy); visibleItemCount = recyclerView.getChildCount(); totalItemCount = layoutManager.getItemCount(); firstVisibleItem = ((LinearLayoutManager)layoutManager).findFirstVisibleItemPosition(); if (loading) { if (totalItemCount > previousTotal) { loading = false; previousTotal = totalItemCount; } } if (!loading && (totalItemCount - visibleItemCount) <= (firstVisibleItem + visibleThreshold)) { onLoadMore(); loading = true; } } public abstract void onLoadMore();}
활동 중(또는 조각) 재활용자에 addOnScrollListener 추가View
LinearLayoutManager mLayoutManager = new LinearLayoutManager(this); recyclerView.setLayoutManager(mLayoutManager); recyclerView.addOnScrollListener(new EndlessRecyclerOnScrollListener(mLayoutManager, 3) { @Override public void onLoadMore() { //TODO ... } });
@John T가 제안하는 바와 같이.아래 코드 블록을 사용하면 됩니다. 정말 짧고 아름다우며 단순합니다. :D
public void loadMoreOnRecyclerView() {
mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(@NonNull @NotNull RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
if (!recyclerView.canScrollVertically(1) && dy != 0) {
//Load more items here
}
}
});
}
제 보고서를 따라가면 작동 방식을 이해할 수 있습니다.
다음과 같은 앱에 대한 설명 정보: https://github.com/skydoves/Pokedex#readme
Recycler View를 사용하여 페이지를 작성하는 방법에 대한 꽤 자세한 예가 있습니다.상위 레벨에서는 PAGE_SIZE가 설정되어 있습니다. 예를 들어 30이라고 합시다.그래서 저는 30개의 아이템을 요청하고 30개를 돌려받으면 다음 페이지를 요청합니다.항목이 30개 미만이면 마지막 페이지에 도달했음을 나타내는 변수에 플래그를 표시한 다음 더 이상의 페이지 요청을 중지합니다.확인해 보시고 어떻게 생각하시는지 알려주세요.
https://medium.com/ @etiennel lowlor/인터뷰가 있는 조명-1cb7e66a502b.
AsyncListUtil을 사용하는 내 솔루션은 웹에서 다음과 같이 말합니다.이 클래스는 단일 스레드를 사용하여 데이터를 로드하므로 디스크와 같은 보조 스토리지에서 데이터를 로드하는 것이 적합하지만 네트워크에서는 로드하지 않습니다. 하지만 데이터를 읽고 잘 작동하기 위해 Odata를 사용하고 있습니다.예에서 데이터 엔티티와 네트워크 방법이 누락되었습니다.저는 샘플 어댑터만 포함합니다.
public class AsyncPlatoAdapter extends RecyclerView.Adapter {
private final AsyncPlatoListUtil mAsyncListUtil;
private final MainActivity mActivity;
private final RecyclerView mRecyclerView;
private final String mFilter;
private final String mOrderby;
private final String mExpand;
public AsyncPlatoAdapter(String filter, String orderby, String expand, RecyclerView recyclerView, MainActivity activity) {
mFilter = filter;
mOrderby = orderby;
mExpand = expand;
mRecyclerView = recyclerView;
mActivity = activity;
mAsyncListUtil = new AsyncPlatoListUtil();
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext()).
inflate(R.layout.plato_cardview, parent, false);
// Create a ViewHolder to find and hold these view references, and
// register OnClick with the view holder:
return new PlatoViewHolderAsync(itemView, this);
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
final Plato item = mAsyncListUtil.getItem(position);
PlatoViewHolderAsync vh = (PlatoViewHolderAsync) holder;
if (item != null) {
Integer imagen_id = item.Imagen_Id.get();
vh.getBinding().setVariable(BR.plato, item);
vh.getBinding().executePendingBindings();
vh.getImage().setVisibility(View.VISIBLE);
vh.getProgress().setVisibility(View.GONE);
String cacheName = null;
String urlString = null;
if (imagen_id != null) {
cacheName = String.format("imagenes/imagen/%d", imagen_id);
urlString = String.format("%s/menusapi/%s", MainActivity.ROOTPATH, cacheName);
}
ImageHelper.downloadBitmap(mActivity, vh.getImage(), vh.getProgress(), urlString, cacheName, position);
} else {
vh.getBinding().setVariable(BR.plato, item);
vh.getBinding().executePendingBindings();
//show progress while loading.
vh.getImage().setVisibility(View.GONE);
vh.getProgress().setVisibility(View.VISIBLE);
}
}
@Override
public int getItemCount() {
return mAsyncListUtil.getItemCount();
}
public class AsyncPlatoListUtil extends AsyncListUtil<Plato> {
/**
* Creates an AsyncListUtil.
*/
public AsyncPlatoListUtil() {
super(Plato.class, //my data class
10, //page size
new DataCallback<Plato>() {
@Override
public int refreshData() {
//get count calling ../$count ... odata endpoint
return countPlatos(mFilter, mOrderby, mExpand, mActivity);
}
@Override
public void fillData(Plato[] data, int startPosition, int itemCount) {
//get items from odata endpoint using $skip and $top
Platos p = loadPlatos(mFilter, mOrderby, mExpand, startPosition, itemCount, mActivity);
for (int i = 0; i < Math.min(itemCount, p.value.size()); i++) {
data[i] = p.value.get(i);
}
}
}, new ViewCallback() {
@Override
public void getItemRangeInto(int[] outRange) {
//i use LinearLayoutManager in the RecyclerView
LinearLayoutManager layoutManager = (LinearLayoutManager) mRecyclerView.getLayoutManager();
outRange[0] = layoutManager.findFirstVisibleItemPosition();
outRange[1] = layoutManager.findLastVisibleItemPosition();
}
@Override
public void onDataRefresh() {
mRecyclerView.getAdapter().notifyDataSetChanged();
}
@Override
public void onItemLoaded(int position) {
mRecyclerView.getAdapter().notifyItemChanged(position);
}
});
mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
onRangeChanged();
}
});
}
}
}
if (layoutManager.findLastCompletelyVisibleItemPosition() ==
recyclerAdapter.getItemCount() - 1) {
//load more items.
}
공정하고 단순합니다.이것은 효과가 있을 거예요.
방법이 있습니다.public void setOnScrollListener (RecyclerView.OnScrollListener listener)
https://developer.android.com/reference/android/support/v7/widget/RecyclerView.html#setOnScrollListener%28android.support.v7.widget.RecyclerView.OnScrollListener%29 에서.그것을 사용합니다.
편집:
재정의onScrollStateChanged
에 있는 방법onScrollListener
그리고 이것을 하라.
boolean loadMore = firstVisibleItem + visibleItemCount >= totalItemCount;
//loading is used to see if its already loading, you have to manually manipulate this boolean variable
if (loadMore && !loading) {
//end of list reached
}
모든 내용이 자세히 설명되어 있는지 확인합니다.A에서 Z까지 RecyclerView를 사용한 페이지화
mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(RecyclerView recyclerView,
int newState) {
super.onScrollStateChanged(recyclerView, newState);
}
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
int visibleItemCount = mLayoutManager.getChildCount();
int totalItemCount = mLayoutManager.getItemCount();
int firstVisibleItemPosition = mLayoutManager.findFirstVisibleItemPosition();
if (!mIsLoading && !mIsLastPage) {
if ((visibleItemCount + firstVisibleItemPosition) >= totalItemCount
&& firstVisibleItemPosition >= 0) {
loadMoreItems();
}
}
}
})
추가 항목 로드():
private void loadMoreItems() {
mAdapter.removeLoading();
//load data here from the server
// in case of success
mAdapter.addData(data);
// if there might be more data
mAdapter.addLoading();
}
내 어댑터에서:
private boolean mIsLoadingFooterAdded = false;
public void addLoading() {
if (!mIsLoadingFooterAdded) {
mIsLoadingFooterAdded = true;
mLineItemList.add(new LineItem());
notifyItemInserted(mLineItemList.size() - 1);
}
}
public void removeLoading() {
if (mIsLoadingFooterAdded) {
mIsLoadingFooterAdded = false;
int position = mLineItemList.size() - 1;
LineItem item = mLineItemList.get(position);
if (item != null) {
mLineItemList.remove(position);
notifyItemRemoved(position);
}
}
}
public void addData(List<YourDataClass> data) {
for (int i = 0; i < data.size(); i++) {
YourDataClass yourDataObject = data.get(i);
mLineItemList.add(new LineItem(yourDataObject));
notifyItemInserted(mLineItemList.size() - 1);
}
}
목록이 너무 작거나 그렇지 않은 경우 이러한 답변은 고려되지 않습니다.
다음은 양방향으로 RecycleViews에서 작동하는 코드입니다.
@Override
public boolean onTouchEvent(MotionEvent motionEvent) {
if (recyclerViewListener == null) {
return super.onTouchEvent(motionEvent);
}
/**
* If the list is too small to scroll.
*/
if (motionEvent.getAction() == MotionEvent.ACTION_UP) {
if (!canScrollVertically(1)) {
recyclerViewListener.reachedBottom();
} else if (!canScrollVertically(-1)) {
recyclerViewListener.reachedTop();
}
}
return super.onTouchEvent(motionEvent);
}
public void setListener(RecyclerViewListener recycleViewListener) {
this.recyclerViewListener = recycleViewListener;
addOnScrollListener(new OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
if (recyclerViewListener == null) {
return;
}
recyclerViewListener.scrolling(dy);
if (!canScrollVertically(1)) {
recyclerViewListener.reachedBottom();
} else if (!canScrollVertically(-1)) {
recyclerViewListener.reachedTop();
}
}
});
}
저는 당신에게 제 근사치를 알려드렸습니다.저한테는 잘 맞습니다.
도움이 되길 바랍니다.
/**
* Created by Daniel Pardo Ligorred on 03/03/2016.
*/
public abstract class BaseScrollListener extends RecyclerView.OnScrollListener {
protected RecyclerView.LayoutManager layoutManager;
public BaseScrollListener(RecyclerView.LayoutManager layoutManager) {
this.layoutManager = layoutManager;
this.init();
}
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
this.onScroll(recyclerView, this.getFirstVisibleItem(), this.layoutManager.getChildCount(), this.layoutManager.getItemCount(), dx, dy);
}
private int getFirstVisibleItem(){
if(this.layoutManager instanceof LinearLayoutManager){
return ((LinearLayoutManager) this.layoutManager).findFirstVisibleItemPosition();
} else if (this.layoutManager instanceof StaggeredGridLayoutManager){
int[] spanPositions = null; //Should be null -> StaggeredGridLayoutManager.findFirstVisibleItemPositions makes the work.
try{
return ((StaggeredGridLayoutManager) this.layoutManager).findFirstVisibleItemPositions(spanPositions)[0];
}catch (Exception ex){
// Do stuff...
}
}
return 0;
}
public abstract void init();
protected abstract void onScroll(RecyclerView recyclerView, int firstVisibleItem, int visibleItemCount, int totalItemCount, int dx, int dy);
}
@전통적인 @tablaziz
대신에 이 논리를 사용하는 게 어때요?
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
int totalItemCount, lastVisibleItemPosition;
if (dy > 0) {
totalItemCount = _layoutManager.getItemCount();
lastVisibleItemPosition = _layoutManager.findLastVisibleItemPosition();
if (!_isLastItem) {
if ((totalItemCount - 1) == lastVisibleItemPosition) {
LogUtil.e("end_of_list");
_isLastItem = true;
}
}
}
}
아래를 시도해 보십시오.
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.RecyclerView.LayoutManager;
/**
* Abstract Endless ScrollListener
*
*/
public abstract class EndlessScrollListener extends
RecyclerView.OnScrollListener {
// The minimum amount of items to have below your current scroll position
// before loading more.
private int visibleThreshold = 10;
// The current offset index of data you have loaded
private int currentPage = 1;
// True if we are still waiting for the last set of data to load.
private boolean loading = true;
// The total number of items in the data set after the last load
private int previousTotal = 0;
private int firstVisibleItem;
private int visibleItemCount;
private int totalItemCount;
private LayoutManager layoutManager;
public EndlessScrollListener(LayoutManager layoutManager) {
validateLayoutManager(layoutManager);
this.layoutManager = layoutManager;
}
public EndlessScrollListener(int visibleThreshold,
LayoutManager layoutManager, int startPage) {
validateLayoutManager(layoutManager);
this.visibleThreshold = visibleThreshold;
this.layoutManager = layoutManager;
this.currentPage = startPage;
}
private void validateLayoutManager(LayoutManager layoutManager)
throws IllegalArgumentException {
if (null == layoutManager
|| !(layoutManager instanceof GridLayoutManager)
|| !(layoutManager instanceof LinearLayoutManager)) {
throw new IllegalArgumentException(
"LayoutManager must be of type GridLayoutManager or LinearLayoutManager.");
}
}
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
visibleItemCount = recyclerView.getChildCount();
totalItemCount = layoutManager.getItemCount();
if (layoutManager instanceof GridLayoutManager) {
firstVisibleItem = ((GridLayoutManager) layoutManager)
.findFirstVisibleItemPosition();
} else if (layoutManager instanceof LinearLayoutManager) {
firstVisibleItem = ((LinearLayoutManager) layoutManager)
.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;
}
}
// Defines the process for actually loading more data based on page
public abstract void onLoadMore(int page);
}
Abdulaziz Noor Answer를 사용하여 LoadMoreRecyclerView를 만들었습니다.
추가 재활용기 보기 로드
public class LoadMoreRecyclerView extends RecyclerView {
private boolean loading = true;
int pastVisiblesItems, visibleItemCount, totalItemCount;
//WrapperLinearLayout is for handling crash in RecyclerView
private WrapperLinearLayout mLayoutManager;
private Context mContext;
private OnLoadMoreListener onLoadMoreListener;
public LoadMoreRecyclerView(Context context) {
super(context);
mContext = context;
init();
}
public LoadMoreRecyclerView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
mContext = context;
init();
}
public LoadMoreRecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
mContext = context;
init();
}
private void init(){
mLayoutManager = new WrapperLinearLayout(mContext,LinearLayoutManager.VERTICAL,false);
this.setLayoutManager(mLayoutManager);
this.setItemAnimator(new DefaultItemAnimator());
this.setHasFixedSize(true);
}
@Override
public void onScrolled(int dx, int dy) {
super.onScrolled(dx, dy);
if(dy > 0) //check for scroll down
{
visibleItemCount = mLayoutManager.getChildCount();
totalItemCount = mLayoutManager.getItemCount();
pastVisiblesItems = mLayoutManager.findFirstVisibleItemPosition();
if (loading)
{
if ( (visibleItemCount + pastVisiblesItems) >= totalItemCount)
{
loading = false;
Log.v("...", "Call Load More !");
if(onLoadMoreListener != null){
onLoadMoreListener.onLoadMore();
}
//Do pagination.. i.e. fetch new data
}
}
}
}
@Override
public void onScrollStateChanged(int state) {
super.onScrollStateChanged(state);
}
public void onLoadMoreCompleted(){
loading = true;
}
public void setMoreLoading(boolean moreLoading){
loading = moreLoading;
}
public void setOnLoadMoreListener(OnLoadMoreListener onLoadMoreListener) {
this.onLoadMoreListener = onLoadMoreListener;
}
}
래퍼 선형 레이아웃
public class WrapperLinearLayout extends LinearLayoutManager
{
public WrapperLinearLayout(Context context, int orientation, boolean reverseLayout) {
super(context, orientation, reverseLayout);
}
@Override
public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
try {
super.onLayoutChildren(recycler, state);
} catch (IndexOutOfBoundsException e) {
Log.e("probe", "meet a IOOBE in RecyclerView");
}
}
}
//xml로 추가합니다.
<your.package.LoadMoreRecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent">
</your.package.LoadMoreRecyclerView>
작성 시 또는 작성 시
mLoadMoreRecyclerView = (LoadMoreRecyclerView) view.findViewById(R.id.recycler_view);
mLoadMoreRecyclerView.setOnLoadMoreListener(new OnLoadMoreListener() {
@Override
public void onLoadMore() {
callYourService(StartIndex);
}
});
서비스 요청
private void callYourService(){
//callyour Service and get response in any List
List<AnyModelClass> newDataFromServer = getDataFromServerService();
//Enable Load More
mLoadMoreRecyclerView.onLoadMoreCompleted();
if(newDataFromServer != null && newDataFromServer.size() > 0){
StartIndex += newDataFromServer.size();
if (newDataFromServer.size() < Integer.valueOf(MAX_ROWS)) {
//StopLoading..
mLoadMoreRecyclerView.setMoreLoading(false);
}
}
else{
mLoadMoreRecyclerView.setMoreLoading(false);
mAdapter.notifyDataSetChanged();
}
}
언급URL : https://stackoverflow.com/questions/26543131/how-to-implement-endless-list-with-recyclerview
'programing' 카테고리의 다른 글
각도 2: 양식이 연결되지 않아 양식 제출이 취소되었습니다. (0) | 2023.07.25 |
---|---|
애니메이션을 중지하는 방법(취소()가 작동하지 않음) (0) | 2023.07.25 |
MariaDB 주 시작 날짜 & 주 번호 1 ~ 52 (0) | 2023.07.25 |
자바스크립트에서 비동기 호출을 동기 함수에서 기다리는 방법은 무엇입니까? (0) | 2023.07.25 |
nodejs mariadb 커넥터에 자동 재플래시 옵션을 추가하지 않는 방법은 무엇입니까? (0) | 2023.07.25 |