Single Adapter for Multi type/Multi view/Multi object

In this article, explained about a single adapter can handle multi view means an adapter can handle different type of data and layout which will inflate in RecyclerView. This article is very simple and easy to implement.

Single Adapter for Multi type/Multi view/Multi object

Single Adapter for Multiple View

Download sample application->>  MultiViewRecycleList

A Recycleview can display multiple view holder at same time and all have different layout and data. In this blog, will explain how to handle all different view holders and layouts into a single adapter in easy way.

There are 2 way to handle this :

1. Use https://github.com/sockeqwe/AdapterDelegates

2. Use Different ViewHolder.

Here I will explain 2nd one.

Now let’s start with a new project in Android Studio.

1. Create a new android project in Android Studio from 

File ->> New Project ->> BasicActivity.

 

2. Implement dependency in app gradle file.

apply plugin: 'com.android.application'

android {
    compileSdkVersion 28
    defaultConfig {
        applicationId "datanapps.multiviewrecyclelistsample"
        minSdkVersion 17
        targetSdkVersion 28
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support:appcompat-v7:28.0.0'
    implementation 'com.android.support:recyclerview-v7:28.0.0'
    implementation "com.hannesdorfmann:adapterdelegates3:3.0.1"
    implementation 'com.android.support.constraint:constraint-layout:1.1.3'

    // picasso
    implementation 'com.squareup.picasso:picasso:2.71828'

    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}

 

3. Add the below resources to respective strings.xmlcolors.xml and styles.xml files.

strings.xml

<resources>
    <string name="app_name">MultiViewRecycleListSample</string>
</resources>

colors.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="colorPrimary">#008577</color>
    <color name="colorPrimaryDark">#00574B</color>
    <color name="colorAccent">#D81B60</color>
    <color name="colorPink">#F7B8F0</color>
    <color name="colorOrange">#F3E978</color>
    <color name="colorWhite">#FFFFFF</color>
    <color name="colorGrey">#A6A6A6</color>
    <color name="colorBlack">#000000</color>
    <color name="colorYellow">#F6E52A</color>
    <color name="colorPurple">#BA1FF3</color>
    <color name="colorPurpleTransparent">#A6BA1FF3</color>
</resources>

styles.xml

<resources>

    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
    </style>

</resources>

 

 4. Open AndroidManifest.xml and add INTERNET permission.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="datanapps.multiviewrecyclelistsample">


    <uses-permission android:name="android.permission.INTERNET"/>


    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme"
        tools:ignore="GoogleAppIndexingWarning">


        <activity android:name=".simple.MainActivity"
            android:screenOrientation="portrait"
            >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>


      <!--  <activity android:name=".delegates_example.DelegateExampleActivity"
            android:screenOrientation="portrait"
            >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>-->


    </application>

</manifest>

5. Now create a base model interface and create models for all different view type and extend base model.

BaseModel.class

package datanapps.multiviewrecyclelistsample.models;

/**
 * Base interface for all items that can be shown in a feed
 */
public interface BaseModel {
}

 

Header.class

package datanapps.multiviewrecyclelistsample.models;

public class Header implements BaseModel {

    private String  headerName;

    public Header() {
        // nothing to do here
    }

    public Header(String headerName) {
        this.headerName = headerName;
    }

    public String getHeaderName() {
        return headerName;
    }

    public void setHeaderName(String headerName) {
        this.headerName = headerName;
    }
}

Movie.class

public class Movie implements BaseModel {
    private String title, genre, year;

    public Movie() {
    }

    public Movie(String title, String genre, String year) {
        this.title = title;
        this.genre = genre;
        this.year = year;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String name) {
        this.title = name;
    }

    public String getYear() {
        return year;
    }

    public void setYear(String year) {
        this.year = year;
    }

    public String getGenre() {
        return genre;
    }

    public void setGenre(String genre) {
        this.genre = genre;
    }
}

 

RectHeader.class

package datanapps.multiviewrecyclelistsample.models;

public class RectHeader implements BaseModel {

    private String rectHeaderName;
    private String rectHeaderImageUrl;


    public RectHeader() {
        // nothing to do here
    }

    public RectHeader(String headerImage, String headerName ) {
        this.rectHeaderImageUrl = headerImage;
        this.rectHeaderName = headerName;
    }

    public String getRectHeaderName() {
        return rectHeaderName==null?"":rectHeaderName;
    }

    public void setRectHeaderName(String rectHeaderName) {
        this.rectHeaderName = rectHeaderName;
    }

    public String getRectHeaderImageUrl() {
        return rectHeaderImageUrl;
    }

    public void setRectHeaderImageUrl(String rectHeaderImageUrl) {
        this.rectHeaderImageUrl = rectHeaderImageUrl;
    }
}

 

User.class

package datanapps.multiviewrecyclelistsample.models;

public class User implements BaseModel {
    private int image;
    private String  name;

    public User() {
        // nothing to do here
    }

    public User(int image, String name) {
        this.image = image;
        this.name = name;
    }

    public int getImage() {
        return image;
    }

    public void setImage(int image) {
        this.image = image;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

6. Create layouts for all different views.

item_layout_header.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="80dp"
    android:background="@color/colorAccent"
    android:clickable="true"
    android:focusable="true"
    android:orientation="vertical">
    <TextView
        android:id="@+id/tv_header"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:ellipsize="end"
        android:layout_alignParentTop="true"
        android:text="Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book."
        android:gravity="center|start"
        android:textColor="@color/colorWhite"
        android:textStyle="bold" />

</RelativeLayout>

item_layout_movie.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@color/colorWhite"
    android:clickable="true"
    android:padding="10dp"
    android:focusable="true"
    android:orientation="vertical"
    >

    <TextView
        android:id="@+id/title"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:text="dfdfdf"
        android:textColor="@color/colorAccent"
        android:textSize="16sp"
        android:textStyle="bold" />

    <TextView
        android:id="@+id/genre"
        android:layout_width="match_parent"
        android:text="fdfdfdfd"
        android:layout_height="wrap_content"
        android:layout_below="@id/title" />

    <TextView
        android:id="@+id/year"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:text="ffdfdfd"
        android:textColor="@color/colorPrimary" />

</RelativeLayout>

item_layout_rect_header.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="250dp"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:background="@color/colorGrey"

    android:clickable="true"
    android:focusable="true"
    android:orientation="vertical">
    <android.support.v7.widget.AppCompatImageView
        android:id="@+id/tv_rect_header_image"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_alignParentTop="true"
        android:gravity="center"
        android:textColor="@color/colorBlack"
        android:textSize="25sp"
        android:textStyle="bold" />

    <TextView
        android:id="@+id/tv_rect_header"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
       app:layout_constraintBottom_toBottomOf="parent"
        android:text="dfdfdf"
        android:textColor="@color/colorWhite"
        android:textSize="25sp"
        android:padding="5dp"
        android:textStyle="bold" />

</android.support.constraint.ConstraintLayout>

item_layout_user.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:clickable="true"
    android:focusable="true"
    android:padding="10dp"
    android:background="@color/colorPurpleTransparent"
    android:orientation="vertical"
    >

    <ImageView
        android:id="@+id/img_image_name"
        android:layout_width="80dp"
        android:layout_height="80dp"
        android:layout_alignParentTop="true"
        android:textColor="@color/colorAccent"
        android:contentDescription="@string/app_name"
        android:src="@color/colorPrimary"
        android:textStyle="bold" />

    <TextView
        android:id="@+id/tv_user_name"
        android:layout_width="match_parent"
        android:layout_marginStart="10dp"
        android:text="@string/app_name"
        android:textSize="22sp"
        android:textColor="@color/colorBlack"
        android:layout_toEndOf="@+id/img_image_name"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:layout_below="@id/title" />

</RelativeLayout>

 

7. Create layout for recycleview to display items:

activity_main.xml

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

    <android.support.v7.widget.RecyclerView
        android:id="@+id/recycler_view"
        android:scrollbars="vertical"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        tools:ignore="MissingConstraints" />

</android.support.constraint.ConstraintLayout>

 

8. Create MultiViewAdapter adapter :

 

package datanapps.multiviewrecyclelistsample.simple;

import android.content.Context;
import android.media.Image;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

import com.squareup.picasso.Picasso;

import java.util.ArrayList;
import java.util.List;

import datanapps.multiviewrecyclelistsample.R;
import datanapps.multiviewrecyclelistsample.models.BaseModel;
import datanapps.multiviewrecyclelistsample.models.Header;
import datanapps.multiviewrecyclelistsample.models.Movie;
import datanapps.multiviewrecyclelistsample.models.RectHeader;
import datanapps.multiviewrecyclelistsample.models.User;

/*
 *
 * Yogendra
 * 11/02/2019
 *
 *
 * This is single adapter that contain multiple view
 *
 * All different model can handle by one adapter
 *
 * */
public class MultiViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

    private List<BaseModel> feedItems;
    private LayoutInflater inflater;

    /*
     * define a constant for identify better
     * */
    final int USER = 0;
    final int RECT_HEADER = 1;
    final int MOVIE = 2;
    final int HEADER = 3;

    /*
     *
     * */
    MultiViewAdapter(Context context) {
        feedItems = new ArrayList<>();
        inflater = LayoutInflater.from(context);

    }

    /*
     * getter for feed item list
     * */
    public void setFeedItems(List<BaseModel> feedItems) {
        this.feedItems = feedItems;
        notifyDataSetChanged();
    }

    @Override
    public int getItemCount() {
        return feedItems == null ? 0 : feedItems.size();
    }

    @Override
    public int getItemViewType(int position) {

        BaseModel baseModel = feedItems.get(position);
        if (baseModel instanceof User) {
            return USER;
        } else if (baseModel instanceof RectHeader) {
            return RECT_HEADER;
        } else if (baseModel instanceof Movie) {
            return MOVIE;
        } else if (baseModel instanceof Header) {
            return HEADER;
        }
        return 0;

    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        switch (viewType) {
            case USER:
                return new UserViewHolder(inflater.inflate(R.layout.item_layout_user, parent, false));
            case RECT_HEADER:
                return new RectHeaderHolder(inflater.inflate(R.layout.item_layout_rect_header, parent, false));
            case MOVIE:
                return new MovieViewHolder(inflater.inflate(R.layout.item_layout_movie, parent, false));
            case HEADER:
                return new HeaderHolder(inflater.inflate(R.layout.item_layout_header, parent, false));
        }

        return new UserViewHolder(inflater.inflate(R.layout.item_layout_user, parent, false));

    }

    @Override
    public void onBindViewHolder(final RecyclerView.ViewHolder holder, final int position) {
        switch (holder.getItemViewType()) {
            case USER:
                final User user = (User) feedItems.get(position);
                final UserViewHolder userViewHolder = (UserViewHolder) holder;
                userViewHolder.userImage.setImageResource(user.getImage());
                userViewHolder.userName.setText(user.getName());

                break;

            case RECT_HEADER:
                final RectHeader rectHeader = (RectHeader) feedItems.get(position);
                final RectHeaderHolder rectHeaderHolder = (RectHeaderHolder) holder;
                rectHeaderHolder.tvRectHeader.setText(rectHeader.getRectHeaderName());
                Picasso.get().load(rectHeader.getRectHeaderImageUrl()).into(rectHeaderHolder.imgHeader);

                break;


            case MOVIE:
                final Movie movie = (Movie) feedItems.get(position);
                final MovieViewHolder movieViewHolder = (MovieViewHolder) holder;
                movieViewHolder.title.setText(movie.getTitle());
                movieViewHolder.genre.setText(movie.getGenre());
                movieViewHolder.year.setText(movie.getYear());

                break;

            case HEADER:
                final Header header = (Header) feedItems.get(position);
                final HeaderHolder headerViewHolder = (HeaderHolder) holder;
               // headerViewHolder.tvHeader.setText(header.getHeaderName() + "" + (position + 1));

                break;
        }
    }

    /*
     * All view holder defined here
     *
     * */
//============================================//

    public class UserViewHolder extends RecyclerView.ViewHolder {
        public TextView userName;
        public ImageView userImage;

        public UserViewHolder(View view) {
            super(view);
            userImage = view.findViewById(R.id.img_image_name);
            userName = view.findViewById(R.id.tv_user_name);

        }
    }


    //============================================//

    public class RectHeaderHolder extends RecyclerView.ViewHolder {
        public TextView tvRectHeader;
        public ImageView imgHeader;
        public View bgView;

        public RectHeaderHolder(View view) {
            super(view);
            bgView = view;
            tvRectHeader = view.findViewById(R.id.tv_rect_header);
            imgHeader =  view.findViewById(R.id.tv_rect_header_image);

        }
    }


    //============================================//
    public class MovieViewHolder extends RecyclerView.ViewHolder {
        public TextView title, year, genre;

        public MovieViewHolder(View view) {
            super(view);
            title = view.findViewById(R.id.title);
            genre = view.findViewById(R.id.genre);
            year = view.findViewById(R.id.year);
        }
    }

    //============================================//

    public class HeaderHolder extends RecyclerView.ViewHolder {
        public TextView tvHeader;

        public HeaderHolder(View view) {
            super(view);

            tvHeader = view.findViewById(R.id.tv_header);

        }
    }
}

9. Create MainActivity.class 

package datanapps.multiviewrecyclelistsample.simple;

import android.graphics.Color;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;

import java.util.ArrayList;
import java.util.List;

import datanapps.multiviewrecyclelistsample.R;
import datanapps.multiviewrecyclelistsample.models.BaseModel;
import datanapps.multiviewrecyclelistsample.models.Header;
import datanapps.multiviewrecyclelistsample.models.Movie;
import datanapps.multiviewrecyclelistsample.models.RectHeader;
import datanapps.multiviewrecyclelistsample.models.User;



/*
 *
 * Yogendra
 * 11/02/2019
 *
 * */

// Sample activity that display recycle view
public class MainActivity extends AppCompatActivity {
    private MultiViewAdapter multiViewAdapter;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        createAdapter();
        setRecycleView();
    }

    /*
    *
    * prepare adapter
    * */
    private void createAdapter(){
        multiViewAdapter = new MultiViewAdapter(this);
        multiViewAdapter.setFeedItems(getPreparedItemDate());
    }

/*
* prepare recycle view
*
* */
    private void setRecycleView(){
        RecyclerView recyclerView = findViewById(R.id.recycler_view);
        RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getApplicationContext());
        recyclerView.setLayoutManager(mLayoutManager);
        recyclerView.setItemAnimator(new DefaultItemAnimator());
        recyclerView.setAdapter(multiViewAdapter);
    }

    /*
    *
    * Prepare data list to show in recycle view
    * */
    private  List<BaseModel> getPreparedItemDate() {

        List<BaseModel> itemList = new ArrayList<>();
        itemList.add(new Movie("Mad Max: Fury Road", "Action & Adventure", "2015"));
        itemList.add(new User(R.mipmap.ic_launcher, "Vinay"));
        itemList.add(new RectHeader("http://hippy.in/wp-content/uploads/old-bollywood-movie-posters-for-sale-mughal-e-azam.jpg", " Mughal-E-Azam"));
        itemList.add(new Header("Header "));
        itemList.add(new User(R.drawable.ic_avatar_male_1, "Yogendra"));
        itemList.add(new Movie("Apane", "Family", "2009"));
        itemList.add(new Header("Header "));
        itemList.add(new User(R.drawable.ic_avatar_female, "Shakila"));
        itemList.add(new User(R.mipmap.ic_launcher, "Kishor"));
        itemList.add(new User(R.drawable.ic_avatar_male_1, "Pawan"));
        itemList.add(new Header("Header "));
        itemList.add(new Movie("BOSS", "Actios", "2012"));
        itemList.add(new RectHeader("https://cdn.shopify.com/s/files/1/0747/3829/products/mNS0678_1024x1024.jpg?v=1502489793", " Barfi"));
        itemList.add(new Movie("YES", "Romanse", "2005"));
        itemList.add(new Movie("Baby", "Actios", "2014"));
        itemList.add(new RectHeader("https://cdn.shopify.com/s/files/1/0747/3829/products/mNS0681_1024x1024.jpg?v=1502406836", " BHaag Milkha Bhaag"));
        itemList.add(new Header("Header "));
        itemList.add(new RectHeader("https://static-koimoi.akamaized.net/wp-content/new-galleries/2015/11/ghayal-once-again-movie-poster-3.jpg", " Ghayal-Once-Again"));
        itemList.add(new Header("Header "));
        itemList.add(new User(R.drawable.ic_avatar_female, "Kiran"));
       itemList.add(new Header("Header "));
        return itemList;
    }
    }

 

Download sample application->>  MultiViewRecycleList

---------------------------------------------

Please suggest ideas for my next blog in comment section.

Thank you so much, Have a great day !

please click LIKE button and SHARE to help others find it!


Click Here To See More

What's Your Reaction?

like
1
dislike
0
love
0
funny
0
angry
0
sad
0
wow
3