IT recording...

[Android] RecyclerView 사용하기 본문

Android

[Android] RecyclerView 사용하기

I-one 2020. 8. 16. 15:41

안드로이드 공부를 무작정 앱을 만들고자 시작한 후 recyclerView를 접했을 때 복잡해서 구조를 이해하기 힘들었다. 

내가 이해한 대로 최대한 쉽게 설명해 보겠다. 

 

recyclerview는 반복되는 화면을 for문을 사용하지 않고 화면에 띄워주는 역할을 하는 애다. 

여러 데이터들을 노출 시켜 줄 때 화면을 넘어가게 되면 스크롤도 된다.

 

recyclerView 이해 돕기 위한 그림(4-1과 같은 번호는 아래 설명 번호이다.)

 

사용법 

 

1. 일단 사용하려면 종속성을 추가해야 한다. 

> build.gradle(:app) 의 dependency에 아래 코드를 추가한 후 우측 상단에 보이는 sync를 통해 싱크를 맞춘다.
**아래 코드는 2020.08.16 기준 작성된 코드이므로 만약 적용이 안되면 자신의 프로그램 버전에 맞는 아이를 찾기 바란다.
참고로 나는 인터넷에서 찾았던 androidx 이거 아닌 버전으로 했다가 오류 나서 한참 고생했다. 
implementation 'androidx.recyclerview:recyclerview:1.1.0'

 

2. activity_main.xml 에 recyclerView 위젯 추가

> 꼭 activity_main.xml이 아니어도 그냥 사용할 xml파일, 얘를 배치할 공간에 아래 코드 붙여 넣으면 된다.
id 지정은 꼭 해야 한다. 나중에 mainActivity에서 아이디로 얘 찾아오기 때문
**<andoidx.recyclerview.widget.RecyclerView 이 부분도 무작정 복사하지 말고 <recycler 정도 치면 나오는 자동 완성 기능 사용하길 바란다.
이거 그냥 썼다가 mainActivity의 setContentView(R.layout.activity_main); 맨 처음 프로젝트 시작하는 곳에서 부터 오류 나서 또 고생했었다. 
<androidx.recyclerview.widget.RecyclerView
        android:id="@+id/my_recycler_view"
        android:scrollbars="vertical"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1" />

 

3. row_items.xml 만들기

위젯에 반복해서 들어갈 애들의 레이아웃을 정하는 곳이다. 

row_items.xml 레이아웃

원하는 대로 디자인 하면 된다. 나ㅜ중에 어댑터에서 recyclerView위젯이랑 연결된다

데이터 넣을 곳에는 id 설정을 해놓아야 한다. 나중에 어댑터에서 이 위치 찾아야 하기 때문

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    android:layout_height="60dp"
    android:layout_width="match_parent"
    android:orientation="horizontal"
    android:padding="10dp"
    android:background="@drawable/round_style"
    >
    <!--<androidx.cardview.widget.CardView
        android:id="@+id/card_view"
        android:layout_gravity="center"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_margin="12dp"
        card_view:cardCornerRadius="4dp">-->

    <LinearLayout
        android:layout_width="0dp"
        android:layout_weight="0.2"
        android:layout_height="match_parent"
        android:orientation="vertical">
        <TextView
            android:id="@+id/textView_empty"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:text="남은 자리 수"
            android:textStyle="bold"
            android:gravity="center"
            android:paddingBottom="5dp"
            android:textSize="16sp"/>
        <TextView
            android:id="@+id/textView_current"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="0.7"
            android:text="현재자리/전체"
            android:textSize="11sp"
            android:gravity="center"/>

    </LinearLayout>



    <LinearLayout
        android:layout_width="0dp"
        android:layout_weight="1"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:layout_marginLeft="3dp"
        android:background="@drawable/left_stroke">
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1">
            <TextView
                android:id="@+id/textView_name"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:text="과목이름"

                android:gravity="center"
                android:textSize="13sp"
                />
            <TextView
                android:id="@+id/textView_professor"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:background="@drawable/left_stroke"
                android:text="교수님"
                android:textSize="11sp"
                android:gravity="center"
                />

        </LinearLayout>
        <TextView
            android:id="@+id/textView_time"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:text="시간"
            android:paddingTop="3.5dp"
            android:gravity="center"
            android:textSize="11sp"
            />


    </LinearLayout>

    <TextView
        android:id="@+id/textView_number"
        android:layout_width="0dp"
        android:layout_weight="0.2"
        android:layout_height="match_parent"
        android:paddingLeft="3dp"
        android:text="과목번호"
        android:gravity="center"
        android:background="@drawable/left_stroke"/>



    <!--</androidx.cardview.widget.CardView>-->
