Search…

Multiple View Type trong RecyclerView

Nguyễn NghĩaNguyễn Nghĩa
15/11/202011 min read
Giới thiệu và cách tạo RecyclerView nâng cao, RecyclerView với nhiều dòng khác nhau hay còn được gọi là RecyclerView Multiple View Type, có thể nhận thấy tính năng News Feed của Facebook.

Custom Adapter RecyclerView Multiple View Type

Việc xây dựng RecylerView có nhiều dòng item khác nhau cũng giống như RecyclerView chỉ có 1 dòng item nhưng khác biệt ở custom adapter như sau:

  • Tạo n ViewHolder ứng với n dòng item.
  • Override lại phương thức getItemViewType(int position) để lấy về kiểu tương ứng với từng vị trí trong collection.
  • Phương thức onCreateViewHolder() phải dựa vào kiểu để tạo ViewHolder tương ứng.
  • Phương thức onBindViewHolder() phải dựa vào kiểu để gắn dữ liệu tương ứng vào ViewHolder.

Hướng dẫn tạo Custom Adapter

Tạo 3 file XML tương ứng với 3 dòng item như sau:

  • row_text.xml: có 1 TextView để hiển thị văn bản.
  • row_image.xml: hiển thị 1 hình ảnh ImageView.
  • row_user.xml: có 2 TextView hiển thị tên và địa chỉ của user.

File row_text.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_marginTop="3dp"
    android:layout_height="wrap_content">
    <TextView
        android:background="#ecf0f1"
        android:padding="5dp"
        android:textColor="#2c3e50"
        android:id="@+id/tv_text"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
</FrameLayout>

File row_image.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginTop="3dp">
    <ImageView
        android:id="@+id/imv_image"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#95a5a6" />
</FrameLayout>

File row_user.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:layout_marginTop="3dp"
    android:background="#bdc3c7"
    android:orientation="vertical">
    <TextView
        android:id="@+id/tv_name"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textColor="#34495e"
        android:textSize="18dp" />
    <TextView
        android:id="@+id/tv_address"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textColor="#16a085"
        android:textSize="16dp" />
</LinearLayout>

Lớp User.java lưu thông tin User:

package com.eitguide.nguyennghia.recyclerviewmultipleviewtype;
/**
 * Created by nguyennghia on 8/28/16.
 */
public class User {
    private String name;
    private String address;

    public User() {
       // TODO something
    }

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

    public String getName() {
        return name;
    }

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

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }
}

Tiếp theo, tiến hành tạo 1 CustomAdapter.

Có 3 ViewHolder như sau:

TextViewHolder

public class TextViewHolder extends RecyclerView.ViewHolder {
    private TextView tvText;

    public TextViewHolder(View itemView) {
        super(itemView);
        tvText = (TextView) itemView.findViewById(R.id.tv_text);

        itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Toast.makeText(mContext, mObjects.get(getAdapterPosition()).toString(), Toast.LENGTH_SHORT).show();
            }
        });
    }
}

ImageViewHolder

public class ImageViewHolder extends RecyclerView.ViewHolder {
    private ImageView imvImage;

    public ImageViewHolder(View itemView) {
        super(itemView);
        imvImage = (ImageView) itemView.findViewById(R.id.imv_image);

        itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Toast.makeText(mContext, mObjects.get(getAdapterPosition()).toString(), Toast.LENGTH_SHORT).show();
            }
        });
    }
}

UserViewHolder

public class UserViewHolder extends RecyclerView.ViewHolder {
    private TextView tvName;
    private TextView tvAddess;

    public UserViewHolder(View itemView) {
        super(itemView);
        tvName = (TextView) itemView.findViewById(R.id.tv_name);
        tvAddess = (TextView) itemView.findViewById(R.id.tv_address);

        itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                User user = (User) mObjects.get(getAdapterPosition());
                Toast.makeText(mContext, user.getName() + ", " + user.getAddress(), Toast.LENGTH_SHORT).show();
            }
        });
    }
}

Override lại phương thức getItemViewType():

@Override
public int getItemViewType(int position) {
    if (mObjects.get(position) instanceof String)
        return TEXT;
    else if (mObjects.get(position) instanceof Integer)
        return IMAGE;
    else if (mObjects.get(position) instanceof User)
        return USER;
    return -1;
}

Override lại phương thức onCreateViewType():

@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    LayoutInflater li = LayoutInflater.from(mContext);
    switch (viewType) {
        case TEXT:
            View itemView0 = li.inflate(R.layout.row_text, parent, false);
            return new TextViewHolder(itemView0);
        case IMAGE:
            View itemView1 = li.inflate(R.layout.row_image, parent, false);
            return new ImageViewHolder(itemView1);
        case USER:
            View itemView2 = li.inflate(R.layout.row_user, parent, false);
            return new UserViewHolder(itemView2);
        default:
            break;
    }
    return null;
}

Override lại phương thức onBindViewHolder():

@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
    switch (getItemViewType(position)) {
        case TEXT:
            TextViewHolder textViewHolder = (TextViewHolder) holder;
            textViewHolder.tvText.setText(mObjects.get(position).toString());
            break;
        case IMAGE:
            ImageViewHolder imageViewHolder = (ImageViewHolder) holder;
            imageViewHolder.imvImage.setImageResource((int) mObjects.get(position));
            break;
        case USER:
            User user = (User) mObjects.get(position);
            UserViewHolder userViewHolder = (UserViewHolder) holder;
            userViewHolder.tvName.setText(user.getName());
            userViewHolder.tvAddess.setText(user.getAddress());
            break;
    }
}

Source code toàn bộ CustomAdapter.java

