안드로이드 RecyclerView(리싸이클러뷰) 사용법 가이드

프로그래밍/Android 관련2018. 3. 29. 20:58

안녕하세요. 개발자 드리머즈입니다.


이번 포스트에선 간단한 안드로이드 RecyclerView를 만들어 보겠습니다.



위 사진과 같은 RecyclerView를 만드는 것이 목표입니다. RecyclerView 내부의 Row(행)을 좀 더 예쁘게 표시하기 위해 그리고 공부를 위해 CardView를 사용했습니다.


ListView가 아닌 RecyclerView를 사용하는 이유?

지금은 RecyclerView를 많이 사용해봤기에 괜찮지만 처음에 RecyclerView를 접했을 때는 이름도 좀 이상해보이는 것을 사용해야하나.. 라는 생각이 들었습니다.  하지만 안드로이드 디벨로퍼 공식 홈(https://developer.android.com/guide/topics/ui/layout/recyclerview.html)에 따르면 RecyclerView는 ListView에 비해 더 발전되고 flexible하다고 합니다. RecyclerView는 ListView가 할 수 있는 것을 다 할 수 있고 거기다가 장점이 더 많으니 그냥 항상 RecyclerView를 사용하면 될 것 같습니다.


코드 작성

*build.gradle (Module: app)

1
2
3
4
5
6
7
8
9
10
11
dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support:appcompat-v7:26.1.0'
    implementation 'com.android.support.constraint:constraint-layout:1.0.2'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.1'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
 
    implementation 'com.android.support:cardview-v7:26.1.0'
    implementation 'com.android.support:recyclerview-v7:26.1.0'
}
cs


위 코드와 같이 RecyclerView와 CardView를 사용하기 위해서 app레벨의 build.gradle의 dependencies{}에 아래의 두 코드를 추가합니다.


implementation 'com.android.support:cardview-v7:26.1.0'

implementation 'com.android.support:recyclerview-v7:26.1.0'


project레벨의 build.gradle에 추가하는 것이 아니라 app레벨의 build.gradle에 추가해야합니다.



*위치 : res/layout/

*파일명 : activity_main.xml


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
    >
 
    <android.support.v7.widget.RecyclerView
        android:id="@+id/recycler_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#dddddd"
        />
 
</LinearLayout>
cs
액티비티의 레이아웃은 정말 간단합니다. 그냥 화면을 RecyclerView로 가득 채우는 코드입니다.


*위치 : res/layout/

*파일명 : recycler_view_row.xml


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="80dp"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    app:cardElevation="5dp"
    app:cardCornerRadius="5dp"
    android:layout_marginBottom="1dp"
    android:layout_marginLeft="2dp"
    android:layout_marginRight="2dp"
    android:layout_marginStart="2dp"
    android:layout_marginEnd="2dp"
    >
 
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="horizontal"
        >
 
        <ImageView
            android:id="@+id/iv_picture"
            android:layout_width="60dp"
            android:layout_height="60dp"
            android:layout_gravity="center_vertical"
            android:layout_margin="10dp"
            tools:src="@drawable/bread"
            />
 
        <TextView
            android:id="@+id/tv_price"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical"
            android:textSize="20sp"
            tools:text="5,000원"
            />
 
    </LinearLayout>
 
</android.support.v7.widget.CardView>
cs

RecyclerView의 행(row)를 나타내는 레이아웃입니다.


소스가 좀 길어보이지만 잘 살펴보면 위 사진과 같이 ImageView와 TextView를 포함하는 엄청 간단한 코드입니다.

한 가지 특이한 점은 그래픽적으로 예쁘게 보이게 하려고 CardView안에 이것들을 넣었다는 것입니다. CardView에서 app:cardCornerRadius를 설정하면 round corner를 표현할 수 있습니다.



*파일명 : FoodInfo.java

1
2
3
4
5
6
7
8
9
public class FoodInfo {
    public int drawableId;
    public String price;
 
    public FoodInfo(int drawableId, String price){
        this.drawableId = drawableId;
        this.price = price;
    }
}
cs

하나의 행에 대한 정보를 담을 클래스입니다. 지금 만드는 간단한 예제에서는 ImageView 1개와 TextView 1개가 있기 때문에 이를 설정하는데 사용될 변수 2개가 있습니다.


