오늘이라도

[Android] 22. 리사이클러 뷰(Recycler View) ① : 리사이클러 뷰, 어댑터 작성, 클릭 이벤트 추가 / ② : 클릭 이벤트 인터페이스 작성, 버튼 눌러서 항목 추가 본문

취업성공패키지 SW 개발자 교육/Android

[Android] 22. 리사이클러 뷰(Recycler View) ① : 리사이클러 뷰, 어댑터 작성, 클릭 이벤트 추가 / ② : 클릭 이벤트 인터페이스 작성, 버튼 눌러서 항목 추가

upcake_ 2020. 6. 4. 11:26
반응형

https://github.com/upcake/Class_Examples

교육 중에 작성한 예제들은 깃허브에 올려두고 있습니다. 

gif 파일은 클릭해서 보는 것이 정확합니다.


 - 리사이클러 뷰(Recycler View) ① : 리사이클러 뷰, 어댑터 작성, 클릭 이벤트 추가 -

▲리사이클러 뷰 ① 작동 화면

 

▼activity_main.xml

<?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">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recyclerView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

    </androidx.recyclerview.widget.RecyclerView>
</LinearLayout>

 

▼MainActivity.java

package com.example.my29_recylerview;

import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import android.os.Bundle;

public class MainActivity extends AppCompatActivity {

    RecyclerView recyclerView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        recyclerView = findViewById(R.id.recyclerView);

        //Ctrl + p를 누르면 받아야할 매개 변수가 무엇인지 보여준다.
        LinearLayoutManager layoutManager = new LinearLayoutManager(this, RecyclerView.VERTICAL, false);
        recyclerView.setLayoutManager(layoutManager);

        PersonAdapter adapter = new PersonAdapter();
        adapter.addItem(new PersonDTO("가수1", "010-1111-1111", R.drawable.singer1));
        adapter.addItem(new PersonDTO("가수2", "010-2222-2222", R.drawable.singer2));
        adapter.addItem(new PersonDTO("가수3", "010-3333-3333", R.drawable.singer3));
        adapter.addItem(new PersonDTO("가수4", "010-4444-4444", R.drawable.singer4));
        adapter.addItem(new PersonDTO("가수5", "010-5555-5555", R.drawable.singer5));

        recyclerView.setAdapter(adapter);
    }
}

 

▼PersonDTO.java

package com.example.my29_recylerview;

public class PersonDTO {
    String name;
    String phoneNum;
    int resId;

    public PersonDTO() {
    }

    public PersonDTO(String name, String phoneNum, int resId) {
        this.name = name;
        this.phoneNum = phoneNum;
        this.resId = resId;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPhoneNum() {
        return phoneNum;
    }

    public void setPhoneNum(String phoneNum) {
        this.phoneNum = phoneNum;
    }

    public int getResId() {
        return resId;
    }

    public void setResId(int resId) {
        this.resId = resId;
    }
}

 

▼person_item.xml

<?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="wrap_content"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    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">
        <!--CornerRadius : 모서리 깎기-->
        <!--cardElevation : 부유 효과-->
        
        <LinearLayout
            android:id="@+id/parentLayout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal" >

            <ImageView
                android:id="@+id/imageView"
                android:layout_width="100dp"
                android:layout_height="100dp"
                android:padding="5dp"
                android:src="@drawable/singer1" />

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="100dp"
                android:orientation="vertical"
                android:layout_margin="5dp">

                <TextView
                    android:id="@+id/tvName"
                    android:layout_width="match_parent"
                    android:layout_height="50dp"
                    android:text="이름"
                    android:textSize="30sp" />
                <!--dp는 레이아웃의 크기를 지정할 때, sp는 텍스트의 크기를 지정할 때 사용한다.-->
                <!--화면에서 언제나 똑같은 크기의 글자를 보여주고자할때는 dp를 텍스트에 사용해도 된다.-->

