[24.07.18] TIL - 035

๐ŸŽง 0. ์˜ค๋Š˜์˜ ์ถ”์ฒœ๊ณก

๋ชฝ๋กฑํ•œ ๋…ธ๋žœ๋ฐ, ์‹ค์ œ๋กœ ๋งˆ์•ฝ์— ์ทจํ•œ ์ฑ„ ๊ฐ€์‚ฌ๋ฅผ ์ ์—ˆ๋‹ค๊ณ  ํ•˜๋„ค์š”.

๐Ÿ“— 1. ์ฑŒ๋ฆฐ์ง€๋ฐ˜ ๊ณผ์ œ ์ง„ํ–‰

์ œ๊ฐ€ ์ง„ํ–‰ํ•œ ๊ณผ์ œ๋Š” 2๊ฐ€์ง€์ž…๋‹ˆ๋‹ค. ์ฒซ ๋ฒˆ์งธ๋Š” ListAdapter์™€ Multi ViewType์„ ์ด์šฉํ•œ RecyclerView์ด๊ณ ,

๋‘ ๋ฒˆ์งธ๋Š” ์„ธ๋กœ/๊ฐ€๋กœ ๋ชจ๋“œ์— ๋”ฐ๋ฅธ ํ”„๋ž˜๊ทธ๋จผํŠธ ๋ณ€ํ™”์ž…๋‹ˆ๋‹ค.

1-1. ListAdapter์™€ ViewType

package com.android.nbc_c_assignment1.challenge4_1

import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
import com.android.nbc_login.databinding.LayoutContactListFavoriteBinding
import com.android.nbc_login.databinding.LayoutContactListNormalBinding

enum class ViewType {
    NORMAL, FAVORITE
}

class ContactListAdapter(private val viewModel: ContactListViewModel) : ListAdapter<ContactListData, RecyclerView.ViewHolder>(
    ContractListDiffCallback()
) {
//    fun initList() {
//        val list = viewModel.getList()
//        if (list != null) {
//            val partition = list.partition { it.isFavorite }
//            favoriteList = partition.first
//            normalList = partition.second
//        }
//    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
        val viewHolder: RecyclerView.ViewHolder
        when(viewType) {
            ViewType.NORMAL.ordinal -> {
                val binding = LayoutContactListNormalBinding.inflate(LayoutInflater.from(parent.context), parent, false)
                viewHolder = NormalViewHolder(binding)
            }
            else -> {
                val binding = LayoutContactListFavoriteBinding.inflate(LayoutInflater.from(parent.context), parent, false)
                viewHolder = FavoriteViewHolder(binding)
            }
        }
        println("$viewHolder $viewType")
        return viewHolder
    }

    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
        when(holder) {
            is NormalViewHolder -> holder.bind(viewModel, position, itemLongClick)
            is FavoriteViewHolder -> holder.bind(viewModel, position, itemLongClick)
        }
    }

    override fun getItemViewType(position: Int): Int {
        println("h $position ${viewModel.getList()?.get(position)?.isFavorite}")
        return if (viewModel.getList()?.get(position)?.isFavorite == true) ViewType.FAVORITE.ordinal else ViewType.NORMAL.ordinal
    }

    override fun getItemCount(): Int = viewModel.getList()!!.size

    override fun getItemId(position: Int): Long = position.toLong()

    interface ItemClick {
        fun onClick()
    }

    var itemLongClick: ItemClick? = null

}
class ContactListAdapter(private val viewModel: ContactListViewModel) : ListAdapter<ContactListData, RecyclerView.ViewHolder>(
    ContractListDiffCallback()
)

์˜ค๋Š˜์€ ์ผ๋‹จ ์ฝ”๋“œ๋ฅผ ๊ฐ„๋‹จํ•˜๊ฒŒ ์„ค๋ช…๋งŒ ํ•˜๊ณ , ๋‚ด์ผ ๋ณต์Šตํ•˜๊ณ  ์ •๋ฆฌํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

