본문 바로가기
Android Studio

[Android Studio] 첫 안드로이드 앱 개발 시작해보기 - RecyclerView (8)

by jisayDeveloper 2023. 11. 3.
728x90
반응형
SMALL

Recycler View를 사용하려면 build.gradle(app)의 dependencies에 

implementation 'androidx.recyclerview:recyclerview:1.3.2'

추가해야합니다.

 

activity_main.xml

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

    <androidx.recyclerview.widget.RecyclerView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:id="@+id/rv"
            android:scrollbarFadeDuration="0"
            android:scrollbarSize="5dp"
            android:scrollbarThumbVertical="@android:color/darker_gray"
            android:scrollbars="vertical"
            android:layout_weight="1">

    </androidx.recyclerview.widget.RecyclerView>

    <Button
            android:id="@+id/btn_add"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="add"/>

</LinearLayout>

 

 <androidx.recyclerview.widget.RecyclerView>를 추가하고 데이터를 추가하기위해 <Button>도 만들어줍니다.

 

item_list.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">

    <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content"
                  android:orientation="horizontal">

        <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content"
                   android:id="@+id/iv_profile"
                   android:src="@mipmap/ic_launcher"/>
        
        <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent"
                      android:gravity="center_vertical"
                      android:orientation="vertical">

            <TextView android:layout_width="match_parent" android:layout_height="wrap_content"
                      android:id="@+id/tv_name"
                      android:text="jisay"/>
            <TextView android:layout_width="match_parent" android:layout_height="wrap_content"
                      android:id="@+id/tv_content"
                      android:text="recycler view"/>
        </LinearLayout>
    </LinearLayout>

</LinearLayout>

item_list는 추가되는 데이터를 출력하기위한 레이아웃입니다.

 

MainData

package com.example.recyclerview;

public class MainData {

    private int iv_profile;
    private String tv_name;
    private String tv_content;

    public MainData(int iv_profile, String tv_name, String tv_content) {
        this.iv_profile = iv_profile;
        this.tv_name = tv_name;
        this.tv_content = tv_content;
    }
    
    //getter & setter....
   
}

DTO입니다. getter와 setter들도 만들어야 합니다.

 

MainAdapter

package com.example.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 androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import org.jetbrains.annotations.NotNull;

import java.util.ArrayList;

public class MainAdapter extends RecyclerView.Adapter<MainAdapter.CustomViewHolder>{

    private ArrayList<MainData> arrayList;

    public MainAdapter(ArrayList<MainData> arrayList) {
        this.arrayList = arrayList;
    }

    @NonNull
    @NotNull
    @Override
    public MainAdapter.CustomViewHolder onCreateViewHolder(@NonNull @NotNull ViewGroup parent, int viewType) {

        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_list,parent,false);
        CustomViewHolder holder = new CustomViewHolder(view);

        return holder;
    }

    @Override
    public void onBindViewHolder(@NonNull @NotNull MainAdapter.CustomViewHolder holder, int position) {

        holder.iv_profile.setImageResource(arrayList.get(position).getIv_profile());
        holder.tv_name.setText(arrayList.get(position).getTv_name());
        holder.tv_content.setText(arrayList.get(position).getTv_content());

        holder.itemView.setTag(position);
        holder.itemView.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                String curName = holder.tv_name.getText().toString();
                Toast.makeText(v.getContext(), curName, Toast.LENGTH_SHORT).show();
            }
        });

        holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View v) {
                remove(holder.getAdapterPosition());
                return true;
            }
        });

    }

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

    public void remove(int position){
        try{
            arrayList.remove(position);
            notifyItemRemoved(position);
        }catch (IndexOutOfBoundsException e){
            e.printStackTrace();
        }
    }

    public class CustomViewHolder extends RecyclerView.ViewHolder {

        protected ImageView iv_profile;
        protected TextView tv_name;
        protected TextView tv_content;
        
        public CustomViewHolder(@NonNull @NotNull View itemView) {
            super(itemView);
            this.iv_profile = (ImageView) itemView.findViewById(R.id.iv_profile);
            this.tv_name = (TextView) itemView.findViewById(R.id.tv_name);
            this.tv_content = (TextView) itemView.findViewById(R.id.tv_content);
        }
    }
}

하나 하나 살펴보겠습니다.

 

MainAdapter

  • RecyclerView.Adapter를 상속하고  MainData객체를 처리할 겁니다.

생성자

  • ArrayList<MainData>를 매개 변수로 받습니다.

onCreateViewHolder

  • 뷰홀더를 생성하고 뷰를 연결하는 부분입니다.
  • 이 메서드에서는 list_item.xml 레이아웃을 사용하여 뷰를 생성하고, 이를 CustomViewHolder 객체에 연결합니다.

