user5578746
user5578746

Reputation: 319

Image collage in recycler adapter

I have a typical recycler adapter set up. Some of the items in the adapter have images, sometimes just one image, sometimes 20. I want to create an image collage, like the one below, depending on the number of images in each item:

enter image description here

I have 10 different layouts. The first is to be used when the item only has 1 image (1 ImageView in the layout), another used when the item has 2 images (2 ImageViews in the layout), another used when the item has 3 images, etc. If the item has over 10 images, it uses the layout with 10 ImageViews and hides the rest of the images. The layouts are named:

Here is my Recycler adapter:

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

    private static Context context;
    private List<Message> mDataset;

    public RecyclerAdapter(Context context, List<Message> myDataset) {
        this.context = context;
        this.mDataset = myDataset;
    }

    public static class ViewHolder extends RecyclerView.ViewHolder implements View.OnCreateContextMenuListener, View.OnClickListener {
        public TextView title;

        public ViewHolder(View view) {
            super(view);
            view.setOnCreateContextMenuListener(this);

            title = (TextView) view.findViewById(R.id.title);
        }
    }

    @Override
    public RecyclerAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.message_layout, parent, false);
        ViewHolder vh = new ViewHolder((LinearLayout) view);

        return vh;
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        Message item = mDataset.get(position);

        holder.title.setText(item.getTitle());

        int numImages = item.getImages().size();
        if (numImages > 0) {
            // Show image collage
        }
    }

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

}

Here is the main layout, message_layout.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        />

    // Image collage layout

</LinearLayout>

And this is one of the image collage layouts, two_images.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <ImageView
        android:id="@+id/image_one"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:adjustViewBounds="true"
        />

    <ImageView
        android:id="@+id/image_two"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:adjustViewBounds="true"
        />

</LinearLayout>

So the question is, how do I load/inflate the correct layout depending on the number of images into the recycler adapter, and populate the layout with the images?

Upvotes: 1

Views: 1147

Answers (2)

Ariel Perez
Ariel Perez

Reputation: 519

You should create a custom ViewHolder for each one of your layouts.

Imagine you have this ViewHolder: TwoImagesViewHolder

public class TwoImagesViewHolder extends RecyclerView.ViewHolder {
    public TextView title;
    public ImageView imageOne;
    public ImageView imageTwo;

    public TwoImagesViewHolder(@NonNull View view) {
        super(view);
        title = (TextView)view.findViewById(R.id.title);
        imageOne = (ImageView)view.findViewById(R.id.image_one);
        imageTwo = (ImageView)view.findViewById(R.id.image_two);
    }
}

Inside the adapter you can use your holder like this:

@Override
public RecyclerAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    Message item = mDataset.get(position);
    int numImages = item.getImages().size();
    if (numImages == 2) {
        return new TwoImagesViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.message_layout, parent, false))
    }

    // Add all the conditions for your custom ViewHolders 

    return DefaultViewHolder; // Define a Default holder 
}

@Override
public void onBindViewHolder(ViewHolder holder, int position) {
    Message item = mDataset.get(position);
    int numImages = item.getImages().size();
    if (numImages == 2) {
      // Show image collage
      TwoImagesViewHolder holder = (TwoImagesViewHolder)viewHolder;
      holder.title.setText(item.getTitle());
      holder.image_one.setImageResource(...);
      holder.image_two.setImageResource(...);
    }

    // Add all the conditions for your custom ViewHolders 
}

You need to create all your conditions to instance the correct layout holder and remember to have the same conditions for the onCreateViewHolder and onBindViewHolder.

Upvotes: 0

Amit Kumar
Amit Kumar

Reputation: 1458

You can use StaggeredGridLayoutManager to achieve above type of layouts. Click here for more information about StaggeredGridLayoutManager

There are a number of libraries for staggered gridview. you can use any of them. I recommend to use this: AndroidStaggeredGrid

Upvotes: 2

Related Questions