Android

[Android] 5주차 스터디 (RecyclerView)

poppy 2020. 11. 25. 22:59
반응형

RecyclerView

- 많은 수의 데이터를 제한된 영역에서 유연하게 표시해주는 위젯입니다

- CustomListView의 확장판이라고 할 수 있고, 유연함과 성능이 더 좋습니다

- 리스트뷰의 사용 목적과 동작 방식이 매우 비슷합니다

- 리사이클러뷰는 유연하기 때문에 수직구조와 수평구조 모두 가능하고 동적 구성이 부드럽습니다

- 리사이클러뷰는 onCreateViewHolder, onBindViewHolder, getItemCount를 필수로 오버라이딩 해야한다는 것이 중요합니다

 

어댑터

- 리사이클러뷰에서 표시될 아이템 뷰를 생성하는 역할

레이아웃 매니저

- 아이템이 뷰에서 어떤 형태로 배치될지 결정하는 요소

- 리니어(Linear): 수평, 수직 방향으로 일렬 배치하는 구조

- 그리드(Grid): 격자 모양으로 배치하는 구조

- 스태거드 그리드(Staggerd Grid): 엇갈린 격자 모양으로 배치하는 구조 ex) 인스타그램

- 리사이클러뷰에서는 레이아웃 매니저를 지정해주어야 합니다

 

초기 작업

리사이클러뷰를 만들기 전에 먼저 초기 작업을 해줍니다

build.gradle (Module: app) 파일에 다음 문장을 추가해줍니다

implementation 'androidx.recyclerview:recyclerview:1.0.0'

[Refactor] - [Migrate to AndroidX] 를 클릭하여 안드로이드X로 마이그레이션 해줍니다

 

1. 메인액티비티에 리사이클러뷰를 추가해줍니다 - 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:layout_width="0dp"
        android:layout_height="0dp"
        android:id="@+id/recycler1"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

리사이클러뷰를 사용하기 위해 가장 큰 틀인 activity_main에 RecyclerView를 추가해줍니다.

 

2. 아이템뷰 레이아웃을 만들어줍니다. - recycler_item.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_height="wrap_content">

    <ImageView
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:id="@+id/icon"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:id="@+id/title"
        android:textSize="24dp"
        android:textColor="#000000"
        app:layout_constraintLeft_toRightOf="@id/icon"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:id="@+id/desc"
        android:textSize="16dp"
        android:textColor="#666666"
        app:layout_constraintLeft_toRightOf="@id/icon"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@id/title" />


</androidx.constraintlayout.widget.ConstraintLayout>

이미지 한 개와 텍스트 두 개를 넣어줍니다. 리스트의 아이템에 들어가는 요소가 이미지 한 개와 텍스트 두 개인 것 입니다.

 

3. Item에 들어갈 요소를 정의해줍니다. - RecyclerItem.java

public class RecyclerItem {
    private Drawable iconDrawable ;
    private String titleStr ;
    private String descStr ;

    public void setIcon(Drawable icon) {
        iconDrawable = icon ;
    }
    public void setTitle(String title) {
        titleStr = title ;
    }
    public void setDesc(String desc) {
        descStr = desc ;
    }

    public Drawable getIcon() {
        return this.iconDrawable ;
    }
    public String getTitle() {
        return this.titleStr ;
    }
    public String getDesc() {
        return this.descStr ;
    }
}

아이템에 들어갈 요소인 이미지와 문자열 두 개를 정의해주고, getter/setter를 넣어줍니다.

 

4. 리스트와 아이템을 이어줄 Adapter를 만들어줍니다. -RecyclerImageTextAdapter.java

public class RecyclerImageTextAdapter extends RecyclerView.Adapter<RecyclerImageTextAdapter.ViewHolder> {
    private ArrayList<RecyclerItem> mData = null; 

    // 생성자
    RecyclerImageTextAdapter(ArrayList<RecyclerItem> list) {
        mData = list ;
    }

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