onBindViewHolder

  • arrayList에서 해당 위치의 데이터를 가져와 뷰 홀더에 설정합니다. 
  • 항목을 클릭하면 토스트 메시지를 표시합니다.
  • 항목을 롱클릭하면 해당 항목을 제거합니다.

getItemCount

  • 어댑터에서 관리하는 데이터 목록의 크기를 반환합니다.
  • 이 크기는 리사이클러 뷰에 몇 개의 항목이 표시될지 결정하는 중요한 부분입니다.

remove

  • arrayList에서 해당 위치의 데이터를 제거하고, 해당 위치의 항목을 제거한 것을 리사이클러 뷰에 알립니다.

CustomViewHolder

  • 리사이클러 뷰의 각 항목에 대한 뷰들을 담는 역할을 합니다.
  • 내부 클래스로 어댑터 클래스 내부에 정의되며, 각 항목에 표시될 뷰들을 이 클래스의 멤버 변수로 가지고 있습니다.

 

MainActivity

package com.example.recyclerview;

import android.view.View;
import android.widget.Button;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import java.util.ArrayList;

public class MainActivity extends AppCompatActivity {

    private ArrayList<MainData> arrayList;
    private MainAdapter mainAdapter;
    private RecyclerView recyclerView;
    private LinearLayoutManager linearLayoutManager;

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

        recyclerView = (RecyclerView) findViewById(R.id.rv);
        linearLayoutManager = new LinearLayoutManager(this);
        recyclerView.setLayoutManager(linearLayoutManager);

        arrayList = new ArrayList<MainData>();
        mainAdapter = new MainAdapter(arrayList);
        recyclerView.setAdapter(mainAdapter);

        Button btn_add = (Button) findViewById(R.id.btn_add);
        btn_add.setOnClickListener(new View.OnClickListener() {
        
            @Override
            public void onClick(View v) {
                MainData data = new MainData(R.mipmap.ic_launcher, "jisay", "recycleView");
                arrayList.add(data);
                mainAdapter.notifyDataSetChanged();
            }
        });

    }
}

 

ArrayList 및 어댑터 초기화 

  • private ArrayList<MainData> arrayList; : ArrayList는 리사이클러 뷰에 표시될 데이터를 보유합니다.  
  • private MainAdapter mainAdapter; : 리사이클러뷰와 데이터를 연결하는 역할을 합니다.
  • private RecyclerView recyclerView; : 리사이클러뷰는 리스트 형태의 항목을 화면에 표시하는 뷰 그룹입니다.
  • private LinearLayoutManager linearLayoutManager; : 레이아웃 매니저는 리사이클러뷰의 항목을 배치하는 방법을 결정합니다.

onCreate 

  • super.onCreate(savedInstanceState); : 부모 클래스의 onCreate 메서드를 호출합니다.
  • setContentView(R.layout.activity_main);: 레이아웃 XML 파일인 activity_main.xml을 화면에 표시합니다.

리사이클러 뷰 초기화 

  • recyclerView = (RecyclerView) findViewById(R.id.rv); : XML 레이아웃에서 rv ID를 가진 리사이클러뷰를 찾아서 recyclerView 변수에 할당합니다.
  • linearLayoutManager = new LinearLayoutManager(this); : 리사이클러 뷰의 레이아웃 매니저를 LinearLayoutManager로 초기화합니다. 레이아웃 매니저는 항목을 수직으로 배치합니다.
  • recyclerView.setLayoutManager(linearLayoutManager); : 리사이클러 뷰에 레이아웃 매니저를 설정합니다.

데이터 관리 및 어댑터 설정

  • arrayList = new ArrayList();: MainData 객체를 담는 ArrayList를 생성합니다.
  • mainAdapter = new MainAdapter(arrayList); : MainAdapter 어댑터를 생성하고, 이 어댑터에 arrayList 데이터를 연결합니다.
  • recyclerView.setAdapter(mainAdapter); : 리사이클러 뷰에 어댑터를 설정하여 데이터를 표시할 수 있도록 합니다.

"Add" 버튼 클릭 리스너

  • "Add" 버튼을 찾아서 클릭 리스너를 설정합니다. 버튼이 클릭되면, 새로운 MainData 객체를 생성하고 arrayList에 추가합니다. 그런 다음, mainAdapter.notifyDataSetChanged();를 호출하여 어댑터에 데이터의 변경 사항을 알립니다. 이로써, 리사이클러뷰는 새로운 항목을 화면에 표시합니다.

이제 결과를 보겠습니다.

 

갈수록 코드도 복잡해지고 4년 전 강의라 버전이 맞지 않아 또 구글링해서 RecyclerView 최신 버전 찾고 안되면 또 어디가 설정이 잘못되서 Error ,Exception 뱉고 많이 어려워졌다...오늘 오전엔 카메라 쓰는 법도 배웠는데 이건 설정이 더 답이 없어서 아무래도 포스팅하는데 시간이 더 걸릴거 같다.

 

 

 

 

728x90
반응형
LIST