일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
Tags
- 안드로이드 fcm
- Android DataBinding
- 습관만들기
- Kotlin FCM
- Android WebView
- 안드로이드 갤러리 접근
- Android ViewPager2
- 카카오 알고리즘
- Android 12 대응
- 프로그래머스 알고리즘
- android recyclerview
- 안드로이드
- Java
- Android ProgressBar
- 66챌린지
- scope function
- Android Jetpack
- 알고리즘 자바
- 안드로이드 카카오 로그인
- Kotlin
- DataBinding
- Android 12
- Android Interceptor
- Android Navigation
- OkHttp Interceptor
- 영어공부
- MVP Architecture
- 영어독립365
- WebView
- Android
Archives
- Today
- Total
Developer Geek
[Android] Custom Binding Adapter Example in Kotlin 본문
반응형
개요
Custom Binding Adapter
를 이용하여, 썸네일을 담당하는 이미지뷰에 이미지를 로드하고 가격을 담당하는 텍스트뷰에 정수를 입력하면 원
을 추가하여 보여지도록 하는 리스트를 만든다.
실행화면
프로젝트 구조
build.gradle(Module)
- CustomBindingAdapter 구현을 위해
kotlin-kapt
를 아래와 같이build.gradle(Module)
파일의 plugins에 추가한다.plugins { ... id 'kotlin-kapt' }
- 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
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
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