티스토리 뷰

 

앱개발 숙련 팀 프로젝트

 

구현한 기능

 

상단 Toolbar의 icon을 클릭했을 때 layoutManager를 사용하여

Grid/List 선택에 따라 보여주는 방식을 변경 처리하기

 

 

아이템 레이아웃

 

그리드 아이템은 프로필 이미지와 이름만을 세로 배치한다.

 

 

어댑터 클래스

class ArticleAdapter() :
    ListAdapter<ArticleModel, RecyclerView.ViewHolder>(diffUtil) {

    private fun startProfileActivity(itemView: View, articleModel: ArticleModel) {
        val context = itemView.context
        val intent = Intent(context, ItemProfileActivity::class.java).apply {
            putExtra("name", articleModel.name)
            putExtra("phoneNumber", articleModel.phoneNumber)
            putExtra("email", articleModel.mail)
            putExtra("profileImage", articleModel.imageUrl)
        }
        context.startActivity(intent)
    }
        
    inner class ListViewHolder(private val binding: ListItemArticleBinding) :
        RecyclerView.ViewHolder(binding.root) {
        fun bind(articleModel: ArticleModel) {
            binding.apply {
                binding.name.text = articleModel.name
                binding.profileImage.setImageResource(articleModel.imageUrl)
                binding.like.setImageResource(R.drawable.heart_outlined)
                binding.profileImage.setOnClickListener {
                    startProfileActivity(itemView, articleModel)
                }
                binding.like.setOnClickListener {
                    articleModel.dHeartCheck = !articleModel.dHeartCheck
                    binding.like.setImageResource(
                        if (articleModel.dHeartCheck) R.drawable.heart_filled
                        else R.drawable.heart_outlined
                    )
                }
            }
        }
    }

    inner class GridViewHolder(private val binding: GridItemArticleBinding) :
        RecyclerView.ViewHolder(binding.root) {
        fun bind(articleModel: ArticleModel) {
            binding.apply {
                binding.name.text = articleModel.name
                binding.profileImage.setImageResource(articleModel.imageUrl)
                binding.profileImage.setOnClickListener {
                    startProfileActivity(itemView, articleModel)
                }
            }
        }
    }

    private var layoutId = R.layout.list_item_article

    fun setLayoutId(newLayoutId: Int) {
        layoutId = newLayoutId
        notifyDataSetChanged()
    }

    override fun getItemViewType(position: Int): Int {
        return if (layoutId == R.layout.list_item_article) LIST_VIEW else GRID_VIEW
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
        return when(viewType){
            LIST_VIEW->{
                val binding = ListItemArticleBinding.inflate(
                    LayoutInflater.from(parent.context), parent, false
                )
                ListViewHolder(binding)
            }
            GRID_VIEW->{
                val binding = GridItemArticleBinding.inflate(
                    LayoutInflater.from(parent.context), parent, false
                )
                GridViewHolder(binding)
            }
            else -> throw IllegalArgumentException("Invalid view type")
        }
    }

    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
        val item = currentList[position]
        when (holder) {
            is ListViewHolder -> holder.bind(item)
            is GridViewHolder -> holder.bind(item)
        }
    }

    companion object {
        const val LIST_VIEW = 1
        const val GRID_VIEW = 2

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

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

각 아이템 레이아웃의 뷰홀더를 만들어 layoutId(아이템 레이아웃 아이디) 

값에 따라 뷰타입을 초기화하도록 어댑터 클래스를 설계했다. 

 

초기에는 리스트 형태로 아이템을 출력하도로 설정했다.

메인에서 setLayoutId를 호출하면 layoutId를 업데이트하고

notifyDataSetChanged()를 호출해 전체 아이템에 변경사항을 알린다.

 

 

드롭다운 메뉴 만들기

<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:id="@+id/action_item1"
        android:title="Grid Type" />
    <item
        android:id="@+id/action_item2"
        android:title="List Type" />
</menu>

layout/menu에서 툴바의 우측 아이콘을 눌렀을 때 나오는 메뉴 레이아웃을 선언한다.

 

 

아이템 레이아웃 변경 처리 

binding.ivMenu.setOnClickListener {
    val popupMenu = PopupMenu(requireContext(), it)
    popupMenu.menuInflater.inflate(R.menu.dropdown_menu, popupMenu.menu)
    popupMenu.setOnMenuItemClickListener { item: MenuItem ->
        when (item.itemId) {
            R.id.action_item1 -> {
                adapter.setLayoutId(R.layout.list_item_article)
                binding.articleRecyclerView.layoutManager = LinearLayoutManager(requireContext())
                true
            }
            R.id.action_item2 -> {
                adapter.setLayoutId(R.layout.grid_item_article)
                binding.articleRecyclerView.layoutManager = GridLayoutManager(requireContext(), 4)
                true
            }
            else -> false
        }
    }
    popupMenu.show()
}

 

앱바의 우측 아이콘을 누르면 생성한 드롭다운 레이아웃을 기반으로

팝업메뉴를 생성하고 팝업메뉴의 itemId를 통해 아이템 선택 이벤트를 처리한다.

 

각 항목을 선택하면 보여줄 방식에 따라 뷰홀더와 레이아웃 매니저를 초기화한다.

 

 

번외

// 커스텀 뷰 설정
val builder = AlertDialog.Builder(requireContext())
val binding = AddContactDialogBinding.inflate(LayoutInflater.from(requireContext()))
builder.setView(binding.root)

// 다이얼로그 생성 및 표시
val dialog = builder.create()
dialog.window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
dialog.show()

// 다이얼로그 크기 설정
dialog.window?.setLayout(
    (requireContext().resources.displayMetrics.widthPixels * 0.9).toInt(),
    LayoutParams.WRAP_CONTENT
)

다이얼로그의 너비를 조정하려면 다이얼로그의 배경색을 투명색으로

설정한 뒤 다이얼로그를 띄우고 그 후 크기를 설정하면 된다.

 

 

 

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/11   »
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
글 보관함