RecyclerView를 이용해서 list 만들기
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:id="@+id/layout1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<EditText
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:id="@+id/editText"
android:hint="이름" />
<EditText
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:id="@+id/editText2"
android:hint="전화번호" />
</LinearLayout>
<LinearLayout
android:id="@+id/layout2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/editText3"
android:hint="생년월일" />
</LinearLayout>
<RelativeLayout
android:id="@+id/layout3"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:text="추가"
android:id="@+id/button" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignBaseline="@+id/button"
android:layout_marginRight="14dp"
android:text="0명"
android:textColor="#000000"
android:textSize="14dp"
android:id="@+id/textView" />
</RelativeLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
activity_main.xml
xml에 RecyclerView를 추가하면 item 들이 가상으로 보인다. 각 item을 위한 class를 만들어서 그 class를 ArrayList에 담아서 관리해야한다.
그 class 를 만들어보자.
public class Person {
String name;
String mobile;
String birth;
int ResId;
public Person(String name, String mobile,String birth,int ResId) {
this.name = name;
this.mobile = mobile;
this.ResId = ResId;
this.birth = birth;
}
public String getBirth() {
return birth;
}
public void setBirth(String birth) {
this.birth = birth;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getMobile() {
return mobile;
}
public void setMobile(String mobile) {
this.mobile = mobile;
}
public int getResId() {
return ResId;
}
public void setResId(int resId) {
ResId = resId;
}
}
Person.java
연락처 하나를 이 Person class 에 정의한다. (한 item을 위한 data 라고 생각하면 된다.)
data를 담아두기 위한 목적이니 getter, setter 를 추가한다.
이제 Person 에 data를 넣을 수 있고, 그 data는 adapter에 넣어야 한다.
RecyclerView 는 선택 위젯이고 눈에 보이는 모양을 담당한다.
실제 데이터 관리는 adapter를 사용한다.
adapter를 만들어보자.
public class PersonAdapter {
static class ViewHolder extends RecyclerView.ViewHolder{
TextView textView1;
TextView textView2;
TextView textView3;
ImageView imageView;
public ViewHolder(View itemView,final OnPersonItemClickListener listener) {
super(itemView);
textView1 = itemView.findViewById(R.id.textView1);
textView2 = itemView.findViewById(R.id.textView2);
textView3 = itemView.findViewById(R.id.textView3);
imageView = itemView.findViewById(R.id.imageView);
public void setItem(Person item){
textView1.setText(item.getName());
textView2.setText(item.getBirth());
textView3.setText(item.getMobile());
imageView.setImageResource(item.getResId());
}
}
}
personAdapter.java
RecyclerView.ViewHolder 를 상속한 ViewHolder 클래스를 만들었다. ViewHolder는 각 item을 위한 뷰를 담는 역할이다. 재사용이 가능하다.
ViewHolder 생성자 함수도 만들었다. 이 생성자에는 View 객체가 전달되고, 전달 받은 객체를 부모 클래스의 변수에 담아두게 되는데 생성자 안에서 super() 메서드를 호출하면 된다.
그리고 방금 만든 Person 데이터를 View 에 보여주는 역할을 하는 setItem 메서드를 만들었다.
public class PersonAdapter extends RecyclerView.Adapter<PersonAdapter.ViewHolder>{
ArrayList<Person> items = new ArrayList<>();
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(parent.getContext()); //LayoutInflater 객체 참조.
View itemView = inflater.inflate(R.layout.person_item,parent,false); //각 item을 위한 View를 만들었다.
return new ViewHolder(itemView,this); //우리가 만든 ViewHolder에 itemView를 전달한다.
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
Person item = items.get(position);
holder.setItem(item);
}
@Override
public int getItemCount() {
return items.size();
}
...
static class ViewHolder extends RecyclerView.ViewHolder{
TextView textView1;
TextView textView2;
TextView textView3;
ImageView imageView;
public ViewHolder(View itemView,final OnPersonItemClickListener listener) {
super(itemView);
textView1 = itemView.findViewById(R.id.textView1);
textView2 = itemView.findViewById(R.id.textView2);
textView3 = itemView.findViewById(R.id.textView3);
imageView = itemView.findViewById(R.id.imageView);
}
public void setItem(Person item){
textView1.setText(item.getName());
textView2.setText(item.getBirth());
textView3.setText(item.getMobile());
imageView.setImageResource(item.getResId());
}
}
}
personAdapter.java
- Adapter 는 여러개의 item을 가지고 있으므로 ArrayList를 만들어 data를 넣을 수 있게 했다.
- ViewHoler를 담고있는 Adapter를 상속하도록 RecyclerView.Adapter<PersonAdapter.ViewHolder> 를 상속받았다.
- 필요한 세개의 메소드를 추가했다.
- getItemCount() : items 에 들어있는 개수를 return 받기 위한 함수이다.
- onCreateViewHolder() : ViewHolder 가 생성되는 시점에 자동으로 실행된다. (item 을 위한 layout을 이 안에서 inflation한다. -> inflation 한 View를 ViewHolder에 넣는다. -> 그 ViewHolder를 return한다. -> 하나의 item을 위한 ViewHolder가 만들어져서 return 된다.)
- onBindViewHoler() : 스크롤을 내리거나 올릴 때, 화면에서 벗어나는 ViewHoler를 재사용할 건데, 그 사용했었던 ViewHoler를 parameter로 전달 받는다.
각 View를 위한 layout을 만들자.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardCornerRadius="10dp"
app:cardElevation="5dp"
app:cardUseCompatPadding="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_margin="8dp">
<ImageView
android:id="@+id/imageView"
android:layout_width="80dp"
android:layout_height="80dp"
android:padding="5dp"
app:srcCompat="@drawable/img4" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="5dp">
<TextView
android:id="@+id/textView1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:duplicateParentState="true"
android:text="name"
android:textColor="#009688"
android:textSize="30sp" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentBottom="true"
android:text="birth"
android:textColor="#FF9800"
android:textSize="15sp" />
<TextView
android:id="@+id/textView3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentBottom="true"
android:text="mobile"
android:textColor="#3F51B5"
android:textSize="15sp" />
</RelativeLayout>
</LinearLayout>
</LinearLayout>
</androidx.cardview.widget.CardView>
</LinearLayout>
person_item.xml
public class PersonAdapter extends RecyclerView.Adapter<PersonAdapter.ViewHolder> {
ArrayList<Person> items = new ArrayList<>();
OnPersonItemClickListener listener;
...
public void addItem(Person item){
items.add(item);
}
public void setItems(ArrayList<Person> items){
this.items = items;
}
public Person getItem(int position){
return items.get(position);
}
public void setItem(int position,Person item){
items.set(position,item);
}
@Override
public void onItemClick(ViewHolder holder, View view, int position) {
listener.onItemClick(holder,view,position);
}
public void setOnItemClickListener(OnPersonItemClickListener listener) {
this.listener = listener;
}
static class ViewHolder extends RecyclerView.ViewHolder{
TextView textView1;
TextView textView2;
TextView textView3;
ImageView imageView;
public ViewHolder(View itemView,final OnPersonItemClickListener listener) {
super(itemView);
textView1 = itemView.findViewById(R.id.textView1);
textView2 = itemView.findViewById(R.id.textView2);
textView3 = itemView.findViewById(R.id.textView3);
imageView = itemView.findViewById(R.id.imageView);
itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int position = getAdapterPosition();
listener.onItemClick(ViewHolder.this,v,position);
}
});
}
public void setItem(Person item){
textView1.setText(item.getName());
textView2.setText(item.getBirth());
textView3.setText(item.getMobile());
imageView.setImageResource(item.getResId());
}
}
}
PersonAdapter.java
몇가지 메서드를 추가했다.
- addItem() : Adapter에 Person 객체를 추가하기 위해
- setItems() : ArrayList 를 전체적으로 설정하기 위해
- getItem() : position 번째에 있는 item을 return 하기 위해
- setItem()
이제 MainActivity에 RecyclerView 를 설정해보자.
public class MainActivity extends AppCompatActivity {
EditText editText1;
EditText editText2;
EditText editText3;
TextView textView;
RecyclerView recyclerView;
PersonAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
editText1 = findViewById(R.id.editText);
editText2 = findViewById(R.id.editText2);
editText3 = findViewById(R.id.editText3);
textView = findViewById(R.id.textView);
recyclerView = findViewById(R.id.recyclerView);
LinearLayoutManager layoutManager = new LinearLayoutManager(this,LinearLayoutManager.VERTICAL,false); //RecyclerView 에 레이아웃 매니저 설정
//GridLayoutManager layoutManager = new GridLayoutManager(this,2);
recyclerView.setLayoutManager(layoutManager);
adapter = new PersonAdapter();
adapter.addItem(new Person("피아지","1990-01-01","010-1111-1111",R.drawable.img4)); //실제 Person 객체 넣기
adapter.addItem(new Person("손아지","1990-11-01","010-1111-1234",R.drawable.img4));
recyclerView.setAdapter(adapter);
}
}
MainActivity.java
item을 눌렀을 때 동작하도록 해보자. 버튼을 눌렀을 때 동작할 함수를 약속할 interface를 만들자.
public interface OnPersonItemClickListener {
public void onItemClick(PersonAdapter.ViewHolder holder, View view, int position);
}
OnPersonItemClickListener.java
item이 클릭되면 onItemClick 함수가 호출된다.
ViewHolder에도 item이 클릭되었을 때 기능을 추가해야한다.
public class PersonAdapter extends RecyclerView.Adapter<PersonAdapter.ViewHolder> implements OnPersonItemClickListener{
ArrayList<Person> items = new ArrayList<>();
OnPersonItemClickListener listener;
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
View itemView = inflater.inflate(R.layout.person_item,parent,false);
return new ViewHolder(itemView,this);
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
Person item = items.get(position);
holder.setItem(item);
}
@Override
public int getItemCount() {
return items.size();
}
public void addItem(Person item){
items.add(item);
}
public void setItems(ArrayList<Person> items){
this.items = items;
}
public Person getItem(int position){
return items.get(position);
}
public void setItem(int position,Person item){
items.set(position,item);
}
@Override
public void onItemClick(ViewHolder holder, View view, int position) {
listener.onItemClick(holder,view,position);
}
public void setOnItemClickListener(OnPersonItemClickListener listener) {
this.listener = listener;
}
static class ViewHolder extends RecyclerView.ViewHolder{
TextView textView1;
TextView textView2;
TextView textView3;
ImageView imageView;
public ViewHolder(View itemView,final OnPersonItemClickListener listener) {
super(itemView);
textView1 = itemView.findViewById(R.id.textView1);
textView2 = itemView.findViewById(R.id.textView2);
textView3 = itemView.findViewById(R.id.textView3);
imageView = itemView.findViewById(R.id.imageView);
itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int position = getAdapterPosition();
listener.onItemClick(ViewHolder.this,v,position);
}
});
}
public void setItem(Person item){
textView1.setText(item.getName());
textView2.setText(item.getBirth());
textView3.setText(item.getMobile());
imageView.setImageResource(item.getResId());
}
}
}
personAdapter.java
ViewHoler가 만들어지는 시점에 final OnPersonItemClicklistener listener 를 같이 전달받도록 하자.
그리고 이벤트 처리를 할건데, 이벤트 처리를 listener쪽으로 전달할 것이다.
그리고 OnPersonItemClickListener interface를 상속받아서 onItemClick과 setOnItemClickListener 메소드를 재정의해야한다.
public class MainActivity extends AppCompatActivity {
EditText editText1;
EditText editText2;
EditText editText3;
TextView textView;
RecyclerView recyclerView;
PersonAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
editText1 = findViewById(R.id.editText);
editText2 = findViewById(R.id.editText2);
editText3 = findViewById(R.id.editText3);
textView = findViewById(R.id.textView);
recyclerView = findViewById(R.id.recyclerView);
LinearLayoutManager layoutManager = new LinearLayoutManager(this,LinearLayoutManager.VERTICAL,false);
recyclerView.setLayoutManager(layoutManager);
adapter = new PersonAdapter();
adapter.addItem(new Person("피아지","1990-01-01","010-1111-1111",R.drawable.img4));
adapter.addItem(new Person("손아지","1990-11-01","010-1111-1234",R.drawable.img4));
recyclerView.setAdapter(adapter);
adapter.setOnItemClickListener(new OnPersonItemClickListener() {
@Override
public void onItemClick(PersonAdapter.ViewHolder holder, View view, int position) {
Person item = adapter.getItem(position);
Toast.makeText(getApplicationContext(),"선택정보 : " + item.getName(),Toast.LENGTH_LONG).show();
}
});
Button button = findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
adapter.addItem(new Person(editText1.getText().toString(),editText2.getText().toString(),editText3.getText().toString(),R.drawable.img4));
adapter.notifyDataSetChanged();
recyclerView.setAdapter(adapter);
textView.setText(adapter.getItemCount()+"명");
}
});
textView.setText(adapter.getItemCount()+"명");
}
}
MainActivity.java