Android RecyclerView StaggeredGrid项目在滚动顶部时更改位置

问题描述:

在我的2列交错网格中,我使用无限列表的效果自动将元素10加载10,除了向上滚动时,一切正常。前两个要素改变了他们的立场。它就像前两项从一列跳到另一列。Android RecyclerView StaggeredGrid项目在滚动顶部时更改位置

当我阅读时,适配器必须保存每个元素的状态。但是,我不知道该怎么做。

这是我用来显示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(); 
    } 
} 

#Edit 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格式的asyntask响应发生:

      ... 
      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); 
       } 
      } 
     } 
    }); 

我感谢所有帮助

+0

你是如何将元素添加到您的数据列表?显示用于实例化适配器的代码以及用新项目更新适配器。你说你正在实现它,它使用无限滚动(但没有方法来添加数据到支持您的回收商的适配器的数据结构“ –

+0

塞巴斯蒂安, 我得到了同样的问题,你有一个比bleeding182提出的更好的解决方案? – Rxxxx

+0

@Rxxxx不,这是我找到的唯一解决方案。如果你找到另一个,请让我现在 – Sebastian

这是一个特点。重新排序和重新定位视图以获得无缝的项目。

使用setGapStrategy(int gapStrategy)

设置缝隙处理策略StaggeredGridLayoutManager。如果gapStrategy参数与当前策略不同,则调用此方法将触发布局请求。

您可能需要GAP_HANDLING_NONE

没有做任何事情来隐藏差距。

+0

是的,这个工作,但现在滚动留下前两个元素之间的空间差异。看来一个专栏进一步向下。这是唯一的解决方案? – Sebastian

+0

...你可能只是使用网格布局? –

发生这种情况的原因是,当您向上和向下滚动时,持有人无法识别图像视图的宽度和高度。当您向下滚动时清除上部视图,反之亦然。

使用这样的:

@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); 
} 

为了清楚看到此链接:Picasso/Glide-RecyclerView-StaggeredGridLayoutManager