在RecyclerView中滚动CardView项目的位置



在用这种方法保存和检索最后一个查看项目的位置近一天之后,我终于找到了一个能提供所需输出的解决方案。在返回RecyclerView的路上打开我的一件物品后,我的应用程序滚动到该物品,但有一个小错误。。。我使用两个方法onPause((和onResume((,这是我的实现:

@Override
protected void onPause() {
super.onPause();
lastFirstVisiblePosition = ((LinearLayoutManager)
mRecyclerView.getLayoutManager()).findLastVisibleItemPosition();
Log.d("position", String.valueOf(lastFirstVisiblePosition));
}
@Override
protected void onResume() {
super.onResume();
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
mRecyclerView.scrollToPosition(lastFirstVisiblePosition);
}
}, 200);
}
  1. 由于我是一个初学者,我不确定在这个目的中使用处理程序是否是一个明智的想法
  2. 因为我的卡片/物品大小不同,只要物品不在某个位置,我就无法返回到上次查看的物品的位置,也就是说,只要下面的物品不在屏幕上。。。有没有办法考虑我卡片的尺寸和根据设置的位置

还有一件事需要补充,我尝试过onSaveInstanceState((和onRestoreInstanceState(((方法,但没有成功。。。实现之一:

@Override
protected void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState);
lastFirstVisiblePosition = ((LinearLayoutManager)
mRecyclerView.getLayoutManager()).findLastVisibleItemPosition();
outState.putString("position", String.valueOf(lastFirstVisiblePosition));
Log.d("currentPos", String.valueOf(outState));
}
@Override
protected void onRestoreInstanceState(@NonNull Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
String position = savedInstanceState.getString("position");
mRecyclerView.scrollToPosition(Integer.parseInt(position));
}

通过这种方式,我能够获得当前位置,但无法恢复…

创建变量private static int displayedposition = 0;

现在是您的RecyclerView在活动中的位置。

myRecyclerView.setOnScrollListener(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);
LinearLayoutManager llm = (LinearLayoutManager) myRecyclerView.getLayoutManager();
displayedposition = llm.findLastVisibleItemPosition();
}
});

修改onPause()方法以添加这些行。。

LinearLayoutManager llm = (LinearLayoutManager) mRecyclerView.getLayoutManager();
llm.scrollToPositionWithOffset(displayedposition , youList.size());

如果findLastVisibleItemPosition()似乎不起作用,请尝试findLastCompletelyVisibleItemPosition()。。

它会起作用的。。尝试并还原。

我在此展示我的代码,这可能会对您有所帮助。。Play Store上的我的应用程序链接可参考..

MainActivity.java

package com.amitabh.dhamma_jaagran;
import android.content.Intent;
import android.os.Bundle;
import android.support.design.widget.AppBarLayout;
import android.support.design.widget.CollapsingToolbarLayout;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
import com.bumptech.glide.Glide;

public class MainActivity extends AppCompatActivity  {
private RecyclerView recyclerView;
private AlbumsAdapter adapter;
private AlbumsAdapter.AlbumsAdapterListener listener;
private List<Album> albumList;
private long backPressedTime = 0;    // used by onBackPressed()  
private static TextView footerText;
String currentVersion;
View parentLayout;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
initCollapsingToolbar();
footerText = findViewById(R.id.activity_main_footer);
parentLayout = findViewById(android.R.id.content);
recyclerView = findViewById(R.id.recycler_view);
//  recyclerView.setHasFixedSize(true);
albumList = new ArrayList<>();
adapter = new AlbumsAdapter(this, albumList, listener);
RecyclerView.LayoutManager mLayoutManager = new GridLayoutManager(this, 2);
((GridLayoutManager) mLayoutManager).setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
@Override
public int getSpanSize(int position) {
return (position % 15 == 0 ? 2 : 1);
}
});

