반응형

이번 시간에도 안드로이드 스튜디오에서(with코틀린) 가장 많이 활용되는 기능 중 하나인 RecyclerView를 연습해 볼 텐데요, 여기에 Card View 기능을 활용해 보려고 합니다.


1. New Project → Empty Views Activity를 선택하고  Title을 정해주세요.  여기서는 RecycleView4 라고 하였습니다.

프로젝트의 구성은 아래와 같습니다. 

실행결과는 아래와 같아요.

 

화면을 위아래로 스크롤 해서 여러 가지 메뉴를 보여주도록 했는데요, View를 재활용 보여줄 때 "Card View" 기능을 사용해서 보여주면 좀 더 입체적으로 보여줄 수 있어서 잘 활용하면 좋습니다.

1. activity_main.xml  작성하기

<코드>

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/tv_title"
        android:layout_width="wrap_content"
        android:layout_height="0dp"
        android:layout_marginTop="32dp"
        android:text="Korean Delicious Food"
        android:textColor="#FF5722"
        android:textSize="20dp"
        android:textStyle="bold"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/rv_recyclerView"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_marginStart="8dp"
        android:layout_marginTop="16dp"
        android:layout_marginEnd="8dp"
        android:layout_marginBottom="8dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/tv_title"
         />
</androidx.constraintlayout.widget.ConstraintLayout>

 

2.  food_item.xml  작성하기

아래를 참고해서 레이아웃에서 cardview를 끌어다 놓고 작성을 해 주세요.

<코드>

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">
    <androidx.cardview.widget.CardView
        android:id="@+id/cardView"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginHorizontal="10dp"
        android:layout_marginVertical="6dp"
        android:layout_marginStart="10dp"
        android:layout_marginTop="8dp"
        android:layout_marginEnd="10dp"
        app:cardCornerRadius="20dp"
        app:cardElevation="8dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">
        <androidx.constraintlayout.widget.ConstraintLayout
            android:id="@+id/constraintLayout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
            <ImageView
                android:id="@+id/iV_foodImage"
                android:layout_width="100dp"
                android:layout_height="100dp"
                android:scaleType="fitXY"
                android:src="@drawable/bibimbab_01"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toTopOf="parent" />
            <TextView
                android:id="@+id/tv_foodName"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Bibimbap\n(비빔밥)"
                android:textAlignment="center"
                android:textSize="25dp"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintHorizontal_bias="0.52"
                app:layout_constraintStart_toEndOf="@+id/iV_foodImage"
                app:layout_constraintTop_toTopOf="parent" />
        </androidx.constraintlayout.widget.ConstraintLayout>
    </androidx.cardview.widget.CardView>

</androidx.constraintlayout.widget.ConstraintLayout>

 

3.  Food.kt  클래스 작성하기

<코드>

package com.example.recyclerview4

import android.os.Parcel
import android.os.Parcelable

data class Food(val image:Int, val name:String) : Parcelable {
    constructor(parcel: Parcel) : this(parcel.readInt(), parcel.readString()!!) {
    }
    override fun describeContents(): Int {
        return 0
    }
    override fun writeToParcel(parcel: Parcel, flags: Int) {
        parcel.writeInt(image)
        parcel.writeString(name)
    }
    companion object CREATOR : Parcelable.Creator<Food> {
        override fun createFromParcel(parcel: Parcel): Food {
            return Food(parcel)
        }
        override fun newArray(size: Int): Array<Food?> {
            return arrayOfNulls(size)
        }
    }
}

 

4.  FoodAdapter.kt  작성하기

아래를 참고해 Food Adapter를 만들어 줍니다.

<코드>

package com.example.recyclerview4

import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.AdapterView.OnItemClickListener
import android.widget.ImageView
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView

class FoodAdapter(private val foodList:ArrayList<Food>)
    : RecyclerView.Adapter<FoodAdapter.FoodViewHolder>() {
        var onItemClick : ((Food) -> Unit)? = null

        class FoodViewHolder(itemView:View) : RecyclerView.ViewHolder(itemView) {
            val imageView : ImageView = itemView.findViewById(R.id.iV_foodImage)
            val textView : TextView = itemView.findViewById(R.id.tv_foodName)
        }
        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FoodViewHolder {
            val view = LayoutInflater.from(parent.context).inflate(R.layout.food_item, parent, false)
            return FoodViewHolder(view)
        }
        override fun getItemCount(): Int {
            return foodList.size
        }
        override fun onBindViewHolder(holder: FoodViewHolder, position: Int) {
            val food = foodList[position]
            holder.imageView.setImageResource(food.image)
            holder.textView.text = food.name
            holder.itemView.setOnClickListener {
                onItemClick?.invoke(food)
            }
        }
}

 

5.  MainActivity.kt  작성하기

아래를 참고해 Main Activity를 만들어 줍니다.
먼저 binding 기능을 사용하기 위해, build.gradle.kts(Module:app) 그래들 설정에 아래처럼 바인딩 기능 사용을 추가해 주세요.

viewBinding.isEnabled = true

 

<코드>

package com.example.recyclerview4

import android.content.Intent
import android.os.Bundle
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.example.recyclerview4.databinding.ActivityMainBinding

class MainActivity : AppCompatActivity() {
    private lateinit var recyclerView: RecyclerView
    private lateinit var foodList: ArrayList<Food>
    private lateinit var foodAdapter: FoodAdapter
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        enableEdgeToEdge()
        val binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)
        recyclerView = binding.rvRecyclerView
        recyclerView.setHasFixedSize(true)
        recyclerView.layoutManager = LinearLayoutManager(this)
        foodList = ArrayList()
        foodList.add(Food(R.drawable.bibimbab_01, "Bi-bim-bap\n(비빔밥)"))
        foodList.add(Food(R.drawable.samgyeopsal_02, "Sam-gyeop-sal\n(삼겹살)"))
        foodList.add(Food(R.drawable.galbitang_03, "Gal-bi-tang\n(갈비탕)"))
        foodList.add(Food(R.drawable.tteokguk_04, "tteok-guk\n(떡국)"))
        foodList.add(Food(R.drawable.tteokbokki_05, "tteok-bok-kki\n(떡볶이)"))
        foodList.add(Food(R.drawable.sundubujjigae_06, "Sun-dubu-jjigae\n(순두부 찌개)"))
        foodList.add(Food(R.drawable.koreanfc_07, "Korean-Fried-Chicken\n(한국식 프라이 치킨)"))
        foodList.add(Food(R.drawable.naengmyeon_09, "naeng-myeon\n(냉면)"))
        foodList.add(Food(R.drawable.doenjangjjigae_10, "Doen-jang-jjigae\n(된장찌개)"))
        foodList.add(Food(R.drawable.bulgogi_11, "Bul-go-gi\n(불고기)"))
        foodList.add(Food(R.drawable.kimchijeon_12, "Kimchi-jeon\n(김치전)"))
        foodAdapter = FoodAdapter(foodList)
        recyclerView.adapter = foodAdapter
    }
}

 

여기까지만 하면 기본적으로 RecyclerView 기능을 사용해서 보여줄 수 있게 되는데요, 
여기서 한 가지 기능을 더 추가해 볼게요,  화면을 스크롤하면서 원하는 음식(이미지)카드를 터치하면, 해당 음식에 대해 디테일하게 정보를 보여주는 View를 추가해 볼게요. 

6.  activity_detailed.xml  작성하기 

아래를 참고해 Main Activity를 만들어 줍니다.

res >> layout 폴더에서 마우스 우클릭 해서 New >> Activity >> Empty Views Activity를 클릭합니다. 

아래처럼 Activity Name에  "DetailedActivity" 를 입력하면 "DetailedActivity.kt"파일과 함께  그 아래에 activity_detailed.xml 파일도 함께 자동 생성됩니다. 

 

7.  activity_detailed  작성하기 

아래처럼 xml 코드를 작성해 주세요

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".DetailedActivity">

    <ImageView
        android:id="@+id/iv_Detailed"
        android:layout_width="0dp"
        android:layout_height="250dp"
        android:scaleType="fitXY"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:srcCompat="@drawable/bibimbab_01" />

    <TextView
        android:id="@+id/tv_Detailed"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="173dp"
        android:layout_marginEnd="180dp"
        android:gravity="center"
        android:text="TextView"
        android:textSize="24sp"
        android:textStyle="bold"
        android:textColor="@color/black"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/iv_Detailed" />
