본문 바로가기
안드로이드 자바

[Java][Android] 리사이클러뷰 뷰형태 구분하기

by teamnova 2021. 7. 21.

이번 포스팅에서는 안드로이드 리사이클러뷰 뷰형태를 구분하는 것을 자바로 구현해보겠습니다.

 

보통의 리사이클러뷰는 하나의 뷰홀더를 지정해 놓고,
스크롤이 있는 리스트 형식의 뷰를 데이터만 갈아끼우면서 보여주는데요,

예를들면,

뷰 형태가 1개인 리사이클러뷰

이런 식으로 데이터를 보여주는 뷰의 형식은 일정한데, 안에 들어가는 데이터만 다르게 표시가 되죠.

만약 어플에서 하나의 화면에서 하나의 정보만 보여주는 상황만 있다면, 하나의 뷰 형태만으로 충분할지 모릅니다.

하지만, 우리가 겪는 상황은 더 복잡한 상황이 될 가능성이 높습니다.

예를들어, 채팅 화면을 보면 유저가 채팅방에 입장할 때, 내가 채팅을 입력했을 때, 상대가 채팅을 입력했을 때

보여지는 뷰 형태가 다 같다면, 유저가 채팅을 읽을 때 불편함을 느낄 수 있습니다. 또 다른 예시로
댓글과 대댓글이 뷰 형태가 같다면
유저가 댓글과 대댓글을 구분하기 쉽지 않겠죠.

이러한 이유로 하나의 리사이클러뷰에 여러개의 뷰 형태가 필요할 수 있습니다.

아래 포스팅은 여러가지 뷰형태를 가진 간단한 채팅 형태의 리사이클러뷰의 소스코드입니다.

먼저 리사이클러뷰 아이템에 관한 클래스를 작성합니다.

 

Item.java

public class Item {

    private String content;
    private String name;
    private String time;
    private int viewType;

    public Item(String content, String name , String time, int viewType) {
        this.content = content;
        this.name = name;
        this.time = time;        
        this.viewType = viewType;
    }

    public String getContent() {
        return content;
    }

    public String getName() {
        return name;
    }

    public String getTime() {
        return time;
    }

    public int getViewType() {
        return viewType;
    }
}

 

그 다음 뷰 형태에 관한 클래스를 작성합니다.

0 = 유저가 채팅방에 입장했을 때

1 = 상대가 채팅을 입력했을 때

2 = 내가 채팅을 입력했을 때

 

 

ViewType.java

public class ViewType{
    public static final int CENTER_JOIN = 0;
    public static final int LEFT_CHAT = 1;
    public static final int RIGHT_CHAT = 2;    
}

메인 액티비티 레이아웃에 리사이클러뷰를 배치합니다.

 

 

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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=".MainActivity">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/RecyclerView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

그 다음 각 뷰 형태에 대한 레이아웃도 각각 만들어줍니다.

 

 

center_join.xml (채팅방 입장)

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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="wrap_content"
    android:paddingTop="11dp"
    android:paddingBottom="11dp">

    <TextView
        android:id="@+id/content"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="~~~님이 입장하셨습니다."
        android:textColor="#b9bcce"
        android:textSize="15sp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

 

 

left_chat.xml (상대가 채팅을 입력 했을 때)

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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="wrap_content"
    android:background="@color/white"
    android:paddingTop="12dp"
    android:paddingBottom="12dp">

    <TextView
        android:id="@+id/name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="10dp"
        android:text="이름"
        android:textColor="@color/black"
        android:textSize="12sp"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/content"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="10dp"
        android:layout_marginTop="5dp"
        android:paddingLeft="16dp"
        android:paddingTop="4dp"
        android:paddingRight="16dp"
        android:paddingBottom="4dp"
        android:text="상대방이 보낸 메세지"
        android:textColor="#333d4b"
        android:textSize="12sp"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/name" />

    <TextView
        android:id="@+id/time"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="5dp"
        android:text="00:00"
        android:textColor="#b9bcce"
        android:textSize="10sp"
        app:layout_constraintBottom_toBottomOf="@+id/content"
        app:layout_constraintStart_toEndOf="@+id/content" />

</androidx.constraintlayout.widget.ConstraintLayout>

 

 

right_chat.xml (내가 채팅을 입력했을 때)

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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="wrap_content"
    android:background="@color/white"
    android:paddingTop="12dp"
    android:paddingBottom="12dp">

    <TextView
        android:id="@+id/content"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginEnd="15dp"
        android:paddingLeft="16dp"
        android:paddingTop="4dp"
        android:paddingRight="16dp"
        android:paddingBottom="4dp"
        android:text="내가 보낸 메세지"
        android:textColor="@color/black"
        android:textSize="12sp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/time"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginEnd="5dp"
        android:text="00:00"
        android:textColor="#b9bcce"
        android:textSize="10sp"
        app:layout_constraintBottom_toBottomOf="@+id/content"
        app:layout_constraintEnd_toStartOf="@+id/content" />
