Saya memiliki kode ini untuk RecyclerView.
recyclerView = (RecyclerView)rootview.findViewById(R.id.fabric_recyclerView);
recyclerView.setLayoutManager(layoutManager);
recyclerView.addItemDecoration(new RV_Item_Spacing(5));
FabricAdapter fabricAdapter=new FabricAdapter(ViewAdsCollection.getFabricAdsDetailsAsArray());
recyclerView.setAdapter(fabricAdapter);
Saya perlu tahu kapan RecyclerView mencapai posisi paling bawah saat menggulir. Apa itu mungkin ? Jika ya, bagaimana caranya?
android
scroll
android-recyclerview
Adrian
sumber
sumber
Jawaban:
ada juga cara sederhana untuk melakukannya
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrollStateChanged(RecyclerView recyclerView, int newState) { super.onScrollStateChanged(recyclerView, newState); if (!recyclerView.canScrollVertically(1)) { Toast.makeText(YourActivity.this, "Last", Toast.LENGTH_LONG).show(); } } });
arah bilangan bulat: -1 untuk atas, 1 untuk bawah, 0 akan selalu mengembalikan false.
sumber
if (!recyclerView.canScrollVertically(1) && !mHasReachedBottomOnce) { mHasReachedBottomOnce = true Toast.makeText(YourActivity.this, "Last", Toast.LENGTH_LONG).show();}
newState == RecyclerView.SCROLL_STATE_IDLE
ke dalamif
pernyataan itu akan berhasil.Gunakan kode ini untuk menghindari panggilan berulang
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrollStateChanged(RecyclerView recyclerView, int newState) { super.onScrollStateChanged(recyclerView, newState); if (!recyclerView.canScrollVertically(1) && newState==RecyclerView.SCROLL_STATE_IDLE) { Log.d("-----","end"); } } });
sumber
Cukup terapkan addOnScrollListener () di recyclerview Anda. Kemudian di dalam pendengar gulir, terapkan kode di bawah ini.
RecyclerView.OnScrollListener mScrollListener = new RecyclerView.OnScrollListener() { @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { if (mIsLoading) return; int visibleItemCount = mLayoutManager.getChildCount(); int totalItemCount = mLayoutManager.getItemCount(); int pastVisibleItems = mLayoutManager.findFirstVisibleItemPosition(); if (pastVisibleItems + visibleItemCount >= totalItemCount) { //End of list } } };
sumber
'findFirstVisibleItemPosition'
padaandroid.support.v7.widget.RecyclerView
(recyclerView.layoutManager as LinearLayoutManager).findFirstVisibleItemPosition()
. Pekerjaan ini.Jawabannya ada di Kotlin, ini akan berfungsi di Java. IntelliJ harus mengubahnya untuk Anda jika Anda menyalin dan menempel.
recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener(){ override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) { // 3 lines below are not needed. Log.d("TAG","Last visible item is: ${gridLayoutManager.findLastVisibleItemPosition()}") Log.d("TAG","Item count is: ${gridLayoutManager.itemCount}") Log.d("TAG","end? : ${gridLayoutManager.findLastVisibleItemPosition() == gridLayoutManager.itemCount-1}") if(gridLayoutManager.findLastVisibleItemPosition() == gridLayoutManager.itemCount-1){ // We have reached the end of the recycler view. } super.onScrolled(recyclerView, dx, dy) } })
Ini juga akan berfungsi
LinearLayoutManager
karena memiliki metode yang sama yang digunakan di atas. YaitufindLastVisibleItemPosition()
dangetItemCount()
(itemCount
di Kotlin).sumber
Saya tidak mendapatkan solusi sempurna dengan jawaban di atas karena itu memicu dua kali bahkan pada
onScrolled
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) { super.onScrolled(recyclerView, dx, dy) if( !recyclerView.canScrollVertically(RecyclerView.FOCUS_DOWN)) context?.toast("Scroll end reached") }
sumber
recyclerView.canScrollVertically(direction)
arahnya hanyalah bilangan bulat + vs - jadi bisa 4 jika di bawah atau -12 jika di atas.Coba ini
Saya telah menggunakan jawaban di atas, itu selalu berjalan ketika Anda akan pergi di ujung tampilan pendaur ulang,
Jika Anda ingin memeriksa hanya satu kali apakah di bawah atau tidak? Contoh: - Jika saya memiliki daftar 10 item setiap kali saya pergi ke bawah itu akan menampilkan saya dan lagi jika saya menggulir dari atas ke bawah itu tidak akan mencetak lagi, dan jika Anda menambahkan lebih banyak daftar dan Anda pergi ke sana itu akan ditampilkan lagi.
Catatan: - Gunakan metode ini saat Anda menangani offset dalam menekan API
Buat kelas bernama EndlessRecyclerViewScrollListener
import android.support.v7.widget.GridLayoutManager; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.StaggeredGridLayoutManager; 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() { // 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); }
gunakan kelas ini seperti ini
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getActivity()); recyclerView.setLayoutManager(linearLayoutManager); recyclerView.addOnScrollListener(new EndlessRecyclerViewScrollListener( linearLayoutManager) { @Override public void onLoadMore(int page, int totalItemsCount, RecyclerView view) { Toast.makeText(getActivity(),"LAst",Toast.LENGTH_LONG).show(); } });
Ini berjalan sempurna di akhir saya, beri tahu saya jika Anda mendapatkan masalah apa pun
sumber
Ada implementasi saya, itu sangat berguna untuk
StaggeredGridLayout
.Penggunaan:
private EndlessScrollListener scrollListener = new EndlessScrollListener(new EndlessScrollListener.RefreshList() { @Override public void onRefresh(int pageNumber) { //end of the list } }); rvMain.addOnScrollListener(scrollListener);
Implementasi pendengar:
class EndlessScrollListener extends RecyclerView.OnScrollListener { private boolean isLoading; private boolean hasMorePages; private int pageNumber = 0; private RefreshList refreshList; private boolean isRefreshing; private int pastVisibleItems; EndlessScrollListener(RefreshList refreshList) { this.isLoading = false; this.hasMorePages = true; this.refreshList = refreshList; } @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { super.onScrolled(recyclerView, dx, dy); StaggeredGridLayoutManager manager = (StaggeredGridLayoutManager) recyclerView.getLayoutManager(); int visibleItemCount = manager.getChildCount(); int totalItemCount = manager.getItemCount(); int[] firstVisibleItems = manager.findFirstVisibleItemPositions(null); if (firstVisibleItems != null && firstVisibleItems.length > 0) { pastVisibleItems = firstVisibleItems[0]; } if (visibleItemCount + pastVisibleItems >= totalItemCount && !isLoading) { isLoading = true; if (hasMorePages && !isRefreshing) { isRefreshing = true; new Handler().postDelayed(new Runnable() { @Override public void run() { refreshList.onRefresh(pageNumber); } }, 200); } } else { isLoading = false; } } public void noMorePages() { this.hasMorePages = false; } void notifyMorePages() { isRefreshing = false; pageNumber = pageNumber + 1; } interface RefreshList { void onRefresh(int pageNumber); } }
sumber
Saya juga mencari pertanyaan ini tetapi saya tidak menemukan jawaban yang memuaskan saya, jadi saya membuat realisasi recyclerView sendiri.
solusi lain kurang tepat dibandingkan solusi saya. misalnya: jika item terakhir cukup besar (banyak teks) maka callback solusi lain akan datang jauh lebih awal, kemudian recyclerView benar-benar mencapai paling bawah.
solusi saya memperbaiki masalah ini.
class CustomRecyclerView: RecyclerView{ abstract class TopAndBottomListener{ open fun onBottomNow(onBottomNow:Boolean){} open fun onTopNow(onTopNow:Boolean){} } constructor(c:Context):this(c, null) constructor(c:Context, attr:AttributeSet?):super(c, attr, 0) constructor(c:Context, attr:AttributeSet?, defStyle:Int):super(c, attr, defStyle) private var linearLayoutManager:LinearLayoutManager? = null private var topAndBottomListener:TopAndBottomListener? = null private var onBottomNow = false private var onTopNow = false private var onBottomTopScrollListener:RecyclerView.OnScrollListener? = null fun setTopAndBottomListener(l:TopAndBottomListener?){ if (l != null){ checkLayoutManager() onBottomTopScrollListener = createBottomAndTopScrollListener() addOnScrollListener(onBottomTopScrollListener) topAndBottomListener = l } else { removeOnScrollListener(onBottomTopScrollListener) topAndBottomListener = null } } private fun createBottomAndTopScrollListener() = object :RecyclerView.OnScrollListener(){ override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) { checkOnTop() checkOnBottom() } } private fun checkOnTop(){ val firstVisible = linearLayoutManager!!.findFirstCompletelyVisibleItemPosition() if(firstVisible == 0 || firstVisible == -1 && !canScrollToTop()){ if (!onTopNow) { onTopNow = true topAndBottomListener?.onTopNow(true) } } else if (onTopNow){ onTopNow = false topAndBottomListener?.onTopNow(false) } } private fun checkOnBottom(){ var lastVisible = linearLayoutManager!!.findLastCompletelyVisibleItemPosition() val size = linearLayoutManager!!.itemCount - 1 if(lastVisible == size || lastVisible == -1 && !canScrollToBottom()){ if (!onBottomNow){ onBottomNow = true topAndBottomListener?.onBottomNow(true) } } else if(onBottomNow){ onBottomNow = false topAndBottomListener?.onBottomNow(false) } } private fun checkLayoutManager(){ if (layoutManager is LinearLayoutManager) linearLayoutManager = layoutManager as LinearLayoutManager else throw Exception("for using this listener, please set LinearLayoutManager") } private fun canScrollToTop():Boolean = canScrollVertically(-1) private fun canScrollToBottom():Boolean = canScrollVertically(1) }
lalu di aktivitas / fragmen Anda:
override fun onCreate() { customRecyclerView.layoutManager = LinearLayoutManager(context) } override fun onResume() { super.onResume() customRecyclerView.setTopAndBottomListener(this) } override fun onStop() { super.onStop() customRecyclerView.setTopAndBottomListener(null) }
berharap itu akan membantu seseorang ;-)
sumber
Setelah tidak puas dengan sebagian besar jawaban lain di utas ini, saya menemukan sesuatu yang menurut saya lebih baik dan tidak ada di mana pun di sini.
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { if (!recyclerView.canScrollVertically(1) && dy > 0) { //scrolled to bottom }else if (!recyclerView.canScrollVertically(-1) && dy < 0) { //scrolled to bottom } } });
Ini sederhana dan akan memukul tepat satu kali dalam semua kondisi ketika Anda menggulir ke atas atau bawah.
sumber
Ini solusi saya:
val onScrollListener = object : RecyclerView.OnScrollListener() { override fun onScrolled(recyclerView: RecyclerView?, dx: Int, dy: Int) { directionDown = dy > 0 } override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) { if (recyclerView.canScrollVertically(1).not() && state != State.UPDATING && newState == RecyclerView.SCROLL_STATE_IDLE && directionDown) { state = State.UPDATING // TODO do what you want when you reach bottom, direction // is down and flag for non-duplicate execution } } }
sumber
state
enum itu?Kita bisa menggunakan Interface untuk mendapatkan posisi tersebut
Antarmuka: Buat Antarmuka untuk pendengar
public interface OnTopReachListener { void onTopReached(int position);}
Aktivitas :
mediaRecycleAdapter = new MediaRecycleAdapter(Class.this, taskList); recycle.setAdapter(mediaRecycleAdapter); mediaRecycleAdapter.setOnSchrollPostionListener(new OnTopReachListener() { @Override public void onTopReached(int position) { Log.i("Position","onTopReached "+position); } });
Adaptor:
public void setOnSchrollPostionListener(OnTopReachListener topReachListener) { this.topReachListener = topReachListener;}@Override public void onBindViewHolder(MyViewHolder holder, int position) {if(position == 0) { topReachListener.onTopReached(position);}}
sumber