在我的RecyclerView
我有一些项目,用户可以滚动并看到,现在我想保存这个位置并滚动后回来,这下面的代码总是返回0,我不能保存
recyclerMarketLists.getViewTreeObserver().addOnScrollChangedListener(new ViewTreeObserver.OnScrollChangedListener() {
@Override
public void onScrollChanged() {
recyclerViewCurrentScrolledPosition = recyclerMarketLists.getScrollY();
Log.e("Y: ", recyclerViewCurrentSceolledPosition + "");
}
});
Logcat:
07-07 18:28:30.919 2124-2124/com.sample.presentationproject E/Y:: 0
答案 0 :(得分:29)
您正在尝试获取有关错误对象的信息。它不是RecyclerView
也不是Adapter
责任,而是RecyclerView的LayoutManager。
我会建议添加ViewTreeObserver.OnScrollChangedListener()
而不是通用RecyclerView.OnScrollListener
,而是使用onScrollStateChanged(RecyclerView recyclerView, int newState)
回调,它会为您提供newState
,您应该使用SCROLL_STATE_IDLE
获取它的位置。含义:
yourRecyclerView.getLayoutManager().findFirstVisibleItemPosition();
正如Rik van Velzen指出的那样,你可能需要施展你的
LayoutManager
到LinearLayoutManager
或GridLayoutManager
(您必须转换为正在使用的正确类型)才能访问这些内容findVisibleXXXX()
方法。
关于所说的回调方法。希望我能为你做到这一点,你可以在这里找到关于课程的文档:
答案 1 :(得分:10)
感谢解决方案 Joaquim Ley 。这有助于在不使用任何库的情况下创建recyclerView
horizontal
寻呼机。
初始recyclerView
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_vocabulary_list);
// Set up the recyclerView with the sections adapter.
mRecyclerView = findViewById(R.id.list);
mRecyclerView.setItemAnimator(new DefaultItemAnimator());
mRecyclerView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false));
mRecyclerView.setAdapter(new VocabularyListAdapter<>(vocabularyList));
mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
if (newState == RecyclerView.SCROLL_STATE_IDLE){
int position = getCurrentItem();
onPageChanged(position);
}
}
});
PagerSnapHelper snapHelper = new PagerSnapHelper();
snapHelper.attachToRecyclerView(mRecyclerView);
}
public boolean hasPreview() {
return getCurrentItem() > 0;
}
public boolean hasNext() {
return mRecyclerView.getAdapter() != null &&
getCurrentItem() < (mRecyclerView.getAdapter().getItemCount()- 1);
}
public void preview() {
int position = getCurrentItem();
if (position > 0)
setCurrentItem(position -1, true);
}
public void next() {
RecyclerView.Adapter adapter = mRecyclerView.getAdapter();
if (adapter == null)
return;
int position = getCurrentItem();
int count = adapter.getItemCount();
if (position < (count -1))
setCurrentItem(position + 1, true);
}
private int getCurrentItem(){
return ((LinearLayoutManager)mRecyclerView.getLayoutManager())
.findFirstVisibleItemPosition();
}
private void setCurrentItem(int position, boolean smooth){
if (smooth)
mRecyclerView.smoothScrollToPosition(position);
else
mRecyclerView.scrollToPosition(position);
}
答案 2 :(得分:2)
我对MainActivity进行了7次更改,并获得了像素完美的结果。从其他Activity(例如DetailActivity)返回状态时,我的recyclerview总是会记住其先前状态。
第1步:像这样初始化layoutManager:
// Initialize the layout manager
moviePosterLayoutManager = (moviePosterRecyclerView.getLayoutManager() == null) ?
new GridLayoutManager(this, numberOfColumns) : moviePosterRecyclerView.getLayoutManager();
// create a new layoutManager // reuse the existing layoutManager
步骤2: 在MainActivity类中,创建一个STATIC变量,以在活动之间进行转换时保持布局管理器的状态:
private static Parcelable layoutManagerState;
步骤3: 还要在MainActivity()内部创建此常量:
公共静态最终字符串KEY_LAYOUT_MANAGER_STATE =“ layoutManagerState”;
第4步: 在MainActivity的onCreate方法中,执行以下测试(即
protected void onCreate(@Nullable final Bundle savedInstanceState) {....
if (layoutManagerState != null) {
//moviePosterLayoutManager
moviePosterLayoutManager.onRestoreInstanceState(layoutManagerState);
moviePosterRecyclerView.setLayoutManager(moviePosterLayoutManager);
} else {
moviePosterRecyclerView.setLayoutManager(moviePosterLayoutManager);
moviePosterRecyclerView.scrollToPosition(moviePosition);
// the default position
}
第5步: 在您的onSaveInstanceState方法中,请确保 将您的layoutManagerState保存为可打包文件,如下所示:
受保护的void onSaveInstanceState(Bundle outState){
layoutManagerState = moviePosterLayoutManager.onSaveInstanceState();
// Save currently selected layout manager.
outState.putParcelable(KEY_LAYOUT_MANAGER_STATE,layoutManagerState);
}
步骤6: 将类似的代码放在MainActivity的onResume()方法中:
protected void onResume() {
super.onResume();
if (layoutManagerState != null) {
moviePosterLayoutManager.onRestoreInstanceState(layoutManagerState);
}
}
步骤7: 请记住,所有这些代码都放置在我的MainActivity.java文件中。 要记住,layoutManager负责维护滚动条的滚动位置。 回收者视图。因此,保存layoutManager的状态至关重要。该代码可以 模块化并放置在自定义的recyclerview中,但是我发现这对我来说更简单 实施。
答案 3 :(得分:2)
这是Kotlin中的扩展功能:
private fun RecyclerView.getCurrentPosition() : Int {
return (this.layoutManager as LinearLayoutManager?)!!.findFirstVisibleItemPosition()
}
您可以在RecyclerView
上调用此功能来使用它:
val position = yourRecyclerView.getCurrentPosition()
答案 4 :(得分:2)
在 Kotlin 中试试这个:
myRecyclerView.addOnScrollListener(object: RecyclerView.OnScrollListener() {
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
super.onScrolled(recyclerView, dx, dy)
val offset: Int = myRecyclerView.computeHorizontalScrollOffset()
if (offset % myRecyclerView.width == 0) {
val position: Int = offset / myRecyclerView.width
Log.e("Current position is", position.toString())
}
}
})
答案 5 :(得分:1)
没有一个解决方案有效,我通过使用布局管理器实现了这一点。 这是recyclerview的扩展函数
fun RecyclerView.addScrollListener(onScroll: (position: Int) -> Unit) {
var lastPosition = 0
addOnScrollListener(object : RecyclerView.OnScrollListener() {
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
super.onScrolled(recyclerView, dx, dy)
if (layoutManager is LinearLayoutManager) {
val currentVisibleItemPosition =
(layoutManager as LinearLayoutManager).findFirstVisibleItemPosition()
if (lastPosition != currentVisibleItemPosition && currentVisibleItemPosition != RecyclerView.NO_POSITION) {
onScroll.invoke(currentVisibleItemPosition)
lastPosition = currentVisibleItemPosition
}
}
}
})
}
您可以在 recyclerview 上像这样使用它。
campusFeedRv.addScrollListener { position: Int ->
Log.d(TAG, "Current Position: $position ")
}
答案 6 :(得分:0)
对于类似的要求以及需要在滚动状态更改时执行的某些操作,我使用自定义滚动侦听器进行了此操作:
class OnScrollListener(private val action: () -> Unit) : RecyclerView.OnScrollListener() {
private var actionExecuted: Boolean = false
private var oldScrollPosition: Int = 0
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
super.onScrollStateChanged(recyclerView, newState)
when (newState) {
RecyclerView.SCROLL_STATE_DRAGGING -> actionExecuted = false
RecyclerView.SCROLL_STATE_SETTLING -> actionExecuted = false
RecyclerView.SCROLL_STATE_IDLE -> {
val scrolledPosition =
(recyclerView.layoutManager as? LinearLayoutManager)?.findFirstVisibleItemPosition() ?: return
if (scrolledPosition != RecyclerView.NO_POSITION && scrolledPosition != oldScrollPosition && !actionExecuted) {
action.invoke()
actionExecuted = true
oldScrollPosition = scrolledPosition
}
}
}
}
}
这是由于RecyclerView onScroll先前存在的错误,该错误恰好触发2-3次甚至更多次回调。而且,如果要执行某些操作,则最终将执行多次。
答案 7 :(得分:0)
learnRecycleView
.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerView,
int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
int offset=learnRecycleView.computeHorizontalScrollOffset();
if (offset % learnRecycleView.getWidth() == 0) {
int position = offset / learnRecycleView.getWidth();
System.out.println("Current position is"+position);
}
}
});
答案 8 :(得分:0)
就我而言,我需要在 Activity 中查看当前位置,因此我创建了一个回调方法并使用以下方法。
在 Adapter 类中添加此代码以获取视图的当前位置。
在 onBindViewHolder 方法中添加它。
holder.imgProductParts.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {
@Override
public void onViewAttachedToWindow(View v) {
onPositionChangeListener.onItemChanged(position);
}
@Override
public void onViewDetachedFromWindow(View v) { }
});