        View view = inflater.inflate(R.layout.recycler_item, parent, false) ;
        RecyclerImageTextAdapter.ViewHolder vh = new RecyclerImageTextAdapter.ViewHolder(view) ;

        return vh ;
    }

    @Override
    public void onBindViewHolder(RecyclerImageTextAdapter.ViewHolder holder, int position) {
        RecyclerItem item = mData.get(position) ;

        holder.icon.setImageDrawable(item.getIcon()) ;
        holder.title.setText(item.getTitle()) ;
        holder.desc.setText(item.getDesc()) ;
    }

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

    public class ViewHolder extends RecyclerView.ViewHolder {
        ImageView icon ;
        TextView title ;
        TextView desc ;

        ViewHolder(View itemView) {
            super(itemView) ;

            icon = itemView.findViewById(R.id.icon) ;
            title = itemView.findViewById(R.id.title) ;
            desc = itemView.findViewById(R.id.desc) ;
        }
    }
}

RecyclerView.Adpater를 상속받으면 자동으로 onCreateViewHolder, onBindViewHolder, getItemCount 가 생성됩니다.

리사이클러뷰에서는 필수적인 메소드이기 때문에 꼭 구현해야 합니다!

 

private ArrayList<RecyclerItem> mData = null; - 아이템의 3개 요소를 하나의 묶음으로 가져옵니다.

onCreateViewHolder() - ViewHolder를 만들어줍니다. 아이템 뷰를 위한 ViewHolder객체를 생성하여 리턴합니다. 

onBindViewHolder() - ViewHolder를 처리하는 함수입니다. position에 해당하는 데이터를 가져와서 ViewHolder의 아이템 뷰에 표시해 줍니다.

getItemCount() - 메소드 이름에서부터 알 수 있듯이 아이템의 전체 개수를 리턴해서 알려줍니다.

public class ViewHolder - ViewHolder클래스를 만들어 ViewHolder를 정의해줍니다. 뷰에서 요소를 찾아 연결해줘야하므로 itemView.findViewById()로 연결해줍니다.

 

5. 메인액티비티에 Adpater를 연결해주고 데이터를 추가해줍니다. - MainActivity.java

public class MainActivity extends AppCompatActivity {

    RecyclerView mRecyclerView = null;
    RecyclerImageTextAdapter mAdapter = null;
    ArrayList<RecyclerItem> mList = new ArrayList<RecyclerItem>();

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

        mRecyclerView = findViewById(R.id.recycler1);

        //어댑터 연결
        mAdapter = new RecyclerImageTextAdapter(mList);
        mRecyclerView.setAdapter(mAdapter);

        mRecyclerView.setLayoutManager(new LinearLayoutManager(this)); //레이아웃 매니저

        //데이터 추가
        addItem(ContextCompat.getDrawable(this, R.drawable.instagram), "instagram", "this is instagram");
        addItem(ContextCompat.getDrawable(this, R.drawable.youtube), "youtube", "this is youtube");
        addItem(ContextCompat.getDrawable(this, R.drawable.facebook), "facebook", "this is facebook");

        mAdapter.notifyDataSetChanged();  
    }

    public void addItem(Drawable icon, String title, String desc) {
        RecyclerItem item = new RecyclerItem();

        item.setIcon(icon);
        item.setTitle(title);
        item.setDesc(desc);

        mList.add(item);
    }
}

mAdapter = new RecyclerImageTextAdapter(mList); - 넣어줄 리스트를 매개변수로 Adapter에 넣고 Adapter를 생성합니다

mRecyclerView.setAdapter(mAdapter); - 리사이클러뷰에 어댑터를 연결해줍니다

mRecyclerView.setLayoutManager(new LinearLayoutManager(this)); - 리사이클러뷰에 레이아웃 매니저를 지정합니다

mAdapter.notifyDataSetChanged(); - 데이터가 들어갈 때마다 갱신되게 합니다.

addItem() - 데이터를 추가하는 메소드를 정의합니다. RecyclerItem객체를 생성하여 데이터를 연결해주고, 리스트에 데이터를 추가해줍니다.

 

최종화면은 다음과 같습니다!

반응형