</LinearLayout>

 

 

4. MyAdapter.java 어댑터 만들기 

mainActivity.java있는 폴더에 새로운 class를 생성한다. 바로 어댑터이다. 

public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder>
이름은 그냥 MyAdapter라고 했다. 이름은 다른거 해도 괜찮다 그 후 빨간색 부분을 쓰면 스튜디오가 알아서 자동 완성으로 함수 몇개 만들으라고 한다. 

만들면 생기는 애들에 대해서 설명하겠다. 
4-1. 위에서 만든 row_items.xml 의 요소들을 ID를 이용해서 찾아주는 역할이다. 

public static class MyViewHolder extends RecyclerView.ViewHolder {
public TextView textView_number;

public MyViewHolder(View v) {
super(v);
textView_number = v.findViewById((R.id.textView_number));
}}

빨간색 부분에 textView, ImageView등 row_items에 존재하는 요소들 연결 시켜 놓으면 된다. 

4-2. 어댑터 생성자이다. 
나의 경우는 데이터(classData의 ArrayList)를 생성자를 통해 받아왔다. 
다른 데이터를 받아 올 사람들은 자료형만 바꿔서 받아오면 된다.

public MyAdapter(ArrayList<classData> classDataset) {
this.classDataset = classDataset;
}
4-3. 화면에 뭘 반복적으로 뿌려줄지 결정하는 부분
R.layout.row_items를 통해 이 레이아웃을 계속 뿌려줄 것이라고 알려준다.
(어댑터와 row_items.xml 연결)

public MyAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent,int viewType) {
LinearLayout v = (LinearLayout) LayoutInflater.from(parent.getContext()).inflate(R.layout.row_items, parent, false);
MyViewHolder vh = new MyViewHolder(v);
return vh;
}
4-4. 화면 각 요소에 들어갈 데이터들 넣어주는 부분
row_items.xml 의 아이디가 textView_number인 요소에 가지고 있는 classDataset데이터를 출력해보자

position은 지금 몇번째로 뿌리는 건지를 알려준다. 
** 나는 classDataset 의 ArrayList의 position번째 데이터의 number를 받아와서 (classData 안에 getNumbers() 함수 만듦) 
holder의 textView_number요소에 넘겨주어 출력하게 하였다. 
다른 자료형의 경우는 밑에 주석으로 써놓은 것과 같이 position 사용해서 하면 된다.

public void onBindViewHolder(MyViewHolder holder, int position) {
   holder.textView_number.setText(classDataset.get(position).getNumbers());

   //  그냥 string만 넘겨줄 수도 있다.
   //holder.
textView_number.setText("스트링 아무거나 OK");

   //  classDataset이 만약 string 배열이라면 이런식으로도 가능
   //holder.
textView_number.setText(classDataset[position]);

}
4-5. 데이터 크기 리턴해주는 함수 
이거 return 0; 으로 해놨다가 오류 나서 후딱 size집어넣었다. 배열은 .length 사용하면 됨

public int getItemCount() {
   return classDataset.size();
}

 

import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;

import androidx.recyclerview.widget.RecyclerView;

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