</androidx.constraintlayout.widget.ConstraintLayout>

 

그 다음 어댑터 부분인데요,
뷰형태마다 뷰홀더 클래스를 각각 정의해서 onCreateViewHolder()에서
ViewType에 따라
다른 ViewHolder 객체를 만들어 리턴해주게 되고,

onBindViewHolder에서는 생성된 뷰홀더 객체에 따라 메인 액티비티에서 받아온 데이터들을 바인딩 해주게 됩니다.

 

 

MyAdapter.java

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

    private ArrayList<Item> myDataList = null;

    MyAdapter(ArrayList<Item> dataList)
    {
        myDataList = dataList;
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
    {
        View view;
        Context context = parent.getContext();
        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

        if(viewType == ViewType.CENTER_JOIN)
        {
            view = inflater.inflate(R.layout.center_join, parent, false);
            return new CenterViewHolder(view);
        }
        else if(viewType == ViewType.LEFT_CHAT)
        {
            view = inflater.inflate(R.layout.left_chat, parent, false);
            return new LeftViewHolder(view);
        }
        else
        {
            view = inflater.inflate(R.layout.right_chat, parent, false);
            return new RightViewHolder(view);
        }
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position)
    {
        if(viewHolder instanceof CenterViewHolder)
        {
            ((CenterViewHolder) viewHolder).content.setText(myDataList.get(position).getContent());
        }
        else if(viewHolder instanceof LeftViewHolder)
        {
            ((LeftViewHolder) viewHolder).name.setText(myDataList.get(position).getName());
            ((LeftViewHolder) viewHolder).content.setText(myDataList.get(position).getContent());
            ((LeftViewHolder) viewHolder).time.setText(myDataList.get(position).getTime());
        }
        else
        {
            ((RightViewHolder) viewHolder).content.setText(myDataList.get(position).getContent());
            ((RightViewHolder) viewHolder).time.setText(myDataList.get(position).getTime());
        }
    }

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

    @Override
    public int getItemViewType(int position) {
        return myDataList.get(position).getViewType();
    }

    public class CenterViewHolder extends RecyclerView.ViewHolder{
        TextView content;

        CenterViewHolder(View itemView)
        {
            super(itemView);

            content = itemView.findViewById(R.id.content);
        }
    }

    public class LeftViewHolder extends RecyclerView.ViewHolder{
        TextView content;
        TextView name;
        TextView time;

        LeftViewHolder(View itemView)
        {
            super(itemView);

            content = itemView.findViewById(R.id.content);
            name = itemView.findViewById(R.id.name);
            time = itemView.findViewById(R.id.time);
        }
    }

    public class RightViewHolder extends RecyclerView.ViewHolder{
        TextView content;
        TextView time;

        RightViewHolder(View itemView)
        {
            super(itemView);

            content = itemView.findViewById(R.id.content);
            time = itemView.findViewById(R.id.time);
        }
    }

}

 

 

MainActivity.java

public class MainActivity extends AppCompatActivity {

    private ArrayList<Item> dataList;

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

        this.initializeData();

        RecyclerView recyclerView = findViewById(R.id.RecyclerView);

        LinearLayoutManager manager
                = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL,false);

        recyclerView.setLayoutManager(manager); // LayoutManager 등록
        recyclerView.setAdapter(new MyAdapter(dataList));  // Adapter 등록
    }

    public void initializeData()
    {
        dataList = new ArrayList<>();

        dataList.add(new Item("팀노바님이 입장하셨습니다.", null, null, ViewType.CENTER_JOIN));
        dataList.add(new Item("스틱코드님이 입장하셨습니다.", null, null, ViewType.CENTER_JOIN));
        dataList.add(new Item("안녕하세요", "스틱코드",  "오후 2:00", ViewType.LEFT_CHAT));
        dataList.add(new Item("안녕하세요", null, "오후 2:01", ViewType.RIGHT_CHAT));

    }
}

하나의 리사이클러뷰에 여러 뷰 형태 적용화면

 

하나의 리사이클러뷰에 여러 뷰 형태를 표시하기 위한 코드만 담기 위해 데이터는 직접 입력해서 넣었습니다.

여러분이 처한 상황에 따라 코드를 수정하여 이용하시면 됩니다.