*파일명 : MainActivity.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public class MainActivity extends AppCompatActivity {
 
    RecyclerView mRecyclerView;
    RecyclerView.LayoutManager mLayoutManager;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
        mRecyclerView = findViewById(R.id.recycler_view);
        mRecyclerView.setHasFixedSize(true);
        mLayoutManager = new LinearLayoutManager(this);
        mRecyclerView.setLayoutManager(mLayoutManager);
 
        ArrayList<FoodInfo> foodInfoArrayList = new ArrayList<>();
        foodInfoArrayList.add(new FoodInfo(R.drawable.strawberry, "5,000원"));
        foodInfoArrayList.add(new FoodInfo(R.drawable.bread, "4,600원"));
        foodInfoArrayList.add(new FoodInfo(R.drawable.noodle, "4,000원"));
 
        MyAdapter myAdapter = new MyAdapter(foodInfoArrayList);
 
        mRecyclerView.setAdapter(myAdapter);
 
    }
}
cs

MainActivity의 소스입니다. 여기의 코드도 간단합니다. xml 레이아웃의 RecyclerView를 가져와서 LayoutManager와 Adapter를 설정합니다. 설정하는 LayoutManager에 따라 RecyclerView에 보여지는 아이템(row?)의 배치 방법이 달라집니다. 대부분의 경우에 일렬로 나열하면 되므로 LinearLayoutManager를 사용하면 됩니다. 

myAdapter를 RecyclerView의 어댑터로 설정했습니다. MyAdapter부분에 핵심 코드가 있습니다.


*파일명 : MyAdapter.java


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
public class MyAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>  {
 
    public static class MyViewHolder extends RecyclerView.ViewHolder {
        ImageView ivPicture;
        TextView tvPrice;
 
        MyViewHolder(View view){
            super(view);
            ivPicture = view.findViewById(R.id.iv_picture);
            tvPrice = view.findViewById(R.id.tv_price);
        }
    }
 
    private ArrayList<FoodInfo> foodInfoArrayList;
    MyAdapter(ArrayList<FoodInfo> foodInfoArrayList){
        this.foodInfoArrayList = foodInfoArrayList;
    }
 
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
 
        View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.recycler_view_row, parent, false);
 
        return new MyViewHolder(v);
    }
 
    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
 
        MyViewHolder myViewHolder = (MyViewHolder) holder;
 
        myViewHolder.ivPicture.setImageResource(foodInfoArrayList.get(position).drawableId);
        myViewHolder.tvPrice.setText(foodInfoArrayList.get(position).price);
    }
 
    @Override
    public int getItemCount() {
        return foodInfoArrayList.size();
    }
}
cs


RecyclerView에서 핵심이되는 부분은 RecyclerView가 아니라 Adapter를 정의하는 코드입니다. 처음에 보면 좀 복잡해 보이지만! 하나하나 보다보면 전혀 어렵지 않습니다.

순서대로 보겠습니다.

MyAdapter는 RecyclerView.Adapter<RecyclerView.ViewHolder>를 상속받아서 정의하면 됩니다.

MyAdapter의 내부에 RecyclerView.ViewHolder를 상속받는 클래스를 정의합니다. 이 클래스가 RecyclerView의 행(row)를 표시하는 클래스입니다.

MyAdapter 생성자는 ArrayList<FoodInfo>를 인자로 가집니다. MainActivity.java 코드를 보면 아래처럼 MyAdapter를 생성할 때 표시하고자하는 데이터를 전달했었습니다.


MyAdapter myAdapter = new MyAdapter(foodInfoArrayList);

onCreateViewHolder()함수는 RecyclerView의 행을 표시하는데 사용되는 레이아웃 xml을 가져오는 역할을 합니다.

onBindViewHolder()함수에서 마침내 RecyclerView의 행에 보여질 ImageView와 TextView를 설정합니다.

getItemCount()함수는 RecyclerView의 행 갯수를 리턴하면 됩니다.


*사용된 이미지

*경로 : res/drawable/

bread.png


noodle.png


strawberry.png



여기까지 작성하면 처음에 본 RecyclerView 화면처럼 됩니다.

기타


RecyclerView의 행(row)를 나타내는데 사용된 recycler_view_row.xml에 있는 CardView의 app:cardCornerRadius를 아예 사용하지 않거나 0dp로 설정하면 위 사진처럼 직각 모서리를 가지게 됩니다.


추가로 recycler_view_row.xml에 있는 CardView의 app:cardElevation을 아예 사용하지 않거나 0dp로 설정하면 위 사진처럼 행 주위에 있던 그림자가 사라집니다. 필요에 따라 적당한 값을 사용하면 됩니다.




작성자

Posted by 드리머즈

관련 글

댓글 영역