public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {
    private ArrayList<classData> classDataset;

    //각 text,image등을 연결
    public static class MyViewHolder extends RecyclerView.ViewHolder {

        public TextView textView_number;
        public TextView textView_name;
        public TextView textView_professor;
        public TextView textView_time;
        public TextView textView_empty;
        public TextView textView_current;

        public MyViewHolder(View v) {
            super(v);
            textView_number = v.findViewById((R.id.textView_number));
            textView_name = v.findViewById(R.id.textView_name);
            textView_professor = v.findViewById(R.id.textView_professor);
            textView_time = v.findViewById(R.id.textView_time);
            textView_empty = v.findViewById(R.id.textView_empty);
            textView_current = v.findViewById(R.id.textView_current);
        }
    }

    public MyAdapter(ArrayList<classData> classDataset) {
        this.classDataset = classDataset;
    }

    // 각 줄 open
    @Override
    public MyAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent,int viewType) {
        LinearLayout v = (LinearLayout) LayoutInflater.from(parent.getContext()).inflate(R.layout.row_items, parent, false);
        MyViewHolder vh = new MyViewHolder(v);
        return vh;
    }

    //데이터 세팅
    @Override
    public void onBindViewHolder(MyViewHolder holder, int position) {
        holder.textView_number.setText(classDataset.get(position).getNumbers());
        holder.textView_name.setText(classDataset.get(position).getName().substring(0, classDataset.get(position).getName().indexOf("(")));
        holder.textView_professor.setText(classDataset.get(position).getProfessor());
        holder.textView_time.setText(classDataset.get(position).getTime());
        //String
        int empt = Integer.parseInt(classDataset.get(position).getEmpty());
        int curr = Integer.parseInt(classDataset.get(position).getCurrent());

        holder.textView_empty.setText(Integer.toString(curr-empt));
        holder.textView_current.setText(classDataset.get(position).getEmpty()+"/"+classDataset.get(position).getCurrent());


    }

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

 

5. MainActivity.java에 recycler 어댑터 달기

전역변수로 mAdapter랑 layoutManager를 선언한다. 
recyclerView에서는 layoutManager를 통해 vertical할건지 horizontal할건지 정할 수 있다고 한다.
(But 나는 그냥 기본으로 진행함)
private RecyclerView recyclerView;
private RecyclerView.Adapter mAdapter;
private RecyclerView.LayoutManager layoutManager;
5-1. activity_mai.xml 에서 지정해 놨던 recyclerView위젯을 아이디를 찾아서 recyclerView 변수에 저장한다.
recyclerView = (RecyclerView) findViewById(R.id.my_recycler_view);

(5-1-1) 그 밑에 세줄은 layoutManager 설정하는 것 (나는 default값)
** 만약 fragment에서 사용할 사람이라면 
View view = inflater.inflate(R.layout.fragment_1, container, false);
layoutManager = new LinearLayoutManager(view.getContext());
this 를 view.getContext() 로 context를 찾아서 담아주어야 한다. 


5-2. 어댑터 만들어서 mAdater 변수에 달아준다.
** 어댑터에 파라미터로 데이터를 넘겨줄 수 있다. 넘겨준 데이터는 화면에 출력하는 데 쓰인다.
(나는 classDataset이라는 과목 정보를 클래스 데이터 형식으로 만들어서 넘겨주었다. String[] 형태도 괜찮고, Arraylist 형태도 좋고 다 좋다. 원하는 거 넘겨주고 어댑터에서 자료형만 수정하면 된다. )

 mAdapter = new MyAdapter(classDataset);


5-3. recyclerView위젯에 어댑터 달아준다. 

recyclerView.setAdapter(mAdapter);
 protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        recyclerView = (RecyclerView) findViewById(R.id.my_recycler_view);
        recyclerView.setHasFixedSize(true);
        layoutManager = new LinearLayoutManager(this);
        recyclerView.setLayoutManager(layoutManager);
        
        //어댑터에 넘겨 줄 데이터 받아오기 
        //(이 포스팅에서는 몰라도 된다. 그냥 데이터 저장하는 거라고 생각하기)
		classDataset = new parseData().execute(url,"body").get();

        mAdapter = new MyAdapter(classDataset);
        recyclerView.setAdapter(mAdapter);
    }

 

 

 

 

결과. 학교 시간표를 recyclerView를 통해 화면에 띄웠다. (스크롤 가능)

Comments