10

I am using staggered grid layout. the following is the code:

StaggeredGridLayoutManager glm= new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL);
glm.setGapStrategy(StaggeredGridLayoutManager.GAP_HANDLING_NONE);

I am using GAP_HANDLING_NONE to avoid images swapping from one column to other.

When I start the app, the beginning of the screen is:

enter image description here

After scrolling down to bottom and when I return to the top. randomly the following three images show the layout (it keeps varying)

enter image description here

enter image description here

enter image description here

Saeed Zhiany
  • 2,051
  • 9
  • 30
  • 41
Santhosh
  • 9,965
  • 20
  • 103
  • 243

4 Answers4

6

Staggered grids are likely to have gaps at the edges of the layout. To avoid these gaps, StaggeredGridLayoutManager can offset spans independently or move items between spans. You can control this behavior via setGapStrategy(int):

StaggeredGridLayoutManager sGrid = new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL);
sGrid.setGapStrategy(StaggeredGridLayoutManager.GAP_HANDLING_MOVE_ITEMS_BETWEEN_SPANS);

I hope this will help a buddy.

Daniel
  • 2,320
  • 1
  • 14
  • 27
Kalpesh Rupani
  • 991
  • 4
  • 12
  • I tried this but it still moves the images. There are suspicions that the size of the view is clearly not set in the layout, and since wrap wrap is there, the width and height are 0 at the moment when the glide loads the image, due to which the manager constantly mixes the view between positions. – maXp Jan 10 '20 at 22:28
  • @maXp Please try my answer.Are you check this? – Hardik Talaviya Jan 13 '20 at 05:20
0

Try below code.

Add this Override methode in your Adapter

@Override
public long getItemId(int position) {
    return position;
}

@Override
public int getItemViewType(int position) {
    return position;
}

If this solution is not work for you!

Try below solution

I am using StaggeredGridLayout for getting all gallery images and it's working fine for me.

- Main Activity

/*Init Gallery Photos RecyclerView*/
gallerySglm = new StaggeredGridLayoutManager(2, RecyclerView.VERTICAL);
gallerySglm.setGapStrategy(StaggeredGridLayoutManager.GAP_HANDLING_MOVE_ITEMS_BETWEEN_SPANS);
binding.rvGalleryImg.setLayoutManager(gallerySglm);
galleryPhotosAdapter = new GalleryPhotosAdapter(context, galleryPhotoArrayList);
binding.rvGalleryImg.setAdapter(galleryPhotosAdapter);
galleryPhotosAdapter.notifyDataSetChanged();
/*End Init Gallery Photos RecyclerView*/ 

- Item Layout

Add ImageView inside ConstraintLayout

<?xml version="1.0" encoding="utf-8"?>
<layout>

    <androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:id="@+id/mainCard"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:cardBackgroundColor="@color/main_bg"
        app:cardCornerRadius="@dimen/_5sdp"
        app:cardPreventCornerOverlap="false"
        app:cardUseCompatPadding="false"
        android:layout_margin="@dimen/_2sdp"
        app:layout_constraintDimensionRatio="1:1"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <androidx.constraintlayout.widget.ConstraintLayout
            android:id="@+id/clMain"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <androidx.appcompat.widget.AppCompatImageView
                android:id="@+id/img"
                android:layout_width="0dp"
                android:layout_height="0dp"
                android:scaleType="fitXY"
                android:visibility="visible"
                app:layout_constraintDimensionRatio="1:1"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toTopOf="parent" />

        </androidx.constraintlayout.widget.ConstraintLayout>

    </androidx.cardview.widget.CardView>

</layout>

- Adapter

public class GalleryPhotosAdapter extends RecyclerView.Adapter<GalleryPhotosAdapter.ViewHolder> {

    private Context context;
    private ArrayList<String> arrayList;
    private ConstraintSet set = new ConstraintSet();

    public GalleryPhotosAdapter(Context context, ArrayList<String> arrayList) {
        this.context = context;
        this.arrayList = arrayList;
    }