recyclerView.setLayoutManager(mLayoutManager);
recyclerView.setBackgroundColor(getResources().getColor(R.color.white));
//   recyclerView.setBackgroundResource(R.drawable.white_background);
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.setAdapter(adapter);
// row click listener
recyclerView.addOnItemTouchListener(new RecyclerTouchListener(getApplicationContext(), recyclerView, new RecyclerTouchListener.ClickListener() {
@Override
public void onClick(View view, int position) {
Album album = adapter.getAlbumList().get(position);
String text = album.getName();
//  Toast.makeText(getApplicationContext(), text + " is selected", Toast.LENGTH_SHORT).show();
if (text == "तेरापंथ प्रबोध") {
view.getContext().startActivity(new Intent(view.getContext(), TerapanthPrabodhTabLayoutViewPager.class));
}
if (text == "संवत्सरी प्रतिक्रमण") {
view.getContext().startActivity(new Intent(view.getContext(), MangalStuti.class));
}
}
@Override
public void onLongClick(View view, int position) {
}
}));
prepareAlbums();
try {
Glide.with(this).load(R.drawable.cover2).into((ImageView) findViewById(R.id.backdrop));
} catch (Exception e) {
e.printStackTrace();
}           
}
/**
* Initializing collapsing toolbar
* Will show and hide the toolbar title on scroll
*/
private void initCollapsingToolbar() {
final CollapsingToolbarLayout collapsingToolbar =
findViewById(R.id.collapsing_toolbar);
collapsingToolbar.setTitle(" ");
AppBarLayout appBarLayout = findViewById(R.id.appbar);
appBarLayout.setExpanded(true);
// hiding & showing the title when toolbar expanded & collapsed
appBarLayout.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() {
boolean isShow = false;
int scrollRange = -1;
@Override
public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {
if (scrollRange == -1) {
scrollRange = appBarLayout.getTotalScrollRange();
}
if (scrollRange + verticalOffset == 0) {
collapsingToolbar.setTitle(getString(R.string.app_name));
isShow = true;
} else if (isShow) {
collapsingToolbar.setTitle(" ");
isShow = false;
}
}
});
}
/**
* Adding few albums for testing
*/
private void prepareAlbums() {
int[] covers = new int[]{
R.drawable.album000,
R.drawable.album01,
};
Album a = new Album("तेरापंथ प्रबोध", "Terapanth Prabodh", covers[0]);
albumList.add(a);
a = new Album("मंगल स्तुति", "Mangal Stuti", covers[1]);
albumList.add(a);
adapter.notifyDataSetChanged();
}
}

相册.java

package com.amitabh.dhamma_jaagran;
public class Album
{
private String name;
private String numOfSongs;
private int thumbnail;
public Album() {}
public Album(String name, String numOfSongs, int thumbnail)
{
this.name = name;
this.numOfSongs = numOfSongs;
this.thumbnail = thumbnail;
}
public String getName()
{
return this.name;
}
public String getNumOfSongs()
{
return this.numOfSongs;
}
public int getThumbnail()
{
return this.thumbnail;
}
public void setName(String paramString)
{
this.name = name;
}
public void setNumOfSongs(String paramString)
{
this.numOfSongs = numOfSongs;
}
public void setThumbnail(int paramInt)
{
this.thumbnail = thumbnail;
}
}

相册适配器.java

package com.amitabh.dhamma_jaagran;
import android.content.Context;
import android.support.annotation.NonNull;
import android.support.v7.widget.CardView;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.ImageView;
import android.widget.TextView;
import com.bumptech.glide.Glide;
import java.util.ArrayList;
import java.util.List;

public class AlbumsAdapter extends RecyclerView.Adapter<AlbumsAdapter.MyViewHolder> {
private Context mContext;
private List<Album> albumList;
private AlbumsAdapterListener listener;
private int lastPosition = -1;
public class MyViewHolder extends RecyclerView.ViewHolder {
public TextView title, count;
public ImageView thumbnail, overflow;
public CardView cardView;
public MyViewHolder(View view) {
super(view);
title =  view.findViewById(R.id.title);
count = view.findViewById(R.id.count);
thumbnail =  view.findViewById(R.id.thumbnail);
overflow =  view.findViewById(R.id.overflow);
cardView =  view.findViewById(R.id.card_view);
}
}

public AlbumsAdapter(Context mContext, List<Album> albumList, AlbumsAdapterListener 
listener) {
this.mContext = mContext;
this.albumList = albumList;
this.listener = listener;
}
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.album_card, parent, false);
return new MyViewHolder(itemView);
}
@Override
public void onViewDetachedFromWindow(@NonNull AlbumsAdapter.MyViewHolder holder) {
super.onViewDetachedFromWindow(holder);
holder.itemView.clearAnimation();
}
@Override
public void onBindViewHolder(final MyViewHolder holder, final int position) {
Album album = albumList.get(position);
holder.title.setText(album.getName());
holder.count.setText(album.getNumOfSongs());
/*loading album cover using Glide library*/
Glide.with(mContext).load(album.getThumbnail()).into(holder.thumbnail);
Animation animation = AnimationUtils.loadAnimation(mContext,
(position > lastPosition) ? R.anim.up_from_bottom
: R.anim.down_from_top);
holder.itemView.startAnimation(animation);
lastPosition = position;
}

