Android의 RecyclerView에 대해서 알아보도록 하겠습니다.
RecyclerView
: 기존의 ListView 보다 유연하고 향상된 성능을 가진 RecyclerView는 안드로이드 버전 5.0에서 발표되었습니다. 기존의 ListView와의 가장 큰 차이점으로는 Layout Manager와 View Holder 패턴의 의무화가 있습니다.
Adapter
: 기존의 ListView에서 사용하는 Adapter와 같은 개념으로, 데이터와 아이템에 대한 View 생성
LayoutManager
: 아이템의 배치를 담당하며, 기존의 ListView에서 제공하던 수직 스크롤뿐만 아니라, 수평, 격자 배열도 제공을 합니다, 아래는 RecyclerView의 LayoutManager가 제공하는 기능입니다.
- LinearLayoutMaanger : 가로 또는 세로 스크롤 목록
- GridLayoutManager : 그리드 형식의 목록
- StaggeredGridLayoutManager : 지그재그형의 그리드 형식 목록
ViewHolder
: ViewHolder 패턴을 이용하여, 매번 아이템을 생성할때 하던 뷰 바인딩을 한번만 하고, 바인딩된 객체를 가져다 쓰는 형식으로 리소스를 줄인 부분으로, RecyclerView에서는 ViewHolder를 강제해놓았습니다.
예제
MainActivity
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.StaggeredGridLayoutManager;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity {
private RecyclerView mRecyclerView;
private RecyclerView.Adapter mAdapter;
private RecyclerView.LayoutManager mLayoutManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mRecyclerView = (RecyclerView) findViewById(R.id.my_recycler_view);
mRecyclerView.setHasFixedSize(true);
ArrayList<Item> items = new ArrayList<>();
items.add(new Item(R.drawable.a, "Micky Mouse1"));
items.add(new Item(R.drawable.b, "Micky Mouse2"));
items.add(new Item(R.drawable.c, "Micky Mouse3"));
items.add(new Item(R.drawable.d, "Micky Mouse4"));
items.add(new Item(R.drawable.a, "Micky Mouse1"));
items.add(new Item(R.drawable.b, "Micky Mouse2"));
items.add(new Item(R.drawable.c, "Micky Mouse3"));
items.add(new Item(R.drawable.d, "Micky Mouse4"));
// 이 부분에서 정렬 방식을 설정합니다.
mLayoutManager = new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL);
mRecyclerView.setLayoutManager(mLayoutManager);
mAdapter = new MyAdapter(items, getApplicationContext());
mRecyclerView.setAdapter(mAdapter);
}
}
MyAdapter
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.ImageView;
import android.widget.TextView;
import java.util.ArrayList;
/**
* Created by jungwoon on 2017. 1. 18..
*/
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
private Context context;
private ArrayList<Item> items;
private int lastPosition = -1;
public MyAdapter(ArrayList<Item> items, Context context) {
this.items = items;
this.context = context;
}
// 뷰 바인딩 부분을 한번만 하도록, ViewHolder 패턴 의무화
public static class ViewHolder extends RecyclerView.ViewHolder {
ImageView imageView;
TextView textView;
public ViewHolder(View view) {
super(view);
imageView = (ImageView) view.findViewById(R.id.image_view);
textView = (TextView) view.findViewById(R.id.text_view);
}
}
// 새로운 뷰 생성
@Override
public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_cardview, parent, false);
ViewHolder viewHolder = new ViewHolder(view);
return viewHolder;
}
// RecyclerView의 getView 부분을 담당하는 부분
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.imageView.setImageResource(items.get(position).getImage());
holder.textView.setText(items.get(position).getImageTitle());
setAnimation(holder.imageView, position);
}
// Item 개수를 반환하는 부분
@Override
public int getItemCount() {
return items.size();
}
// View가 나올때 Animation을 주는 부분
private void setAnimation(View viewToAnimate, int position) {
if (position > lastPosition) {
Animation animation = AnimationUtils.loadAnimation(context, android.R.anim.slide_in_left);
viewToAnimate.setAnimation(animation);
lastPosition = position;
}
}
}
Item
/**
* Created by jungwoon on 2017. 1. 18..
*/
public class Item {
private int image;
private String imageTitle;
public Item(int image, String imageTitle) {
this.image = image;
this.imageTitle = imageTitle;
}
public int getImage() {
return image;
}
public String getImageTitle() {
return imageTitle;
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.nkc.recyclerviewtest.MainActivity">
<android.support.v7.widget.RecyclerView
android:id="@+id/my_recycler_view"
android:scrollbars="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</RelativeLayout>
item_cardview.xml
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<!-- A CardView that contains a TextView -->
<android.support.v7.widget.CardView
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:id="@+id/card_view"
android:layout_gravity="center"
android:layout_width="150dp"
android:layout_height="wrap_content"
android:layout_margin="5dp"
card_view:cardCornerRadius="8dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<ImageView
android:id="@+id/image_view"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/text_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"/>
</LinearLayout>
</android.support.v7.widget.CardView>
</LinearLayout>