Veeru
Veeru

Reputation: 4936

StaggeredGridView changing item sizes on scroll

I have run into this problem

Am using a staggered grid view and it has a combination of two columns and single columns..Something like this

enter image description here

everything works fine, until i scroll up and down a few times and it randomly changes to something like this

enter image description here

A few more scrolls and it ended up like this

enter image description here I have no idea why and its very random. I tried to do a notifyDataSetChanged each time the page is shown, and does'nt seem to do anything

This is the code for my dashboard

public class DashboardStaggered extends Fragment {
    RecyclerView mRecyclerView;
    View v;
    MasonryAdapter adapter;
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        Log.d("MASONRY", "onCreateView");
        super.onCreate(savedInstanceState);
        if(v==null) {
            Log.d("MASONRY", "v is NULL recreating");
            v = inflater.inflate(R.layout.activity_dashboard_staggered, container, false);
            setupRecyclerView();
        }else{
            Log.d("MASONRY", "v is NOT NULL");

        }

        return v;
    }

    private void setupRecyclerView(){
        mRecyclerView = (RecyclerView) v.findViewById(R.id.masonry_grid);
        mRecyclerView.setLayoutManager(new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL));
        adapter = new MasonryAdapter(getActivity(),this);
        mRecyclerView.setAdapter(adapter);
        SpacesItemDecoration decoration = new SpacesItemDecoration(12);
        mRecyclerView.addItemDecoration(decoration);
        adapter.notifyDataSetChanged();

    }
    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
    }

    @Override
    public void onResume() {
        super.onResume();
        Log.d("MASONRY", "onResume");
        if(mRecyclerView==null) {
            setupRecyclerView();
        }



    }
    @Override
    public void onPause() {
        super.onPause();
        Log.d("MASONRY", "onPause");

    }

}

If needed i could post the adapter too. Any suggestions are highly appreciated folks.

Adapter code here(don't want to make the post messy) http://pastebin.com/QkZbjjp1

Trimmed code http://pastebin.com/Hgsji1RG

Upvotes: 5

Views: 2957

Answers (4)

loose .rival
loose .rival

Reputation: 81

if you are using Glide to load the image, add dontranform() function and set adjustviewbound to true in the image view.

Eg:

Glide.with(context).load(image.getImageUrl())
                .placeholder(R.drawable.placeholder)
                .dontTransform()
                .into(holder.image);

In the layout file:

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/avatar"
        android:adjustViewBounds="true" />

Upvotes: 1

Mohankumar Shan
Mohankumar Shan

Reputation: 131

Hi you can find this answer below, it may helpful for you. use below library,

flutter_staggered_grid_view: ^0.3.2

use below Input List:

const List mylist = [  
  {"img": "assets/images/img_1.png", "title": "Logan"},  
  {"img": "assets/images/img_2.png", "title": "Candyman"},  
  {"img": "assets/images/img_3.png", "title": "Angry Birds"},  
  {"img": "assets/images/img_4.png", "title": "Rocket Life"},  
]

Container(
          height: MediaQuery.of(context).size.height *0.8,
          // child: Text("data"),
          child: StaggeredGridView.countBuilder(
            crossAxisCount: 2,
            itemCount: SearchVideoList.length,
            itemBuilder: (BuildContext context, int index) => new Container(
                color: Colors.transparent,
                child: new Center(
                  child: InkWell(
                    onTap: () {},
                    child: Container(
                      margin: EdgeInsets.all(5),
                      decoration: BoxDecoration(
                          border: Border.all(
                              color: Colors.white.withOpacity(0.5)),
                          borderRadius: BorderRadius.circular(15),
                          image: DecorationImage(
                            image:
                                AssetImage(SearchVideoList[index]['img']),
                            fit: BoxFit.cover,
                          )),
                    ),
                  ),
                )),
            staggeredTileBuilder: (int index) => new StaggeredTile.count(
                index == 3 ? 2 : 1,
                index == 0
                    ? 2
                    : index == 1
                        ? 1
                        : index == 2
                            ? 1
                            : 1),
            mainAxisSpacing: 4.0,
            crossAxisSpacing: 4.0,
          ),
        ),

**Sample output : ** enter image description here

Upvotes: 0

YLS
YLS

Reputation: 1575

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

Upvotes: 0

Veeru
Veeru

Reputation: 4936

As jason mentioned in the comments, it was a blunder in itemgetviewtype, logical error more than anything else. But lesson learnt, the updated code for getItemViewType is

@Override
    public int getItemViewType(int position) {
        // Return type based on position
        return tileDefinitions.get(position).getTileType();
    }

Thanks everyone for pointing it out.

Upvotes: 1

Related Questions