https://developer.android.com/reference/android/support/v7/widget/RecyclerView
http://liveonthekeyboard.tistory.com/135
http://www.kmshack.kr/2014/10/android-recyclerview/
[๋ฃจ๋นํ์ดํผ] ๋ ๋๊น์ง ์๋๋ก์ด๋ (์ค์ค์)
-
๊ธฐ์กด์ ListView๋ ์ปค์คํ ํ๊ธฐ์๋ ๊ตฌ์กฐ์ ์ธ ๋ฌธ์ ๋ก ๋ง์ ์ ์ฝ์ด ๋ฐ๋์ผ๋ฉฐ, ๊ตฌ์กฐ์ ์ธ ๋ฌธ์ ๋ก ์ธํด ์ฑ๋ฅ๋ฌธ์ ๊ฐ ์์๋ค. ๊ทธ๋์ ์ด ๋ฌธ์ ๋ค์ ํด๊ฒฐํ๊ธฐ ์ํด ์ข ๋ ๋ค์ํ ํํ๋ก ๊ฐ๋ฐ์๊ฐ ์ปค์คํ ํ ์ ์๋๋ก ๋ง๋ค์ด์ง ๊ฒ์ด RecyclerView!
-
๊ธฐ์กด์ ListView๋ณด๋ค ์ ์ฐํ๊ณ ์ฑ๋ฅ์ด ํฅ์๋ ๊ณ ๊ธ ์์ ฏ
-
๋ฆฌ์คํธ๋ฅผ ํ์ํ๊ธฐ ์ํ ์ด๋ํฐ๋ทฐ๋ฅผ ์ข ๋ ๊ฐ์ ํ ์ปดํฌ๋ํธ
-
ํฐ ํ์ ์ ์งํ ์ฑ ๋ฐ์ดํฐ๋ง ๋ฐ๋
- ์ด๋ํฐ๋ทฐ์์ ์ฐจ์ด์
- RecyclerView๋ ๋ ์ด์์ ๋งค๋์ (LayoutManager)๋ฅผ ์ง์ ํด ์ค์ผ ํจ
- ์ด๋ํฐ๋ทฐ์์๋ ์ ํ์ฌํญ์ด์๋ ๋ทฐํ๋ ํจ๋์ด RecyclerView์์๋ ๊ผญ ๊ตฌํํด์ผ ํจ
- ์ด๋ํฐ๋ทฐ๋ ๋ฏธ๋ฆฌ ์ ๊ณต๋ ์ด๋ํฐ๊ฐ ์๋ ๋ฐ๋ฉด RecyclerView์ ์ด๋ํฐ๋ ์๋ฌด๊ฒ๋ ์ ๊ณตํด ์ฃผ์ง ์์
- ์ฅ์
- ViewHolderํจํด์ ์ ์ฉํ์ฌ ๋ทฐ๋ฅผ ์ฌํ์ฉ
- Swipe๋ฅผ ์ด์ฉํ์ฌ ์ง๊ด์ ์ธ Refresh UI๊ตฌ์กฐ ์ค๊ณ๊ฐ๋ฅ
- position์ ๋ฐ๋ผ์ ํ ๋ฆฌ์คํธ ๋ด์์ ๋ค์ํ ๋ทฐ๋ฅผ ํํ๊ฐ๋ฅ(MultiView)
- ๋จ์
- ์ด๋ฒคํธ ๋ฆฌ์ค๋์ ์ปค์(Cursor)๋ฅผ ์ง์ํ์ง ์์
-
๋ฐ์ดํฐ๋ฅผ ๋ฐฐ์นํ๊ณ , ๋ทฐ์ ์ฌ์ฌ์ฉ ๋ฑ์ ๊ฒฐ์ ํ๋ ์ญํ ์ ํ์ฌ ๊ธฐ์กด์ ์ด๋ํฐ๋ทฐ๋ณด๋ค ์ฑ๋ฅ์ด ๊ฐ์ ๋จ
-
LinearLayoutManager : ๋ฐ์ดํฐ๋ฅผ ๋ฆฌ์คํธ๋ทฐ์ฒ๋ผ ์ธ๋ก๋ ๊ฐ๋ก ํ ์ค๋ก ํ์
-
GridLayoutManager : ๊ทธ๋ฆฌ๋๋ทฐ์ฒ๋ผ ๋ฐ์ดํฐ๋ฅผ ๊ทธ๋ฆฌ๋ ํ์์ผ๋ก ํ์
-
StaggeredGridLayoutManager : ๊ทธ๋ฆฌ๋๋ทฐ์ฒ๋ผ ๋ฐ์ดํฐ๋ฅผ ๊ฒฉ์ ํ์์ผ๋ก ํ์ํ๋ฉด์ ์์ดํ ์ ๋์ด๊ฐ ์ผ์ ํ์ง ์์๋ ๋๋ ์ง๊ทธ์ฌ๊ทธํ ๊ทธ๋ฆฌ๋ ํ์์ผ๋ก ํ์
-
-
๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ข ์์ฑ ์ถ๊ฐ
dependencies{ ... implementation 'com.android.support:recyclerview-v7:26.1.0' implementation 'com.android.support:cardview-v7:26.1.0' }
-
CardView ๋ ์ด์์ ์์ฑ
-
์ด๋ํฐ ์์ฑ
-
RecyclerView.Adapter๋ฅผ ์์๋ฐ์ ๊ตฌํํด์ผ ํจ
-
๋ถ๋ถ์๋ RecyclerView.ViewHolder ํด๋์ค๋ฅผ ์์ํ ๋ทฐํ๋ ์ง์ ํด์ผ ํจ
=> ListView์์๋ ๋ทฐํ๋ ํจํด ์ฌ์ฉ์ด ๊ถ์ฅ์ฌํญ์ด์์ผ๋, RecyclerView๋ ์๋ฌด
import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; import java.util.List; public class MyRecyclerAdapter extends RecyclerView.Adapter<MyRecyclerAdapter.ViewHolder>{ private final List<CardItem> mDataList; public MyRecyclerAdapter(List<CardItem> dataList){ mDataList = dataList; } // ๋ทฐ ํ๋๋ฅผ ์์ฑํ๋ ๋ถ๋ถ. ๋ ์ด์์์ ๋ง๋๋ ๋ถ๋ถ @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view = LayoutInflater.from(parent.getContext()) .inflate(R.layout.item_card, parent, false); return new ViewHolder(view); } // ๋ทฐ ํ๋์ ๋ฐ์ดํฐ๋ฅผ ์ค์ ํ๋ ๋ถ๋ถ @Override public void onBindViewHolder(ViewHolder holder, int position) { // CardItem๋ ์์ดํ ์ ํ์ํ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ง๋ ๋ชจ๋ธ ํด๋์ค CardItem item = mDataList.get(position); holder.title.setText(item.getTitle()); holder.contents.setText(item.getContents()); } //์์ดํ ์ ์ @Override public int getItemCount() { return mDataList.size(); } //๊ฐ๊ฐ์ ์์ดํ ์ ๋ ํผ๋ฐ์ค๋ฅผ ์ ์ฅํ ๋ทฐ ํ๋ ํด๋์ค //๋ฐ๋์ RecyclerView.ViewHolder๋ฅผ ์์ํด์ผ ํจ public static class ViewHolder extends RecyclerView.ViewHolder{ TextView title; TextView contents; public ViewHolder(View itemview){ super(itemview); title = itemview.findViewById(R.id.title_text); contents = itemview.findViewById(R.id.contents_text); } } }
-
-
๋ ์ด์์ ๋งค๋์ ์ ์ด๋ํฐ ์ค์ - LinearLayoutManager
import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.support.v7.widget.GridLayoutManager; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.StaggeredGridLayoutManager; import java.util.ArrayList; import java.util.List; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recycler_view); //๋ ์ด์์ ๋งค๋์ ๋ก LinearLayoutManager๋ฅผ ์ค์ RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(this); recyclerView.setLayoutManager(layoutManager); //ํ์ํ ์์ ๋ฐ์ดํฐ List<CardItem> dataList = new ArrayList<>(); // dataList.add(new CardItem(title, contents)); dataList.add(new CardItem("์ด๊ฒ์ ์ฒซ๋ฒ์งธ ์์ดํ ", "์๋๋ก์ด๋ ๋ณด์ด๋ผ๊ณ ํฉ๋๋ค")); dataList.add(new CardItem("์ด๊ฒ์ ๋๋ฒ์งธ ์์ดํ ", "๋ ์ค ์ ๋ ฅ\n๋ ์ค ์ ๋๋ค")); dataList.add(new CardItem("์ด๊ฒ์ ์ธ๋ฒ์งธ ์์ดํ ", "์ธ์ค\n๋๋ฒ์งธ ์ค\n์ธ๋ฒ์งธ ์ค")); dataList.add(new CardItem("์ด๊ฒ์ ๋ค๋ฒ์งธ ์์ดํ ", "์ ๋๋ค์!")); //์ด๋ํฐ ์ค์ MyRecyclerAdapter adapter = new MyRecyclerAdapter(dataList); recyclerView.setAdapter(adapter); } }
-
๋ ์ด์์ ๋งค๋์ ์ฝ๋ ์ ๋ฆฌ
-
LinearLayoutManager
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this); linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL); recyclerView.setLayoutManager(linearLayoutManager);
-
GridLayoutManager
GridLayoutManager gridLayoutManager = new GridLayoutManager(this, 2); gridLayoutManager.setOrientation(LinearLayoutManager.VERTICAL); recyclerView.setLayoutManager(gridLayoutManager);
-
StaggeredGridLayoutManager
StaggeredGridLayoutManager layoutManager = new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL); recyclerView.setLayoutManager(gridLayoutManager);
-
-
-
RecyclerView ์์ดํ ์ ํด๋ฆญ ๋ฆฌ์ค๋๋ฅผ ์ ๊ณตํ์ง ์๋๋ค
=>๋ชจ๋ ์ด๋ฒคํธ์ ๋ํ ์ฒ๋ฆฌ๋ฅผ ๊ฐ๋ฐ์๊ฐ ์ง์ ๊ตฌํํด์ผํจ
public class MyRecyclerAdapter extends RecyclerView.Adapter<MyRecyclerAdapter.ViewHolder>{
private final List<CardItem> mDataList;
private MyRecyclerViewClickListener mListener;
... ์๋ต ...
public void setOnClickListener(MyRecyclerViewClickListener listener){
mListener = listener;
}
public interface MyRecyclerViewClickListener {
// ์์ดํ
์ ์ฒด ๋ถ๋ถ์ ํด๋ฆญ
void onItemClicked(int position);
// share ๋ฒํผ ํด๋ฆญ
void onShareButtonClicked(int position);
// Learn More ๋ฒํผ ํด๋ฆญ
void onLearnMoreButtonClicked(int position);
}
}
- onBindViewHolder() ๋ฉ์๋์์ ํด๋ฆญ์ด ๋ฐ์ํ๋ ๊ณณ์ MyRecyclerViewClickListener์ ์ฐ๊ฒฐ
public class MyRecyclerAdapter extends RecyclerView.Adapter<MyRecyclerAdapter.ViewHolder> {
... ์๋ต ...
// ๋ทฐ ํ๋์ ๋ฐ์ดํฐ๋ฅผ ์ค์ ํ๋ ๋ถ๋ถ
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
CardItem item = mDataList.get(position);
holder.title.setText(item.getTitle());
holder.contents.setText(item.getContents());
// ํด๋ฆญ ์ด๋ฒคํธ
if (mListener != null) {
// ํ์ฌ ์์น
final int pos = position;
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mListener.onItemClicked(pos);
}
});
holder.share.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v) {
mListener.onShareButtonClicked(pos);
}
});
holder.more.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mListener.onLearnMoreButtonClicked(pos);
}
});
}
}
... ์๋ต ...
// ๊ฐ๊ฐ์ ์์ดํ
์ ๋ ํผ๋ฐ์ค๋ฅผ ์ ์ฅํ ๋ทฐ ํ๋ ํด๋์ค
// ๋ฐ๋์ RecyclerView.ViewHolder๋ฅผ ์์ํด์ผ ํจ
public static class ViewHolder extends RecyclerView.ViewHolder {
TextView title;
TextView contents;
Button share;
Button more;
public ViewHolder(View itemview) {
super(itemview);
title = itemview.findViewById(R.id.title_text);
contents = itemview.findViewById(R.id.contents_text);
share = (Button) itemview.findViewById(R.id.share_button);
more = (Button) itemview.findViewById(R.id.more_button);
}
}
... ์๋ต ...
}
- ์กํฐ๋นํฐ์์ ๋ฆฌ์ค๋ ๊ตฌํ, ๋ฉ์๋ ์ฌ์ ์
public class MainActivity extends AppCompatActivity implements MyRecyclerAdapter.MyRecyclerViewClickListener{
private static final String TAG = MainActivity.class.getSimpleName();
@Override
protected void onCreate(Bundle savedInstanceState) {
... ์๋ต ...
// ์ด๋ํฐ ์ค์
MyRecyclerAdapter adapter = new MyRecyclerAdapter(dataList);
adapter.setOnClickListener(this);
recyclerView.setAdapter(adapter);
}
@Override
public void onItemClicked(int position) {
Log.d(TAG, "onItemClicked: " + position);
}
@Override
public void onShareButtonClicked(int position) {
Log.d(TAG, "onShareButtonClicked: " + position);
}
@Override
public void onLearnMoreButtonClicked(int position) {
Log.d(TAG, "onLearnMoreButtonClicked: " + position);
}
}
- ์ฝ๋ฐฑ์ด ์ ๋์ํ๋์ง ํ์ธ
-
์ด๋ํฐ๋ทฐ์์๋ ๋ฐ์ดํฐ๊ฐ ๋ณ๊ฒฝ๋์์ ๋ ์ด๋ฅผ ๋ฐ์ํ๊ธฐ ์ํด notifyDataSetChanged() ๋ฉ์๋๋ฅผ ํธ์ถํ์ฌ ๋ฐ์ดํฐ ๋ณ๊ฒฝ์ ํต์งํ๊ณ ๋ทฐ๊ฐ ์์ ๋๋๋ก ํจ => ํญ์ ์ ์ฒด ํญ๋ชฉ์ ์๋ก ๋ก๋
-
RecyclerView์ ์ด๋ํฐ๋ ๊ฐ ์ํฉ์ ๋ง๊ฒ ์ฌ์ฉํ ์ ์๋ ํต์ง ๋ฉ์๋ ์ ๊ณต
- notifyItemInserted(int position) : position ์์น์ ์์ดํ ์ด ์ฝ์ ๋ ๊ฒ์ ํต์ง
- notifyItemRemoved(int position) : position ์์น์ ์์ดํ ์ด ์ญ์ ๋ ๊ฒ์ ํต์ง
public class MyRecyclerAdapter extends RecyclerView.Adapter<MyRecyclerAdapter.ViewHolder> { ... ์๋ต ... public void removeItem(int position){ mDataList.remove(position); notifyItemRemoved(position); notifyItemRangeChanged(position, mDataList.size()); } public void addItem(int position, CardView item){ mDataList.add(position, item); notifyItemInserted(position); notifyItemRangeChanged(position, mDataList.size()); } }
- ์ ๋ฉ์๋๋ค์ ์์ดํ ์ด ์ถ๊ฐ, ์ญ์ ๋๋ฉด์ ๊ธฐ๋ณธ์ ์ผ๋ก ์ ๋๋ฉ์ด์ ์ด ์ง์๋จ
- notifyItemRangeChanged(position, mDataList.size()) ๋ฉ์๋๋ฅผ ํธ์ถํด์ผ ์ ๋๋ก ์๋
- ์ด ๋ฉ์๋๋ ์ฒซ ๋ฒ์งธ ์ธ์๋ถํฐ ๋ ๋ฒ์งธ ์ธ์ ์ฌ์ด์ ๋ฐ์ดํฐ๊ฐ ๋ณ๊ฒฝ๋์์์ ํต์ง
- ์ด์ ๋ง๊ฒ ์ ๋๋ก ๋์ํ๋๋ก ํจ
-
ItemAnimator์ ItemDecoration
-
RecyclerView๋ ์ ๋๋ฉ์ด์ ๋ชจ์์ ๊พธ๋ฐ ์ ์๋ ๋ฐฉ๋ฒ์ ์ ๊ณต
-
ItemAnimator
- ์์ดํ ์ด ์ถ๊ฐ, ์ญ์ , ์ ๋ ฌ๋ ๋์ ์ ๋๋ฉ์ด์ ์ ์ ์ํ ์ ์๋ ํด๋์ค
- ์ด ํด๋์ค๋ฅผ ์์ํ๋ฉด ์ฌ๋ฌ ๊ฐ์ง ์ถ์ ๋ฉ์๋๋ฅผ ๊ตฌํํ์ฌ ์ ๋๋ฉ์ด์ ๊ตฌ์ฑ ๊ฐ๋ฅ
-
ItemDecoration
-
์์ดํ ์ ๋ชจ์์ ๊พธ๋ฐ ์ ์๋ ํด๋์ค
DividerItemDecoration decoration = new DividerItemDecoration(this, layoutManager.getOrientation()); recyclerView.addItemDecoration(decoration);
-
-
DefaultItemAnimator
-
RecyclerView๋ ํน๋ณํ ์ค์ ์ด ์์ผ๋ฉด ๋ฏธ๋ฆฌ์ ์๋ DefaultItemAnimator๊ฐ ์ ์ฉ๋จ
-
์ด ํด๋์ค๋ ์ถ๊ฐ, ์ญ์ , ์ ๋ ฌ ์ ๋๋ฉ์ด์ ์ ์คํ ์๋๋ฅผ ์กฐ์ ํ ์ ์์
DefaultItemAnimator animator = new DefaultItemAnimator(); animator.setAddDuration(1000); animator.setremoveDuration(1000); animator.setMoveDuration(1000); animator.setChangeDuration(1000); recyclerView.setItemAnimator(animator);
-
-
-