๋จผ์ € ListAdapter<๋ฐ์ดํ„ฐ, ๋ทฐํ™€๋”>(DiffCallback)๋ฅผ ์ƒ์†๋ฐ›์Šต๋‹ˆ๋‹ค.

์—ฌ๊ธฐ์„œ ๋ฐ์ดํ„ฐ๋Š” ๋ฐ์ดํ„ฐ ํด๋ž˜์Šค๋ฅผ ๋„ฃ์–ด์ฃผ๋ฉด ๋˜๋Š”๋ฐ, ๋‹ค์–‘ํ•œ ๋ฐ์ดํ„ฐ ํด๋ž˜์Šค๋ฅผ ์“ธ ๋• sealed class๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒŒ ์ข‹์Šต๋‹ˆ๋‹ค.

 override fun getItemViewType(position: Int): Int {
        println("h $position ${viewModel.getList()?.get(position)?.isFavorite}")
        return if (viewModel.getList()?.get(position)?.isFavorite == true) ViewType.FAVORITE.ordinal else ViewType.NORMAL.ordinal
    }

๋จผ์ € viewType์„ ์ง€์ •ํ•ด์ค˜์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์ €๊ฐ™์€ ๊ฒฝ์šฐ๋Š” ์ฆ๊ฒจ์ฐพ๊ธฐ๋ฅผ ๊ตฌํ˜„ํ–ˆ๊ธฐ์—, ๋ฐ์ดํ„ฐ ํด๋ž˜์Šค ์•ˆ์˜ ๊ฐ’๋งŒ ๊ฐ€์ง€๊ณ  ๋ทฐํƒ€์ž…์„ ๋‚˜๋ˆ ์คฌ์Šต๋‹ˆ๋‹ค.

 override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
        val viewHolder: RecyclerView.ViewHolder
        when(viewType) {
            ViewType.NORMAL.ordinal -> {
                val binding = LayoutContactListNormalBinding.inflate(LayoutInflater.from(parent.context), parent, false)
                viewHolder = NormalViewHolder(binding)
            }
            else -> {
                val binding = LayoutContactListFavoriteBinding.inflate(LayoutInflater.from(parent.context), parent, false)
                viewHolder = FavoriteViewHolder(binding)
            }
        }
        println("$viewHolder $viewType")
        return viewHolder
    }

์ดํ›„, ์ด ๋ทฐํƒ€์ž…์— ๋”ฐ๋ผ ์–ด๋–ค ๋ทฐํ™€๋”๋ฅผ ์ง€์ •ํ•ด์ค„์ง€๋ฅผ ์„ค์ •ํ•ด์ค๋‹ˆ๋‹ค.

override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
        when(holder) {
            is NormalViewHolder -> holder.bind(viewModel, position, itemLongClick)
            is FavoriteViewHolder -> holder.bind(viewModel, position, itemLongClick)
        }
    }

๋งˆ์ง€๋ง‰์œผ๋กœ, ๋ทฐํ™€๋”์— ๋”ฐ๋ผ ๋ฐ์ดํ„ฐ๋“ค์„ ๋ฐ”์ธ๋”ฉํ•ด์ค๋‹ˆ๋‹ค.

์ผ๋‹จ ๊ตฌ์กฐ๋Š” ์ด๋ ‡๊ฒŒ ๋ผ ์žˆ๊ณ , ํ•˜๋‚˜ํ•˜๋‚˜ ์ž์„ธํ•œ ์„ค๋ช…๋“ค์€ ๋‚ด์ผ ๊ฐ€๋Šฅํ•˜๊ฒŒ ์—ด์‹ฌํžˆ ๋ณต์Šตํ•ด์˜ค๊ฒ ์Šต๋‹ˆ๋‹ค...!

1-2. ๊ฐ€๋กœ / ์„ธ๋กœ ๋ชจ๋“œ

์•ˆ๋“œ๋กœ์ด๋“œ ์ŠคํŠœ๋””์˜ค๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ์„ธ๋กœ ๋ชจ๋“œ๋ฅผ ์ง€์›ํ•˜๊ณ , ๊ฐ€๋กœ ๋ชจ๋“œ๋Š” ์ž๋™์ ์œผ๋กœ ์„ธ๋กœ ๋ชจ๋“œ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ๋งŒ๋“ค์–ด์ค๋‹ˆ๋‹ค.

์ด๋•Œ, ๊ฐ€๋กœ ๋ชจ๋“œ๋ฅผ ์›ํ•˜๋Š” ๋Œ€๋กœ ๋ฐ”๊ฟ€ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

layout์— ๊ฐ€๋กœ ๋ชจ๋“œ๋ฅผ activity์˜ xml ๋ช…์„ ๋™์ผํ•˜๊ฒŒ ๋งŒ๋“ค๊ณ , ๋””๋ ‰ํ† ๋ฆฌ ์ด๋ฆ„์„ layout-land์œผ๋กœ ์ง€์ •ํ•ด์ฃผ๋ฉด ๋ฉ๋‹ˆ๋‹ค.

ํ”„๋ž˜๊ทธ๋จผํŠธ์˜ ๊ฒฝ์šฐ, ๊ฐ€๋กœ, ์„ธ๋กœ์—์„œ ์–ด๋–ค id๋ฅผ ์“ธ์ง€, ์–ด๋–ค ์ชฝ์— ์–ด๋–ค ํ”„๋ž˜๊ทธ๋จผํŠธ๋ฅผ ๋ถ™์ผ์ง€๋„ ๋‹ฌ๋ผ์งˆ ์ˆ˜ ์žˆ๊ธฐ์—,

ํ˜„์žฌ ์ƒํƒœ๊ฐ€ ๊ฐ€๋กœ์ธ์ง€ ์„ธ๋กœ์ธ์ง€ ํŒŒ์•…ํ•  ์ˆ˜ ์žˆ๋Š” ์ฝ”๋“œ๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

์ด๋•Œ ํ•„์š”ํ•œ ๊ฒŒ Configuration์ž…๋‹ˆ๋‹ค.

val config = Resources.getSystem().configuration
fun setFragment(config: Configuration, isClick: Boolean = false) {
        if( config.orientation == Configuration.ORIENTATION_PORTRAIT ) {
            if(!isClick) {
                supportFragmentManager.commit {
                    replace(R.id.fragment, titleFragment)
                    setReorderingAllowed(true)
                    addToBackStack("title")
                }
            } else {
                supportFragmentManager.commit {
                    replace(R.id.fragment, detailFragment)
                    setReorderingAllowed(true)
                    addToBackStack("detail")
                }
            }

        } else if ( config.orientation == Configuration.ORIENTATION_LANDSCAPE ) {
            supportFragmentManager.commit {
                setReorderingAllowed(true)
                replace(R.id.fragment_title, titleFragment)
                replace(R.id.fragment_detail, detailFragment)
            }
        }
    }

Configuration์€ Resources.getSystem().configuration์œผ๋กœ ๊ฐ€์ ธ์˜ค๊ฑฐ๋‚˜, resources.configuration์œผ๋กœ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์—ฌ๊ธฐ์„œ orientation์ด๋ผ๋Š” ๋…€์„์˜ ๊ฐ’์ด ORIENTATION_PORTRAIT(์„ธ๋กœ)์ธ์ง€ LANDSCAPE(๊ฐ€๋กœ)์ธ์ง€ ์•Œ์•„๋‚ด์„œ

๋น„๊ตํ•ด์ฃผ๋ฉด ๋˜๊ฒ ์Šต๋‹ˆ๋‹ค.

1-3. ํด๋”๋ธ” ํฐ๋„ ๊ตฌํ˜„ ๊ฐ€๋Šฅํ• ๊นŒ?

๊ฐค๋Ÿญ์‹œ Z Flip์„ ์จ๋ณด์‹  ๋ถ„๋“ค์ด ์žˆ์œผ์‹œ๋ฉด, ์นด๋ฉ”๋ผ๋ฅผ ํ‚ค๊ณ , ๋ฐ˜์ฏค ์ ‘์œผ๋ฉด ์นด๋ฉ”๋ผ ์•ฑ์ด ๋‹ฌ๋ผ์ง€๋Š” ๊ฑธ ์•„์‹ค ํ…๋ฐ์š”.

๊ทธ๋ ‡๋‹ค๋Š” ๊ฑด, ์ด๊ฑธ ์ง€์›ํ•œ๋‹ค๋Š” ๋œป์ด ๋  ๊ฑฐ๋ผ๋Š” ์ƒ๊ฐ์— ํ•œ๋ฒˆ ์ฐพ์•„๋ดค์Šต๋‹ˆ๋‹ค.

๊ณต์‹ ๋ฌธ์„œ - Jetpack WindowManager

์‚ฌ์‹ค ์ด๊ฒƒ๋„ ๊ตฌํ˜„ํ•ด๋ณด๊ณ  ์‹ถ์—ˆ๋Š”๋ฐ, ์–ด์ฉŒ๋‹ค๋ณด๋‹ˆ ์‹œ๊ฐ„์ด ์—†์–ด์„œ ์—๋ฎฌ๋ ˆ์ดํ„ฐ๋ฐ–์— ๋ชป ์ฐพ์•˜์Šต๋‹ˆ๋‹ค.

๊ณต์‹ ๋ฌธ์„œ - ์—๋ฎฌ๋ ˆ์ดํ„ฐ ์ถœ์‹œ ๋…ธํŠธ 30.0.26

์—ฌ๊ธฐ์— ์ ํžŒ config.ini๋ฅผ ๊ธฐ์กด์˜ ์—๋ฎฌ๋ ˆ์ดํ„ฐ์˜ config.ini์— ์ถ”๊ฐ€๋กœ ์ ์–ด์ฃผ๋ฉด ๋ฌด๋ ค ์œ ์‚ฌ Z Flip์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๊ฒŒ ๊ณผ์ œ๋Š” ์•„๋‹ˆ์ง€๋งŒ, ๋ญ”๊ฐ€ ๋งŒ๋“ค์–ด๋ณด๊ณ  ์‹ถ์–ด์„œ ์ฐพ์•„๋ณด๊ฒŒ ๋์Šต๋‹ˆ๋‹ค.

์‹œ๊ฐ„์ด ๋‚จ์œผ๋ฉด ๊ผญ ํ™œ์šฉํ•ด๋ณด๊ณ  ์‹ถ๋„ค์š”.

๐ŸŽฏ 2. ๋

๋‚ด์ผ์€ ๋ ˆํฌ์ง€ํ† ๋ฆฌ ํŒจํ„ด์„ ๋ทฐ ๋ชจ๋ธ์— ์ ์šฉ์‹œ์ผœ ๋ณด๊ณ ,

RecyclerView ListAdapter, ViewType์„ ๋ณต์Šตํ•˜๊ณ ...

์ฝ”๋ฃจํ‹ด์„ ๊ณต๋ถ€ํ•˜๊ณ .....

ํด๋”๋ธ” ํ™”๋ฉด์— ๋Œ€ํ•œ ๊ฒƒ๋„ ๊ณต๋ถ€ํ•ด๋ณด๊ณ .........................

ํ•  ๊ฒŒ ๋งŽ๋„ค์š”.

๋.

profile
์—ฌ๊ธฐ๋Š” ๊ณต๋ถ€ ๊ธฐ๋ก์šฉ ๋ธ”๋กœ๊ทธ

0๊ฐœ์˜ ๋Œ“๊ธ€