我在NestedScrollView中有RecyclerView
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="@+id/recycler"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</android.support.v4.widget.NestedScrollView>
我在大项目中遇到这个问题,为了找到这个问题的解决方案,我创建了没有其他视图的新项目。
这是MainActivity的完整代码
class MainActivity : AppCompatActivity() {
var mItems = mutableListOf<String>()
var mAdapter = MyAdapter(mItems)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
recycler.layoutManager = LinearLayoutManager(this)
recycler.adapter = mAdapter
delayedLoadDataIfPossible(100)
recycler.viewTreeObserver.addOnScrollChangedListener {
delayedLoadDataIfPossible(100)
}
}
private fun delayedLoadDataIfPossible(delay: Long) {
Observable.timer(delay, TimeUnit.MILLISECONDS)
.observeOn(AndroidSchedulers.mainThread())
.subscribe {
var scrollingReachedEnd = isScrollingReachedEnd()
if (scrollingReachedEnd) {
loadData()
}
}
}
private fun isScrollingReachedEnd(): Boolean {
val layoutManager = LinearLayoutManager::class.java.cast(recycler.layoutManager)
val totalItemCount = layoutManager.itemCount
val lastVisible = layoutManager.findLastVisibleItemPosition()
return lastVisible + 5 >= totalItemCount
}
private fun loadData() {
Observable.timer(5, TimeUnit.SECONDS)
.observeOn(AndroidSchedulers.mainThread())
.doOnSubscribe { progress.visibility = View.VISIBLE }
.doFinally { progress.visibility = View.GONE }
.subscribe {
for (i in 1..10) {
mItems.add(i.toString())
}
mAdapter.notifyDataSetChanged()
delayedLoadDataIfPossible(100)
}
}
}
我使用isScrollingReachedEnd方法来识别滚动到达列表的末尾。如果最后有少于5个可见项目,我正在尝试加载新数据。
loadData模拟加载数据。它添加10个项目列表,并通知适配器有关更改。
delayedLoadDataIfPossible方法应该在一些延迟后工作,因为findLastVisibleItemPosition在将项添加到列表之前返回值。结果它返回错误的值。例如,在添加前10个项目后为-1。
我的问题:当RecestedView里面的NestedScrollView findLastVisibleItemPosition返回错误的值而且数据加载甚至没有足够的项目也无法停止。当RecyclerView不在NestedScrollView中时,没有这样的问题。
我的问题:当它在NestedScrollView中时,如何从RecyclerView获取最后一个可见项目位置?
你可以尝试这种方法:
这是我为NestedScrollingView创建ScrollingListener的代码:
@Override
public void onScrollChange(NestedScrollView v, int scrollX, int scrollY, int oldScrollX, int oldScrollY) {
int lastVisibleItemPosition = 0;
int totalItemCount = layoutManager.getItemCount();
if(v.getChildAt(v.getChildCount() - 1) != null) {
if (scrollY >= (v.getChildAt(v.getChildCount()-1).getMeasuredHeight() - v.getMeasuredHeight())
&& scrollY > oldScrollY) {
if (layoutManager instanceof LinearLayoutManager) {
lastVisibleItemPosition = ((LinearLayoutManager) layoutManager).findLastVisibleItemPosition();
}
if (totalItemCount < previousTotalItemCount) {
this.currentPage = this.startingPageIndex;
this.previousTotalItemCount = totalItemCount;
if (totalItemCount == 0) {
this.loading = true;
}
}
if (loading && (totalItemCount > previousTotalItemCount)) {
loading = false;
previousTotalItemCount = totalItemCount;
}
if (!loading && (lastVisibleItemPosition + visibleThreshold) > totalItemCount) {
currentPage++;
onLoadMore();
loading = true;
}
}
}
}
祝好运!
如果你的RecyclerView
在NestedScrollView
里面,你需要添加recyclerView.setNestedScrollingEnabled(false)
。
另外一个注意事项(与您的问题无关,您应该保留对这些RxJava订阅的引用并将它们放在Fragment / Adtivity的onStop上,因为它们可能导致内存泄漏问题。