데이터 바인딩 - 좋아요 카운트 앱 만들어보기

2023. 2. 16. 01:42Android Jetpack

  • 화면에는 일부 데이터가 표시되며 사용자가 좋아요 를 클릭하여 카운터를 늘리고 진행률 을 업데이트할 수 있습니다

 

  • 1. 데이터 바인딩 레이아웃으로 변환을 선택합니다.

  • 2. 이제 레이아웃이 아래와 같이 보여진다.

<?xml version="1.0" encoding="utf-8"?>
<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">

    <data>

        <variable
            name="viewmodel"
            type="com.example.databinding.viewmodel.MyViewModel" />
    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">

        <ImageView
            android:id="@+id/imageView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginBottom="40dp"
            android:minWidth="50dp"
            android:minHeight="50dp"
            app:layout_constraintBottom_toTopOf="@id/progressBar"
            app:layout_constraintStart_toStartOf="@id/progressBar"
            app:popularityIcon="@{viewmodel.popularity}" />

        <TextView
            android:id="@+id/likes_label"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="10dp"
            android:layout_marginStart="8dp"
            android:layout_marginEnd="8dp"
            android:text="@string/likes"
            android:textAlignment="center"
            app:layout_constraintEnd_toEndOf="@+id/imageView"
            app:layout_constraintStart_toStartOf="@+id/imageView"
            app:layout_constraintTop_toBottomOf="@+id/imageView" />

        <TextView
            android:id="@+id/textview"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{viewmodel.likes.toString()}"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <EditText
            android:id="@+id/editText"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginTop="32dp"
            android:layout_marginEnd="16dp"
            app:layout_constraintEnd_toStartOf="@id/plusbutton"
            app:layout_constraintTop_toBottomOf="@id/textview" />


        <Button
            android:id="@+id/plusbutton"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="30dp"
            android:text="@string/Like"
            app:layout_constraintStart_toEndOf="@id/textview"
            app:layout_constraintTop_toBottomOf="@id/textview" />

        <ProgressBar
            android:id="@+id/progressBar"
            style="?android:attr/progressBarStyleHorizontal"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginBottom="50dp"
            android:max="@{100}"
            app:layout_constraintBottom_toTopOf="@+id/textview"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:progressScaled="@{viewmodel.likes}" />
    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

 


  • Viewmodel
package com.example.databinding.viewmodel

import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.Transformations
import androidx.lifecycle.ViewModel

enum class Popularity {
    NORMAL,
    POPULAR,
    STAR
}


class MyViewModel

    : ViewModel() {

    private val _likes = MutableLiveData(0)
    val likes: LiveData<Int> = _likes

    val popularity =Transformations.map(_likes) {
        when {
           (it > 50) -> Popularity.STAR
           (it > 10) -> Popularity.POPULAR
             else -> Popularity.NORMAL
        }
    }

    fun onLike(number:Int) {
                _likes.value = _likes.value?.plus(number)

        }
    }

var _likes는 이 값이 변경될때 ui를 업데이트하는 대신 관찰 가능하게 만듭니다.

  Transformation 변환을 사용하여 LiveData를 다른 LiveData에 종속 시킬수 있다.

사용하면 값이 변경될 때 라이브러리가 UI를 업데이트할 수 있습니다.

 

 

  • BindingAdapter

바인딩 어댑터를 사용하여 사용자 지정 특성을 만들도록합니다.

package com.example.databinding.viewmodel

import android.content.Context
import android.content.res.ColorStateList
import android.graphics.drawable.Drawable
import android.widget.ImageView
import android.widget.ProgressBar
import androidx.core.content.ContextCompat
import androidx.core.widget.ImageViewCompat
import androidx.databinding.BindingAdapter
import com.example.databinding.R

@BindingAdapter(value = ["app:progressScaled", "android:max"], requireAll = true)
fun setProgress(progressBar: ProgressBar, counter: Int, max: Int) {
    progressBar.progress = (counter * 2).coerceAtMost(max)
}
@BindingAdapter("app:popularityIcon")
fun popularityIcon(view: ImageView, popularity: Popularity) {

    val color = getAssociatedColor(popularity, view.context)

    ImageViewCompat.setImageTintList(view, ColorStateList.valueOf(color))

    view.setImageDrawable(getDrawablePopularity(popularity, view.context))
}

private fun getAssociatedColor(popularity: Popularity, context: Context): Int {
    return when (popularity) {
        Popularity.NORMAL -> ContextCompat.getColor(context,R.color.black)

        Popularity.POPULAR -> ContextCompat.getColor(context, R.color.popular)
        Popularity.STAR -> ContextCompat.getColor(context, R.color.star)
    }
}

private fun getDrawablePopularity(popularity: Popularity, context: Context): Drawable? {
    return when (popularity) {
        Popularity.NORMAL -> {
            ContextCompat.getDrawable(context, R.drawable.baseline_people_24)
        }
        Popularity.POPULAR -> {
            ContextCompat.getDrawable(context, R.drawable.baseline_whatshot_24)
        }
        Popularity.STAR -> {
            ContextCompat.getDrawable(context, R.drawable.baseline_whatshot_24)
        }
    }
}

진행률 값의 경우 최대 값과 좋아요 수를 취하는 바인딩 어댑터를 사용합니다.

 

package com.example.databinding

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.databinding.DataBindingUtil
import androidx.lifecycle.ViewModelProvider
import com.example.databinding.databinding.ActivityMainBinding
import com.example.databinding.viewmodel.MyViewModel

class MainActivity : AppCompatActivity() {
    private lateinit var myViewModel: MyViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val binding =
            DataBindingUtil.setContentView<ActivityMainBinding>(this, R.layout.activity_main)

        myViewModel = ViewModelProvider(this)[MyViewModel::class.java]
        binding.lifecycleOwner = this
        binding.viewmodel = myViewModel

        binding.plusbutton.setOnClickListener {
            val input = binding.editText.text.toString().toInt()
            myViewModel.onLike(input)
        }
    }
}

 

LiveData는 수명주기 인식 관찰 가능 개체이므로 사용할 수명 주기 소유자를 지정해야합니다.

Edittext에 숫자값을 입력해 좋아요 버튼 을 눌럿을때  좋아요 수가 증가한다.


  • 좋아요 50개로 채우기
  • 좋아요 갯수에 따라  색상 변경