    @NonNull
    @Override
    public GalleryPhotosAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        ItemGalleryPhotosBinding binding = DataBindingUtil.inflate(LayoutInflater.from(parent.getContext()),
                R.layout.item_gallery_photos, parent, false);
        return new ViewHolder(binding);
    }

    @Override
    public void onBindViewHolder(@NonNull final GalleryPhotosAdapter.ViewHolder holder, final int position) {

        //Set size
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(arrayList.get(position), options);

        String ratio = String.format(Locale.getDefault(), "%d:%d", options.outWidth, options.outHeight);
        set.clone(holder.binding.clMain);
        set.setDimensionRatio(holder.binding.img.getId(), ratio);
        set.applyTo(holder.binding.clMain);
        //End set size

        Glide.with(context)
                .load(arrayList.get(position))
                .into(holder.binding.img);

    }

    @Override
    public int getItemCount() {
        return arrayList.size();
    }

    public class ViewHolder extends RecyclerView.ViewHolder {
        ItemGalleryPhotosBinding binding;

        public ViewHolder(ItemGalleryPhotosBinding binding) {
            super(binding.getRoot());
            this.binding = binding;
        }
    }
}

I hope this can help You!

Thank You.

Hardik Talaviya
  • 1,396
  • 5
  • 18
0

Use this simple solustion for your problem.

    StaggeredGridLayoutManager straggerGridLayoutManager = new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL);
    straggerGridLayoutManager .setGapStrategy(StaggeredGridLayoutManager.GAP_HANDLING_MOVE_ITEMS_BETWEEN_SPANS);
    recyclerView.setLayoutManager(straggerGridLayoutManager);

    dataList = YourDataList (Your Code for Arraylist);

    recyclerView.setItemAnimator(new DefaultItemAnimator());
    recyclerAdapter = new DataAdapter(dataList, recyclerView);
    recyclerView.setAdapter(recyclerAdapter);


    recyclerView.addOnScrollListener(new ScrollListener());

Create class for Custom RecyclerView Scroll Listener.

    private class ScrollListener extends RecyclerView.OnScrollListener {
       @Override
       public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
            recyclerView.invalidateSpanAssignments();
       }
    }
mehul chauhan
  • 1,792
  • 11
  • 26
0

Notice the sample code I provided for you

Images are shown in different proportions based on their dimensions and even some apps show a mixed view of images and videos like Instagram. In the coming tutorial, we will be experiencing such a view where videos are loaded and played with autoplay features when we strolled onto the video view.

When it comes to the implementation technically there is no much difference in regular style of showing images to this staggering view.

Activity_main.Xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="staggered.android.com.staggeredview.MainActivity">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/stagRecycleView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</android.support.constraint.ConstraintLayout>

Recyclerview_row.Xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    android:padding="5dp">

    <ImageView
        android:id="@+id/imgView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scaleType="fitXY"/>

</RelativeLayout>

MainActivity.Java

public class MainActivity extends AppCompatActivity {

    RecyclerViewAdapter adapter;
    ArrayList<Integer> Image;
    RecyclerView recyclerView;
    private RecyclerView.LayoutManager layoutManager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Image = new ArrayList<>(Arrays.asList(
                R.drawable.img1,R.drawable.img2,
                R.drawable.img3,R.drawable.img4,
                R.drawable.img5,R.drawable.img6,
                R.drawable.img7,R.drawable.img8,
                R.drawable.img9,R.drawable.img10,
                R.drawable.img1,R.drawable.img2,
                R.drawable.img3,R.drawable.img4,
                R.drawable.img5,R.drawable.img6,
                R.drawable.img7,R.drawable.img8,
                R.drawable.img9)
        );

        recyclerView = findViewById(R.id.stagRecycleView);

        layoutManager = new StaggeredGridLayoutManager(2,StaggeredGridLayoutManager.VERTICAL);
        recyclerView.setLayoutManager(layoutManager);

        adapter = new RecyclerViewAdapter(this, Image);
        recyclerView.setAdapter(adapter);
    }


}

And finally

RecyclerViewAdapter.Java

public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder> {

    ArrayList<Integer> Image;
    Context context;

    public RecyclerViewAdapter(Context context, ArrayList<Integer> Image) {
        super();
        this.context = context;
        this.Image = Image;
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
        View v = LayoutInflater.from(viewGroup.getContext())
                .inflate(R.layout.recyclerview_row, viewGroup, false);
        ViewHolder viewHolder = new ViewHolder(v);
        return viewHolder;
    }

    @Override
    public void onBindViewHolder(ViewHolder viewHolder, int i) {
        viewHolder.imgview.setImageResource(Image.get(i));
    }

    @Override
    public int getItemCount() {
        return Image.size();
    }

    public static class ViewHolder extends RecyclerView.ViewHolder {

        public ImageView imgview;
        public ViewHolder(View itemView) {
            super(itemView);
            imgview = (ImageView) itemView.findViewById(R.id.imgView);

        }
    }
}

I hope this will help you ;)

Amirhf
  • 380
  • 4
  • 16