@Override
public int getItemCount() {
return albumList.size();
}

public interface AlbumsAdapterListener {
void onAddToFavoriteSelected(int position);
void onPlayNextSelected(int position);
void onCardSelected(int position, ImageView thumbnail);
}
public List<Album> getAlbumList(){
return albumList;
}
public void filter(ArrayList<Album> newList)
{
albumList=new ArrayList<>();
albumList.addAll(newList);
notifyDataSetChanged();
}
}

为了简单起见,我没有使用任何要保存或scollToPositon的实例。。但当用户返回到MainActivity时,它会滚动到以前的位置。。

我想这个答案和你试过的差不多。。

我在mainActivity中创建了RecyclerView,并对其进行了初始化。然后,我创建了一个ViewHolder类,该类为我的项目扩展了RecycerView,并为CardView创建了xml文件。。。

  1. 由于我是初学者,我不确定在这个目的中使用处理程序是否明智

处理程序确实不是最聪明的方法,因为200毫秒可能不足以加载RecyclerView的全部数据,但您需要使用处理程序的原因是,您不知道RecyclerView何时加载了数据,以便在知道之后滚动到某个位置。

对于您的处理程序,有一种更好的方法,但它的功能和您的相同,因为它仍然存在200毫秒的问题。

mRecyclerView.postDelayed(new Runnable() {
@Override
public void run() {
mRecyclerView.scrollToPosition(lastFirstVisiblePosition);
mRecyclerView.removeCallbacks(this);
}
}, 200);

它之所以更好,是因为处理程序耦合到您的RecyclerView

但是,我建议使用的解决方案(而不是使用Hanlder(是向LinearLayoutManager添加一个侦听器,该侦听器是在适配器填充RecyclerView的列表时触发的,通常是在mAdapter.notifyDataSetChanged()结束时。要做到这一点:

第一个

创建一个自定义LinearLayoutManager并添加一个侦听器接口,该接口在调用onLayoutCompleted()时触发。

public class LayoutCompletionLinearLayoutManager extends LinearLayoutManager {
public void setCallback(OnLayoutCompleteCallback callback) {
mCallback = callback;
}
private OnLayoutCompleteCallback mCallback = null;
public LayoutCompletionLinearLayoutManager(Context context) {
super(context);
}
public LayoutCompletionLinearLayoutManager(Context context, int orientation, boolean reverseLayout) {
super(context, orientation, reverseLayout);
}
public LayoutCompletionLinearLayoutManager(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
public void onLayoutCompleted(RecyclerView.State state) {
super.onLayoutCompleted(state);
if (mCallback != null)
mCallback.onLayoutComplete();
}
public interface OnLayoutCompleteCallback {
void onLayoutComplete();
}
}

第二次

在构建RecyclerViewLayoutManager时使用回调。

final LayoutCompletionLinearLayoutManager layoutMgr = 
new LayoutCompletionLinearLayoutManager(getApplicationContext(), 
LinearLayoutManager.HORIZONTAL, false); // change orientation according to your RecyclerView
layoutMgr.setCallback(new LayoutCompletionLinearLayoutManager.OnLayoutCompleteCallback() {
@Override
public void onLayoutComplete() {
mRecyclerView.scrollToPosition(lastFirstVisiblePosition);
layoutMgr.setCallback(null);
}
});
mRecyclerView.setLayoutManager(layoutMgr);
  1. 因为我的卡片/物品大小不同,只要物品不在特定位置,我就无法返回到上次查看的物品的位置,也就是说,只要下面的物品不在屏幕上。。。有没有办法考虑我卡片的尺寸和根据设置的位置

您需要使用LinearLayoutManagerscrollToPositionWithOffset(),根据您的CardView的维度,而不是scrollToPosition(),带有一些偏移

((LayoutCompletionLinearLayoutManager) mRecyclerView.getLayoutManager())
.scrollToPositionWithOffset(lastFirstVisiblePosition, offset);

最新更新