Developer Geek

[Android] Custom Binding Adapter Example in Kotlin 본문

안드로이드/Jetpack

[Android] Custom Binding Adapter Example in Kotlin

devGeek 2022. 7. 5. 21:25
반응형
 

[Android] DataBinding 이란

개요 이 DataBinding Tutorial에서는 레이아웃의 구성 요소와 직접 상호 작용하고, 값을 할당하고, Binding Adapter를 사용하여 View 에서 발송되는 이벤트를 처리하는 방법을 다룬다. DataBinding은 Android Jetp..

devgeek.tistory.com

 

[Android] DataBinding 예제

[Android] DataBinding 이란 개요 이 DataBinding Tutorial에서는 레이아웃의 구성 요소와 직접 상호 작용하고, 값을 할당하고, Binding Adapter를 사용하여 View 에서 발송되는 이벤트를 처리하는 방법을 다룬다..

devgeek.tistory.com

 

[Android] Custom Binding Adapter

Custom Binding Adapter 개요 커스텀 바인딩 어댑터를 이용하면 데이터를 바인딩 하기 전에 동작하는 로직을 추가할 수 있다. 일반적으로 커스텀 바인딩 어댑터는 Data Binding Library에서 제공하는 어댑터

devgeek.tistory.com

개요

Custom Binding Adapter를 이용하여, 썸네일을 담당하는 이미지뷰에 이미지를 로드하고 가격을 담당하는 텍스트뷰에 정수를 입력하면 을 추가하여 보여지도록 하는 리스트를 만든다.

실행화면

프로젝트 구조

프로젝트 구조

build.gradle(Module)

  1. CustomBindingAdapter 구현을 위해 kotlin-kapt를 아래와 같이 build.gradle(Module) 파일의 plugins에 추가한다.
    plugins {  
    ...
    id 'kotlin-kapt'  
    }
  2. DataBinding사용을 위해 buildFeatures{ dataBinding true }를 아래와 같이 build.gradle(Module) 파일의 android{} 에 추가한다.
    android {
     ...
     buildFeatures{
         dataBinding true
     }
    }

AndroidManifest.xml

외부에서 이미지를 읽어오기 위해 인터넷 권한 설정을 허용해준다.
권한 설정은 아래와 같이 <uses-permission android:name="android.permission.INTERNET" />를 태그 안에 넣어준다.

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="com.devgeek.recyclerviewwithdatabindingsample">

    <uses-permission android:name="android.permission.INTERNET" />

    <application
      ...>
      ...
    </application>

</manifest>

activity_main.xml

<layout 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"
    tools:context=".MainActivity">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/recyclerView"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
            tools:listitem="@layout/product_item" />

    </LinearLayout>
</layout>

MainActivity.kt: Init RecyclerView

class MainActivity : AppCompatActivity() {
    private lateinit var binding: ActivityMainBinding
    private val productAdapter = ProductAdapter()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

        binding.recyclerView.adapter = productAdapter
        loadProducts()

    }

    private fun loadProducts() {
        val productList = mutableListOf<ProductModel>()
        productList.apply {
            add(
                ProductModel(
                    id = 0,
                    thumbNailUrl = "https://i.picsum.photos/id/229/100/100.jpg?hmac=rr3nwhpjaZelGscaBcDMtEB6tPeMEWkqcNMlnnOh5fs",
                    name = "상품명 - 1",
                    description = "상품 설명 - 1",
                    price = 10000
                )
            )

            add(
                ProductModel(
                    id = 1,
                    thumbNailUrl = "https://i.picsum.photos/id/846/100/100.jpg?hmac=MIrweaSnfc3PC93ZXP2_RIwTtSgyr4Rj59QNAKYgsfg",
                    name = "상품명 - 2",
                    description = "상품 설명 - 2",
                    price = 20000
                )
            )

            add(
                ProductModel(
                    id = 2,
                    thumbNailUrl = "https://i.picsum.photos/id/250/100/100.jpg?hmac=KjkOu1SZ6cWLdtP6WxtUrsqWRkO0mYRCVy0QIcH9gj0",
                    name = "상품명 - 3",
                    description = "상품 설명 - 3",
                    price = 30000
                )
            )

            add(
                ProductModel(
                    id = 3,
                    thumbNailUrl = "https://i.picsum.photos/id/620/100/100.jpg?hmac=bzyN8XTTVzqxBr2Y7efXe57NV2vj9pQluM4_-xmSFBU",
                    name = "상품명 - 4",
                    description = "상품 설명 - 4",
                    price = 40000
                )
            )
        }

        productAdapter.submitList(productList)
    }
}