                <TextView
                    android:id="@+id/tvPhoneNum"
                    android:layout_width="match_parent"
                    android:layout_height="50dp"
                    android:text="전화번호"
                    android:textSize="25sp" />
            </LinearLayout>
        </LinearLayout>
    </androidx.cardview.widget.CardView>
</LinearLayout>

 

▼PersonAdapter.java

package com.example.my29_recylerview;

import android.util.Log;
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.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;

import java.util.ArrayList;

//리사이클러뷰 어댑터를 상속받는다.
public class PersonAdapter extends RecyclerView.Adapter<PersonAdapter.ViewHolder> {
    ArrayList<PersonDTO> itemList = new ArrayList<>();
    private static final String TAG = "MainPersonAdapter";

    //뷰홀더가 만들어질때 작동하는 메서드
    //화면을 인플레이트하고 인플레이트된 화면을 리턴한다.
    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        LayoutInflater inflater = LayoutInflater.from(parent.getContext());
        View itemView = inflater.inflate(R.layout.person_item, parent, false);
        return new ViewHolder(itemView);
    }

    //뷰홀더가 생길때 dto를 뷰홀더에 넘겨준다.
    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, final int position) {
        Log.d(TAG, "onBindViewHolder: position ▶ " + position);
        PersonDTO item = itemList.get(position);
        holder.setItem(item);

        //이름 텍스트뷰 클릭했을 때 로그캣에 이름 출력
        holder.tvName.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.d(TAG, "onClick: " + itemList.get(position).getName());
            }
        });

        //레이아웃 내부의 아무곳이나 클릭했을 때 로그캣에 전화번호 출력
        holder.parentLayout.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.d(TAG, "onClick: " + itemList.get(position).phoneNum);
            }
        });
    }

    //아이템이 몇 개 들어갔는지 세는 메서드
    @Override
    public int getItemCount() {
        return itemList.size();
    }

    public void addItem(PersonDTO item) {
        itemList.add(item);
    }

    //리사이클러뷰 뷰홀더를 상속받는다.
    public static class ViewHolder extends RecyclerView.ViewHolder {
        TextView tvName, tvPhoneNum;
        ImageView imageView;
        LinearLayout parentLayout;

        //생성자를 만든다.
        //여기서 itemView는 화면에 표시되는 각각의 person_item.xml 뷰이다
        public ViewHolder(@NonNull View itemView) {
            super(itemView);

            tvName = itemView.findViewById(R.id.tvName);
            tvPhoneNum = itemView.findViewById(R.id.tvPhoneNum);
            imageView = itemView.findViewById(R.id.imageView);
            parentLayout = itemView.findViewById(R.id.parentLayout);
        }

        public void setItem(PersonDTO item) {
            tvName.setText(item.getName());
            tvPhoneNum.setText(item.getPhoneNum());
            imageView.setImageResource(item.getResId());
        }
    }
}

 

 

 - 리사이클러 뷰(Recycler View) ② : 클릭 이벤트 인터페이스 작성, 버튼 눌러서 항목 추가 -

▲리사이클러 뷰 ② 작동 화면

DTO와 person_item.xml은 ① 코드를 같이 사용한다.

▼activity_main.xml

<?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">

    <Button
        android:id="@+id/button1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="추가"
        android:textSize="24sp" />

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recyclerView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

    </androidx.recyclerview.widget.RecyclerView>
</LinearLayout>

 

▼MainActivity.java

package com.example.my30_recylerview2;

import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import android.app.Person;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;

public class MainActivity extends AppCompatActivity {
    private static final String TAG = "MainActivity";

    RecyclerView recyclerView;
    Button button1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        recyclerView = findViewById(R.id.recyclerView);

        //Ctrl + p를 누르면 받아야할 매개 변수가 무엇인지 보여준다.
        LinearLayoutManager layoutManager = new LinearLayoutManager(this, RecyclerView.VERTICAL, false);
        recyclerView.setLayoutManager(layoutManager);

        final PersonAdapter adapter = new PersonAdapter();
        adapter.addItem(new PersonDTO("가수1", "010-1111-1111", R.drawable.singer1));
        adapter.addItem(new PersonDTO("가수2", "010-2222-2222", R.drawable.singer2));
        adapter.addItem(new PersonDTO("가수3", "010-3333-3333", R.drawable.singer3));
        adapter.addItem(new PersonDTO("가수4", "010-4444-4444", R.drawable.singer4));
        adapter.addItem(new PersonDTO("가수5", "010-5555-5555", R.drawable.singer5));

