Android RecyclerView StaggeredGrid 项目在顶部滚动时改变位置
Android RecyclerView StaggeredGrid items change position when scrolling top
在我的 2 列交错网格中,我使用无限列表的效果自动加载 10 x 10 的元素,一切正常,除了当我向上滚动时。前两个元素改变了它们的位置。就像前两项从一列跳到另一列。
据我所知,适配器必须保存每个元素的状态。但是,我不知道该怎么做。
这是我用来显示 StaggeredGrid 功能的主要代码
public class SpacesItemDecoration extends RecyclerView.ItemDecoration {
private int space;
public SpacesItemDecoration(int space) {
this.space = space;
}
@Override
public void getItemOffsets(Rect outRect, View view,
RecyclerView parent, RecyclerView.State state) {
outRect.left = space;
outRect.right = space;
outRect.bottom = space+1;
// Add top margin only for the first item to avoid double space between items
if(parent.getChildLayoutPosition(view) == 0)
outRect.top = space;
}
}
public class SolventViewHolders extends RecyclerView.ViewHolder implements View.OnClickListener {
public TextView vh_name;
public TextView vh_price;
public ImageView vh_image;
public SolventViewHolders(View v) {
super(v);
v.setOnClickListener(this);
vh_image=(ImageView)v.findViewById(R.id.thumbnail);
vh_name= (TextView) v.findViewById(R.id.title);
vh_price= (TextView) v.findViewById(R.id.subtitle);
}
public void sendImage(String url) {
Picasso.with(ctx)
.load(url)
.into(vh_image);
}
@Override
public void onClick(View view) {
int position = getPosition();
if (user_id != null) {
openDetail(MyLogs.get(position).getId_item(), MyLogs.get(position).getItemName(), MyLogs.get(position).getPrice(), MyLogs.get(position).getDescrip(), MyLogs.get(position).getId_store(), MyLogs.get(position).getId_store());
}
}
}
public class SolventRecyclerViewAdapter extends RecyclerView.Adapter<SolventViewHolders> {
private List<productItem> itemList;
private Context context;
public SolventRecyclerViewAdapter(Context context, List<productItem> itemList) {
this.itemList = itemList;
this.context = context;
}
@Override
public SolventViewHolders onCreateViewHolder(ViewGroup parent, int viewType) {
View layoutView = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_mosaico_defoult, null);
SolventViewHolders rcv = new SolventViewHolders(layoutView);
return rcv;
}
@Override
public void onBindViewHolder(SolventViewHolders holder, int position) {
holder.vh_name.setText(itemList.get(position).getName());
holder.vh_price.setText("CLP:"+itemList.get(position).getPrice());
}
@Override
public int getItemCount() {
return this.itemList.size();
}
}
#编辑 1:
这就是我实例化适配器的方式
recyclerView = (RecyclerView)view.findViewById(R.id.recycler_view);
recyclerView.setHasFixedSize(true);
gaggeredGridLayoutManager = new StaggeredGridLayoutManager(2, 1);
recyclerView.setLayoutManager(gaggeredGridLayoutManager);
recyclerView.addItemDecoration(new SpacesItemDecoration(2));
populateList(currentPage);
rcAdapter= new SolventRecyclerViewAdapter(ctx, MyLogs);
recyclerView.setAdapter(rcAdapter);
填充方法以 json 格式的异步任务响应出现:
...
for(int i=0; i < lengthJsonArr; i++)
{
JSONObject jsonChildNode = jsonMainNode.getJSONObject(i);
...
MyLogs.add("name,price,etc");
rcAdapter.notifyDataSetChanged();
}
这就是我按住 onScroll 的方式:
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
visibleItemCount = gaggeredGridLayoutManager.getChildCount();
totalItemCount = gaggeredGridLayoutManager.getItemCount();
int[] firstVisibleItems = null;
firstVisibleItems = gaggeredGridLayoutManager.findFirstVisibleItemPositions(firstVisibleItems);
if (firstVisibleItems != null && firstVisibleItems.length > 0) {
pastVisiblesItems = firstVisibleItems[0];
}
if (loading) {
if ((visibleItemCount + pastVisiblesItems) >= totalItemCount) {
loading= false;
Log.d("tag", "LOAD NEXT ITEM");
currentPage = currentPage + 1;
populateList(currentPage);
}
}
}
});
感谢任何帮助
这是一项功能。重新排序和重新定位视图以实现无缝的项目流。
使用setGapStrategy(int gapStrategy)
Sets the gap handling strategy for StaggeredGridLayoutManager. If the gapStrategy parameter is different than the current strategy, calling this method will trigger a layout request.
您可能需要 GAP_HANDLING_NONE
。
Does not do anything to hide gaps.
发生这种情况是因为当您上下滚动时,holder 无法识别图像视图的宽度和高度。当您向下滚动时,它会清除上面的视图,反之亦然。
这样使用:
@Override
public void onBindViewHolder(ViewHolder viewHolder, int position) {
MyViewHolder vh = (MyViewHolder) viewHolder;
ImageModel item = imageModels.get(position);
RelativeLayout.LayoutParams rlp = (RelativeLayout.LayoutParams)vh.imageView.getLayoutParams();
float ratio = item.getHeight() / item.getWidth();
rlp.height = (int) (rlp.width * ratio);
vh.imageView.setLayoutParams(rlp);
vh.positionTextView.setText("pos: " + position);
vh.imageView.setRatio(item.getRatio());
Picasso.with(mContext).load(item.getUrl()).
placeholder(PlaceHolderDrawableHelper.getBackgroundDrawable(position)).
into(vh.imageView);
}
要清楚请看这个link:Picasso/Glide-RecyclerView-StaggeredGridLayoutManager
在我的 2 列交错网格中,我使用无限列表的效果自动加载 10 x 10 的元素,一切正常,除了当我向上滚动时。前两个元素改变了它们的位置。就像前两项从一列跳到另一列。
据我所知,适配器必须保存每个元素的状态。但是,我不知道该怎么做。
这是我用来显示 StaggeredGrid 功能的主要代码
public class SpacesItemDecoration extends RecyclerView.ItemDecoration {
private int space;
public SpacesItemDecoration(int space) {
this.space = space;
}
@Override
public void getItemOffsets(Rect outRect, View view,
RecyclerView parent, RecyclerView.State state) {
outRect.left = space;
outRect.right = space;
outRect.bottom = space+1;
// Add top margin only for the first item to avoid double space between items
if(parent.getChildLayoutPosition(view) == 0)
outRect.top = space;
}
}
public class SolventViewHolders extends RecyclerView.ViewHolder implements View.OnClickListener {
public TextView vh_name;
public TextView vh_price;
public ImageView vh_image;
public SolventViewHolders(View v) {
super(v);
v.setOnClickListener(this);
vh_image=(ImageView)v.findViewById(R.id.thumbnail);
vh_name= (TextView) v.findViewById(R.id.title);
vh_price= (TextView) v.findViewById(R.id.subtitle);
}
public void sendImage(String url) {
Picasso.with(ctx)
.load(url)
.into(vh_image);
}
@Override
public void onClick(View view) {
int position = getPosition();
if (user_id != null) {
openDetail(MyLogs.get(position).getId_item(), MyLogs.get(position).getItemName(), MyLogs.get(position).getPrice(), MyLogs.get(position).getDescrip(), MyLogs.get(position).getId_store(), MyLogs.get(position).getId_store());
}
}
}
public class SolventRecyclerViewAdapter extends RecyclerView.Adapter<SolventViewHolders> {
private List<productItem> itemList;
private Context context;
public SolventRecyclerViewAdapter(Context context, List<productItem> itemList) {
this.itemList = itemList;
this.context = context;
}
@Override
public SolventViewHolders onCreateViewHolder(ViewGroup parent, int viewType) {
View layoutView = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_mosaico_defoult, null);
SolventViewHolders rcv = new SolventViewHolders(layoutView);
return rcv;
}
@Override
public void onBindViewHolder(SolventViewHolders holder, int position) {
holder.vh_name.setText(itemList.get(position).getName());
holder.vh_price.setText("CLP:"+itemList.get(position).getPrice());
}
@Override
public int getItemCount() {
return this.itemList.size();
}
}
#编辑 1:
这就是我实例化适配器的方式
recyclerView = (RecyclerView)view.findViewById(R.id.recycler_view);
recyclerView.setHasFixedSize(true);
gaggeredGridLayoutManager = new StaggeredGridLayoutManager(2, 1);
recyclerView.setLayoutManager(gaggeredGridLayoutManager);
recyclerView.addItemDecoration(new SpacesItemDecoration(2));
populateList(currentPage);
rcAdapter= new SolventRecyclerViewAdapter(ctx, MyLogs);
recyclerView.setAdapter(rcAdapter);
填充方法以 json 格式的异步任务响应出现:
...
for(int i=0; i < lengthJsonArr; i++)
{
JSONObject jsonChildNode = jsonMainNode.getJSONObject(i);
...
MyLogs.add("name,price,etc");
rcAdapter.notifyDataSetChanged();
}
这就是我按住 onScroll 的方式:
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
visibleItemCount = gaggeredGridLayoutManager.getChildCount();
totalItemCount = gaggeredGridLayoutManager.getItemCount();
int[] firstVisibleItems = null;
firstVisibleItems = gaggeredGridLayoutManager.findFirstVisibleItemPositions(firstVisibleItems);
if (firstVisibleItems != null && firstVisibleItems.length > 0) {
pastVisiblesItems = firstVisibleItems[0];
}
if (loading) {
if ((visibleItemCount + pastVisiblesItems) >= totalItemCount) {
loading= false;
Log.d("tag", "LOAD NEXT ITEM");
currentPage = currentPage + 1;
populateList(currentPage);
}
}
}
});
感谢任何帮助
这是一项功能。重新排序和重新定位视图以实现无缝的项目流。
使用setGapStrategy(int gapStrategy)
Sets the gap handling strategy for StaggeredGridLayoutManager. If the gapStrategy parameter is different than the current strategy, calling this method will trigger a layout request.
您可能需要 GAP_HANDLING_NONE
。
Does not do anything to hide gaps.
发生这种情况是因为当您上下滚动时,holder 无法识别图像视图的宽度和高度。当您向下滚动时,它会清除上面的视图,反之亦然。
这样使用:
@Override
public void onBindViewHolder(ViewHolder viewHolder, int position) {
MyViewHolder vh = (MyViewHolder) viewHolder;
ImageModel item = imageModels.get(position);
RelativeLayout.LayoutParams rlp = (RelativeLayout.LayoutParams)vh.imageView.getLayoutParams();
float ratio = item.getHeight() / item.getWidth();
rlp.height = (int) (rlp.width * ratio);
vh.imageView.setLayoutParams(rlp);
vh.positionTextView.setText("pos: " + position);
vh.imageView.setRatio(item.getRatio());
Picasso.with(mContext).load(item.getUrl()).
placeholder(PlaceHolderDrawableHelper.getBackgroundDrawable(position)).
into(vh.imageView);
}
要清楚请看这个link:Picasso/Glide-RecyclerView-StaggeredGridLayoutManager