ProductModel.kt: RecyclerView item type

data class ProductModel(
    val id: Int,
    val thumbNailUrl: String,
    val name: String,
    val description: String,
    val price: Int
)

MyBindingAdapter.kt: Custom Binding Adapter

 

 

[Android] Custom Binding Adapter

Custom Binding Adapter 개요 커스텀 바인딩 어댑터를 이용하면 데이터를 바인딩 하기 전에 동작하는 로직을 추가할 수 있다. 일반적으로 커스텀 바인딩 어댑터는 Data Binding Library에서 제공하는 어댑터

devgeek.tistory.com

import android.widget.ImageView
import android.widget.TextView
import androidx.databinding.BindingAdapter
import coil.load

object MyBindingAdapter {
    @BindingAdapter("imageUrl")
    @JvmStatic
    fun loadImage(view: ImageView, url: String) {
        view.load(url)
    }

    @BindingAdapter("price")
    @JvmStatic
    fun bindPrice(view: TextView, price: Int) {
        view.text = "${price}원"
    }
}

product_item.xml: RecyclerView Item UI

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <data>

        <variable
            name="productModel"
            type="com.devgeek.recyclerviewwithdatabindingsample.ProductModel" />
    </data>

    <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:padding="20dp">

        <ImageView
            android:id="@+id/ivThumbnail"
            imageUrl="@{productModel.thumbNailUrl}"
            android:layout_width="100dp"
            android:layout_height="100dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <TextView
            android:id="@+id/tvName"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginStart="20dp"
            android:text="@{productModel.name}"
            android:textSize="20sp"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toEndOf="@id/ivThumbnail"
            app:layout_constraintTop_toTopOf="@id/ivThumbnail"
            tools:text="이름" />

        <TextView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:text="@{productModel.description}"
            app:layout_constraintBottom_toTopOf="@id/tvPrice"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="@id/tvName"
            app:layout_constraintTop_toBottomOf="@id/tvName"
            tools:text="상품 설명" />

        <TextView
            android:id="@+id/tvPrice"
            price="@{productModel.price}"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textColor="@color/black"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            tools:text="10000원" />


    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

ProductAdapter.kt

 

 

안드로이드 RecyclerView.ListAdapter 예제 in Kotlin

개요 상품의 이미지, 이름 그리고 가격들을 리스트로 뿌려준다. View Binding 을 사용한다. 실행 화면 프로젝트 구조 Code - Example product_item.xml layout\product_item.xml <?xml version="1.0" encoding="ut..

devgeek.tistory.com


class ProductAdapter : ListAdapter<ProductModel, ProductAdapter.ViewHolder>(diffUtil) {

    /** Create new views (invoked by the layout manager) **/
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        return ViewHolder(
            ProductItemBinding.inflate(
                LayoutInflater.from(parent.context),
                parent,
                false
            )
        )
    }

    /**
     * Replace the contents of a view (invoked by the layout manager)
     *
     * Get element from your dataset at this position and replace the
     * contents of the view with that element
     * */
    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        holder.binding.productModel = currentList[position]
    }

    inner class ViewHolder(val binding: ProductItemBinding) :
        RecyclerView.ViewHolder(binding.root) {
        init {
            /** Define click listener for the ViewHolder's View. */
        }
    }


    companion object {
        val diffUtil = object : DiffUtil.ItemCallback<ProductModel>() {
            override fun areItemsTheSame(oldItem: ProductModel, newItem: ProductModel): Boolean {
                return oldItem.id == newItem.id
            }

            override fun areContentsTheSame(oldItem: ProductModel, newItem: ProductModel): Boolean {
                return oldItem == newItem
            }

        }
    }
}

 

질문과 잘못된 점에 대해 말씀해주시는 건 언제나 환영입니다.
zero5.two4@gmail.com
반응형

'안드로이드 > Jetpack' 카테고리의 다른 글

Android Navigation Graph Component  (0) 2022.07.17
Navigation Basic Sample in Kotlin  (0) 2022.07.15
[Android] DataBinding 예제  (0) 2022.06.29
[Android] Custom Binding Adapter  (0) 2022.06.28
[Android] DataBinding 이란  (0) 2022.06.26
Comments