        recyclerView.setAdapter(adapter);

        adapter.setOnItemClickListener(new OnPersonDTOItemClickListener() {
            @Override
            public void onItemClick(PersonAdapter.ViewHolder holderm, View view, int position) {
                PersonDTO item = adapter.getItem(position);

                Log.d(TAG, "onItemClick: " + item.getName());
            }
        });

        button1 = findViewById(R.id.button1);
        button1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                PersonDTO item = new PersonDTO("가수6", "010-6666-6666", R.mipmap.ic_launcher);
                adapter.addItem(item);

                adapter.notifyDataSetChanged();
            }
        });
    }
}

 

▼PersonAdapter.java

package com.example.my30_recylerview2;

import android.util.Log;
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.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;

import java.util.ArrayList;

//리사이클러뷰 어댑터를 상속받는다.
public class PersonAdapter extends RecyclerView.Adapter<PersonAdapter.ViewHolder> implements OnPersonDTOItemClickListener{
    ArrayList<PersonDTO> itemList = new ArrayList<>();
    private static final String TAG = "MainPersonAdapter";
    OnPersonDTOItemClickListener listener;

    //뷰홀더가 만들어질때 작동하는 메서드
    //화면을 인플레이트하고 인플레이트된 화면을 리턴한다.
    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        LayoutInflater inflater = LayoutInflater.from(parent.getContext());
        View itemView = inflater.inflate(R.layout.person_item, parent, false);
        return new ViewHolder(itemView, listener);
    }

    //뷰홀더가 생길때 dto를 뷰홀더에 넘겨준다.
    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, final int position) {
        Log.d(TAG, "onBindViewHolder: position ▶ " + position);
        PersonDTO item = itemList.get(position);
        holder.setItem(item);
    }

    //아이템이 몇 개 들어갔는지 세는 메서드
    @Override
    public int getItemCount() {
        return itemList.size();
    }

    //리스트에 DTO를 추가하는 메서드
    public void addItem(PersonDTO item) {
        itemList.add(item);
    }

    //리스트의 해당 인덱스의 DTO 객체를 반환하는 메서드
    public PersonDTO getItem(int position) {
        return itemList.get(position);
    }

    public void setOnItemClickListener(OnPersonDTOItemClickListener listener) {
        this.listener = listener;
    }

    @Override
    public void onItemClick(ViewHolder holderm, View view, int position) {
        if(listener != null){
            listener.onItemClick(holderm, view, position);
        }
    }

    //리사이클러뷰 뷰홀더를 상속받는다.
    public static class ViewHolder extends RecyclerView.ViewHolder {
        TextView tvName, tvPhoneNum;
        ImageView imageView;

        //생성자를 만든다.
        //여기서 itemView는 화면에 표시되는 각각의 person_item.xml 뷰이다
        public ViewHolder(@NonNull View itemView, final OnPersonDTOItemClickListener listener) {
            super(itemView);

            tvName = itemView.findViewById(R.id.tvName);
            tvPhoneNum = itemView.findViewById(R.id.tvPhoneNum);
            imageView = itemView.findViewById(R.id.imageView);

           itemView.setOnClickListener(new View.OnClickListener() {
               @Override
               public void onClick(View view) {
                   int position = getAdapterPosition();
                   if(listener != null) {
                       listener.onItemClick(ViewHolder.this, view, position);
                   }
               }
           });
        }

        public void setItem(PersonDTO item) {
            tvName.setText(item.getName());
            tvPhoneNum.setText(item.getPhoneNum());
            imageView.setImageResource(item.getResId());
        }
    }
}

 

▼OnPersonDTOItemClickListener

package com.example.my30_recylerview2;

import android.view.View;

public interface OnPersonDTOItemClickListener {
    public void onItemClick(PersonAdapter.ViewHolder holderm, View view, int position);
}
반응형