繁体   English   中英

RecyclerView 中 CardView 项的滚动位置

[英]Scrolling position of the CardView items in RecyclerView

在用这种方法保存和检索最后查看项目的位置将近一天后,我终于找到了一个解决方案,可以提供所需的输出。 在返回 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. 由于我是初学者,我不确定为此目的使用 Handler 是否是一个聪明的主意?
  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 在您的 Activity 中的位置。

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 商店中的应用链接可以参考..

主活动.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 类,它扩展了我的项目的 RecyclerView 以及 CardView 的 xml 文件......

  1. 由于我是初学者,我不确定为此目的使用 Handler 是否是一个聪明的主意?

处理程序确实不是最聪明的方法,因为 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();
    }
}

第二

在构建RecyclerView LayoutManager 时使用回调。

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. 因为我的卡片/物品大小不同,所以只要物品不在某个位置,我就无法返回到上次查看物品的位置,这意味着只要下面的物品不在屏幕上......有什么办法可以考虑我的卡的尺寸并根据那个设置位置吗?

您需要根据CardView的尺寸而不是scrollToPositionWithOffset()使用带有一些偏移量LinearLayoutManager scrollToPosition()

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM