Android RecyclerView StaggeredGrid items change po

2019-01-28 12:24发布

In my Staggered Grid with 2 columns I use the effect of infinite list to automatically load elements 10 by 10, everything works fine except when I scroll up. The first two elements change their position. It is like the first two items jump from one column to another.

As I read, the adapter must save the state of each element. But, I do not know how to do it.

This is the main code that I use to display the StaggeredGrid functionality

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:

This is how I instanciate the adapter

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

The populate method happens as an asyntask response that comes in json format:

                            ...
            for(int i=0; i < lengthJsonArr; i++)
            {

                JSONObject jsonChildNode = jsonMainNode.getJSONObject(i);

                           ...

                MyLogs.add("name,price,etc");
                rcAdapter.notifyDataSetChanged();

            }

And this is how i hold the 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);
                }
            }
        }
    });

I appreciate any help

2条回答
2楼-- · 2019-01-28 12:50

This is a feature. Reordering and repositioning view for a seamless tream of items.

Use 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.

You will probably want GAP_HANDLING_NONE.

Does not do anything to hide gaps.

查看更多
SAY GOODBYE
3楼-- · 2019-01-28 13:04

This happens because the holder dose not recognize the width and height of the Image view when you scroll up and down. It clears the upper view when you scroll down and vice versa.

Use like this :

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

For clear see this link: Picasso/Glide-RecyclerView-StaggeredGridLayoutManager

查看更多
登录 后发表回答