package com.eitguide.nguyennghia.recyclerviewmultipleviewtype;
import android.content.Context;
import android.media.ImageWriter;
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 android.widget.Toast;
import java.util.List;
/**
 * Created by nguyennghia on 8/28/16.
 */
public class CustomAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
    private Context mContext;
    private List<Object> mObjects;
    public static final int TEXT = 0;
    public static final int IMAGE = 1;
    public static final int USER = 2;
    public CustomAdapter(Context context, List<Object> objects) {
        mContext = context;
        mObjects = objects;
    }

    @Override
    public int getItemViewType(int position) {
        if (mObjects.get(position) instanceof String)
            return TEXT;
        else if (mObjects.get(position) instanceof Integer)
            return IMAGE;
        else if (mObjects.get(position) instanceof User)
            return USER;
        return -1;
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        LayoutInflater li = LayoutInflater.from(mContext);
        switch (viewType) {
            case TEXT:
                View itemView0 = li.inflate(R.layout.row_text, parent, false);
                return new TextViewHolder(itemView0);
            case IMAGE:
                View itemView1 = li.inflate(R.layout.row_image, parent, false);
                return new ImageViewHolder(itemView1);
            case USER:
                View itemView2 = li.inflate(R.layout.row_user, parent, false);
                return new UserViewHolder(itemView2);
            default:
                break;
        }
        return null;
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        switch (getItemViewType(position)) {
            case TEXT:
                TextViewHolder textViewHolder = (TextViewHolder) holder;
                textViewHolder.tvText.setText(mObjects.get(position).toString());
                break;
            case IMAGE:
                ImageViewHolder imageViewHolder = (ImageViewHolder) holder;
                imageViewHolder.imvImage.setImageResource((int) mObjects.get(position));
                break;
            case USER:
                User user = (User) mObjects.get(position);
                UserViewHolder userViewHolder = (UserViewHolder) holder;
                userViewHolder.tvName.setText(user.getName());
                userViewHolder.tvAddess.setText(user.getAddress());
                break;
        }
    }

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

    public class UserViewHolder extends RecyclerView.ViewHolder {
        private TextView tvName;
        private TextView tvAddess;
        public UserViewHolder(View itemView) {
            super(itemView);
            tvName = (TextView) itemView.findViewById(R.id.tv_name);
            tvAddess = (TextView) itemView.findViewById(R.id.tv_address);

            itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    User user = (User) mObjects.get(getAdapterPosition());
                    Toast.makeText(mContext, user.getName() + ", " + user.getAddress(), Toast.LENGTH_SHORT).show();
                }
            });
        }
    }

    public class TextViewHolder extends RecyclerView.ViewHolder {
        private TextView tvText;

        public TextViewHolder(View itemView) {
            super(itemView);
            tvText = (TextView) itemView.findViewById(R.id.tv_text);

            itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    Toast.makeText(mContext, mObjects.get(getAdapterPosition()).toString(), Toast.LENGTH_SHORT).show();
                }
            });
        }
    }

    public class ImageViewHolder extends RecyclerView.ViewHolder {
        private ImageView imvImage;

        public ImageViewHolder(View itemView) {
            super(itemView);

            imvImage = (ImageView) itemView.findViewById(R.id.imv_image);
            itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    Toast.makeText(mContext, mObjects.get(getAdapterPosition()).toString(), Toast.LENGTH_SHORT).show();
                }
            });
        }
    }
}

Sau khi đã tạo xong CustomAdapter thì thêm RecyclerView vào main_activity.xml và cài đặt cho RecyclerView trong MainActivity.java như sau:

File main_activity.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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="com.eitguide.nguyennghia.recyclerviewmultipleviewtype.MainActivity">
    <android.support.v7.widget.RecyclerView
        android:id="@+id/rv_multipe_view_type"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</RelativeLayout>

Cài đặt trong MainActivity.java

package com.eitguide.nguyennghia.recyclerviewmultipleviewtype;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity {
    private static final String TAG = "MainActivity";
    private RecyclerView rvMultipleViewType;
    private List<Object> mData;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        rvMultipleViewType = (RecyclerView) findViewById(R.id.rv_multipe_view_type);
        mData = new ArrayList<>();
        mData.add(new User("Nguyen Van Nghia", "Quan 11"));
        mData.add(R.drawable.avatar_1);
        mData.add("Text 0");
        mData.add("Text 1");
        mData.add(new User("Nguyen Hoang Minh", "Quan 3"));
        mData.add("Text 2");
        mData.add(R.drawable.avatar_2);
        mData.add(R.drawable.avatar_3);
        mData.add(new User("Pham Nguyen Tam Phu", "Quan 10"));
        mData.add("Text 3");
        mData.add("Text 4");
        mData.add(new User("Tran Van Phuc", "Quan 1"));
        mData.add(R.drawable.avatar_4);
        mData.add(R.drawable.avatar_5);
        mData.add("Text 5");
        mData.add(new User("Nguyen Ngoc Tien", "Quan 11"));
        mData.add(R.drawable.avatar_6);
        CustomAdapter adapter = new CustomAdapter(this, mData);
        rvMultipleViewType.setAdapter(adapter);
        rvMultipleViewType.setLayoutManager(new LinearLayoutManager(this));
    }
}

Mỗi phần tử trong danh sách đều có kiểu Object từ đó có thể thêm bất cứ kiểu dữ liệu vào danh sách này (tất cả đối tượng trong Java đều kế thừa từ Object).

Tải code sử dụng trong bài viết:

Bài chung series

IO Stream

IO Stream Co., Ltd

developer@iostream.co
383/1 Quang Trung, ward 10, Go Vap district, Ho Chi Minh city
Business license number: 0311563559 issued by the Department of Planning and Investment of Ho Chi Minh City on February 23, 2012

©IO Stream, 2013 - 2025