</androidx.constraintlayout.widget.ConstraintLayout>

8.  DetailedActivity.kt  작성하기 

아래처럼 코드를 작성해 주세요. (binding 기능으로 사용하였고 기존 기능은 주석처리해 놓았으니 비교해 보세요)

package com.example.recyclerview4

import android.os.Bundle
import android.view.LayoutInflater
import android.widget.ImageView
import android.widget.TextView
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import com.example.recyclerview4.databinding.ActivityDetailedBinding

class DetailedActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        enableEdgeToEdge()
        val binding = ActivityDetailedBinding.inflate(layoutInflater)
//        setContentView(R.layout.activity_detailed)
        setContentView(binding.root)
        val food = intent.getParcelableExtra<Food>("food")
        if (food != null) {
//            val textView : TextView = findViewById(R.id.tv_Detailed)
//            val imageView : ImageView = findViewById(R.id.iv_Detailed)
            binding.tvDetailed.text = food.name
            binding.ivDetailed.setImageResource(food.image)
        }
    }
}

마지막으로 MainActivity.kt 코드 끝에 아래와 같은 코드를 추가해 주세요. 

foodAdapter.onItemClick = {
    val intent = Intent(this, DetailedActivity::class.java)
    intent.putExtra("food",it)
    startActivity(intent)
}

MainActivity.kt 의 전체 완성된 코드는 아래와 같아요.

package com.example.recyclerview4

import android.content.Intent
import android.os.Bundle
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.example.recyclerview4.databinding.ActivityMainBinding
class MainActivity : AppCompatActivity() {
    private lateinit var recyclerView: RecyclerView
    private lateinit var foodList: ArrayList<Food>
    private lateinit var foodAdapter: FoodAdapter
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        enableEdgeToEdge()
        val binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)
        recyclerView = binding.rvRecyclerView
        recyclerView.setHasFixedSize(true)
        recyclerView.layoutManager = LinearLayoutManager(this)
        foodList = ArrayList()
        foodList.add(Food(R.drawable.bibimbab_01, "Bi-bim-bap\n(비빔밥)"))
        foodList.add(Food(R.drawable.samgyeopsal_02, "Sam-gyeop-sal\n(삼겹살)"))
        foodList.add(Food(R.drawable.galbitang_03, "Gal-bi-tang\n(갈비탕)"))
        foodList.add(Food(R.drawable.tteokguk_04, "tteok-guk\n(떡국)"))
        foodList.add(Food(R.drawable.tteokbokki_05, "tteok-bok-kki\n(떡볶이)"))
        foodList.add(Food(R.drawable.sundubujjigae_06, "Sun-dubu-jjigae\n(순두부 찌개)"))
        foodList.add(Food(R.drawable.koreanfc_07, "Korean-Fried-Chicken\n(한국식 프라이 치킨)"))
        foodList.add(Food(R.drawable.naengmyeon_09, "naeng-myeon\n(냉면)"))
        foodList.add(Food(R.drawable.doenjangjjigae_10, "Doen-jang-jjigae\n(된장찌개)"))
        foodList.add(Food(R.drawable.bulgogi_11, "Bul-go-gi\n(불고기)"))
        foodList.add(Food(R.drawable.kimchijeon_12, "Kimchi-jeon\n(김치전)"))
        foodAdapter = FoodAdapter(foodList)
        recyclerView.adapter = foodAdapter
        foodAdapter.onItemClick = {
            val intent = Intent(this, DetailedActivity::class.java)
            intent.putExtra("food",it)
            startActivity(intent)
        }
    }
}

그럼, 앱을 실행하고 원하는 음식 이미지를 터치하면, 아래처럼 디테일 뷰를 볼 수 있습니다. 
아래 이미지에서 갈비탕 이미지를 터치하면, 상세 페이지를 볼 수 있으며, 실제로 추가적인 내용을 넣어 주면 됩니다.

 

이상으로 RecyclerView를 사용하면서 CardView 기능을 활용해 보는 시간을 가져봤습니다.

그럼, 오늘도 즐거운 하루 되세요~

반응형