From 33bdaa7dbd42442bfc561c87828e972423033528 Mon Sep 17 00:00:00 2001 From: klaus Date: Mon, 4 Aug 2025 21:02:05 +0900 Subject: [PATCH] =?UTF-8?q?refactor:=20=EC=BA=90=EB=A6=AD=ED=84=B0=20?= =?UTF-8?q?=ED=83=AD=20=EB=82=B4=EB=B6=80=EC=97=90=EC=84=9C=20=EC=82=AC?= =?UTF-8?q?=EC=9A=A9=ED=95=98=EB=8A=94=20Adapter=20=EC=BD=94=EB=93=9C?= =?UTF-8?q?=EB=A5=BC=20ViewBinding=20=EC=BD=94=EB=93=9C=EB=A1=9C=20?= =?UTF-8?q?=EB=A6=AC=ED=8C=A9=ED=86=A0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../sodalive/chat/character/Character.kt | 3 +- .../chat/character/CharacterAdapter.kt | 74 +++++++++---------- .../chat/character/CharacterTabFragment.kt | 12 +-- .../curation/CurationSectionAdapter.kt | 62 +++++++++------- .../recent/RecentCharacterAdapter.kt | 48 ++++++------ .../res/layout/fragment_character_tab.xml | 11 +-- 6 files changed, 106 insertions(+), 104 deletions(-) diff --git a/app/src/main/java/kr/co/vividnext/sodalive/chat/character/Character.kt b/app/src/main/java/kr/co/vividnext/sodalive/chat/character/Character.kt index 70bdaaaa..c2b868bf 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/chat/character/Character.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/chat/character/Character.kt @@ -4,6 +4,5 @@ data class Character( val id: String, val name: String, val description: String, - val imageUrl: String, - val ranking: Int? = null // 인기 캐릭터에서만 사용 + val imageUrl: String ) diff --git a/app/src/main/java/kr/co/vividnext/sodalive/chat/character/CharacterAdapter.kt b/app/src/main/java/kr/co/vividnext/sodalive/chat/character/CharacterAdapter.kt index 0ecb0fb0..a2053b3b 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/chat/character/CharacterAdapter.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/chat/character/CharacterAdapter.kt @@ -1,14 +1,13 @@ package kr.co.vividnext.sodalive.chat.character +import android.annotation.SuppressLint +import android.content.Context import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import android.widget.ImageView -import android.widget.LinearLayout -import android.widget.TextView import androidx.recyclerview.widget.RecyclerView -import kr.co.vividnext.sodalive.R -import kr.co.vividnext.sodalive.chat.character.Character +import com.bumptech.glide.Glide +import kr.co.vividnext.sodalive.databinding.ItemCharacterBinding class CharacterAdapter( private var characters: List = emptyList(), @@ -16,46 +15,47 @@ class CharacterAdapter( private val onCharacterClick: (Character) -> Unit = {} ) : RecyclerView.Adapter() { - class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { - val ivCharacter: ImageView = itemView.findViewById(R.id.iv_character) - val tvCharacterName: TextView = itemView.findViewById(R.id.tv_character_name) - val tvCharacterDescription: TextView = itemView.findViewById(R.id.tv_character_description) - val llRanking: LinearLayout = itemView.findViewById(R.id.ll_ranking) - val tvRanking: TextView = itemView.findViewById(R.id.tv_ranking) + inner class ViewHolder( + private val context: Context, + private val binding: ItemCharacterBinding + ) : RecyclerView.ViewHolder(binding.root) { + @SuppressLint("SetTextI18n") + fun bind(character: Character, index: Int) { + binding.tvCharacterName.text = character.name + binding.tvCharacterDescription.text = character.description + + // 순위 표시 여부 결정 + if (showRanking) { + binding.llRanking.visibility = View.VISIBLE + binding.tvRanking.text = (index + 1).toString() + } else { + binding.llRanking.visibility = View.GONE + } + + Glide.with(context) + .load(character.imageUrl) + .into(binding.ivCharacter) + + binding.root.setOnClickListener { onCharacterClick(character) } + } } - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { - val view = LayoutInflater.from(parent.context) - .inflate(R.layout.item_character, parent, false) - return ViewHolder(view) - } + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = ViewHolder( + parent.context, + ItemCharacterBinding.inflate( + LayoutInflater.from(parent.context), + parent, + false + ) + ) override fun onBindViewHolder(holder: ViewHolder, position: Int) { - val character = characters[position] - - holder.tvCharacterName.text = character.name - holder.tvCharacterDescription.text = character.description - - // 순위 표시 여부 결정 - if (showRanking && character.ranking != null) { - holder.llRanking.visibility = View.VISIBLE - holder.tvRanking.text = character.ranking.toString() - } else { - holder.llRanking.visibility = View.GONE - } - - // TODO: 이미지 로딩 라이브러리 사용 (Glide, Picasso 등) - // Glide.with(holder.itemView.context) - // .load(character.imageUrl) - // .into(holder.ivCharacter) - - holder.itemView.setOnClickListener { - onCharacterClick(character) - } + holder.bind(characters[position], index = position) } override fun getItemCount(): Int = characters.size + @SuppressLint("NotifyDataSetChanged") fun updateCharacters(newCharacters: List) { characters = newCharacters notifyDataSetChanged() diff --git a/app/src/main/java/kr/co/vividnext/sodalive/chat/character/CharacterTabFragment.kt b/app/src/main/java/kr/co/vividnext/sodalive/chat/character/CharacterTabFragment.kt index 8e430e82..3048829d 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/chat/character/CharacterTabFragment.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/chat/character/CharacterTabFragment.kt @@ -72,7 +72,7 @@ class CharacterTabFragment : BaseFragment( } // 전체보기 버튼 클릭 리스너 - binding.tvFamousCharacterAll.setOnClickListener { + binding.tvPopularCharacterAll.setOnClickListener { // 인기 캐릭터 전체보기 처리 } @@ -106,11 +106,11 @@ class CharacterTabFragment : BaseFragment( private fun loadPopularCharacters() { // TODO: 서버에서 인기 캐릭터 데이터 로드 val popularCharacters = listOf( - Character("1", "캐릭터 이름", "캐릭터 한줄 소개인데 2줄까", "", 1), - Character("2", "캐릭터 이름", "캐릭터 한줄 소개인데 2줄까", "", 2), - Character("3", "캐릭터 이름", "#태그#태그#태그", "", 3), - Character("4", "캐릭터 이름", "캐릭터 한줄 소개인데 2줄까", "", 4), - Character("5", "캐릭터 이름", "캐릭터 한줄 소개인데 2줄까", "", 5) + Character("1", "캐릭터 이름", "캐릭터 한줄 소개인데 2줄까", ""), + Character("2", "캐릭터 이름", "캐릭터 한줄 소개인데 2줄까", ""), + Character("3", "캐릭터 이름", "#태그#태그#태그", ""), + Character("4", "캐릭터 이름", "캐릭터 한줄 소개인데 2줄까", ""), + Character("5", "캐릭터 이름", "캐릭터 한줄 소개인데 2줄까", "") ) popularCharacterAdapter.updateCharacters(popularCharacters) diff --git a/app/src/main/java/kr/co/vividnext/sodalive/chat/character/curation/CurationSectionAdapter.kt b/app/src/main/java/kr/co/vividnext/sodalive/chat/character/curation/CurationSectionAdapter.kt index 22596049..c879aeac 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/chat/character/curation/CurationSectionAdapter.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/chat/character/curation/CurationSectionAdapter.kt @@ -1,52 +1,58 @@ package kr.co.vividnext.sodalive.chat.character.curation +import android.annotation.SuppressLint import android.view.LayoutInflater -import android.view.View import android.view.ViewGroup -import android.widget.TextView import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView -import kr.co.vividnext.sodalive.R -import kr.co.vividnext.sodalive.chat.character.CharacterAdapter import kr.co.vividnext.sodalive.chat.character.Character -import kr.co.vividnext.sodalive.chat.character.curation.CurationSection +import kr.co.vividnext.sodalive.chat.character.CharacterAdapter +import kr.co.vividnext.sodalive.databinding.ItemCurationSectionBinding class CurationSectionAdapter( private var sections: List = emptyList(), private val onCharacterClick: (Character) -> Unit = {} ) : RecyclerView.Adapter() { - class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { - val tvSectionTitle: TextView = itemView.findViewById(R.id.tv_section_title) - val rvCharacters: RecyclerView = itemView.findViewById(R.id.rv_characters) + inner class ViewHolder( + private val binding: ItemCurationSectionBinding + ) : RecyclerView.ViewHolder(binding.root) { + fun bind(section: CurationSection) { + binding.tvSectionTitle.text = section.title + + // 캐릭터 리스트 설정 + val characterAdapter = CharacterAdapter( + characters = section.characters, + showRanking = false, + onCharacterClick = onCharacterClick + ) + + binding.rvCharacters.apply { + layoutManager = LinearLayoutManager( + context, + LinearLayoutManager.HORIZONTAL, + false + ) + adapter = characterAdapter + } + } } - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { - val view = LayoutInflater.from(parent.context) - .inflate(R.layout.item_curation_section, parent, false) - return ViewHolder(view) - } + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = ViewHolder( + ItemCurationSectionBinding.inflate( + LayoutInflater.from(parent.context), + parent, + false + ) + ) override fun onBindViewHolder(holder: ViewHolder, position: Int) { - val section = sections[position] - - holder.tvSectionTitle.text = section.title - - // 캐릭터 리스트 설정 - val characterAdapter = CharacterAdapter( - characters = section.characters, - showRanking = false, - onCharacterClick = onCharacterClick - ) - - holder.rvCharacters.apply { - layoutManager = LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false) - adapter = characterAdapter - } + holder.bind(sections[position]) } override fun getItemCount(): Int = sections.size + @SuppressLint("NotifyDataSetChanged") fun updateSections(newSections: List) { sections = newSections notifyDataSetChanged() diff --git a/app/src/main/java/kr/co/vividnext/sodalive/chat/character/recent/RecentCharacterAdapter.kt b/app/src/main/java/kr/co/vividnext/sodalive/chat/character/recent/RecentCharacterAdapter.kt index 3770ce14..77994b5a 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/chat/character/recent/RecentCharacterAdapter.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/chat/character/recent/RecentCharacterAdapter.kt @@ -1,43 +1,43 @@ package kr.co.vividnext.sodalive.chat.character.recent import android.annotation.SuppressLint +import android.content.Context import android.view.LayoutInflater -import android.view.View import android.view.ViewGroup -import android.widget.ImageView -import android.widget.TextView import androidx.recyclerview.widget.RecyclerView -import kr.co.vividnext.sodalive.R +import com.bumptech.glide.Glide +import kr.co.vividnext.sodalive.databinding.ItemRecentCharacterBinding class RecentCharacterAdapter( private var characters: List = emptyList(), private val onCharacterClick: (RecentCharacter) -> Unit = {} ) : RecyclerView.Adapter() { - class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { - val ivProfile: ImageView = itemView.findViewById(R.id.iv_profile) - val tvName: TextView = itemView.findViewById(R.id.tv_name) + inner class ViewHolder( + private val context: Context, + private val binding: ItemRecentCharacterBinding + ) : RecyclerView.ViewHolder(binding.root) { + fun bind(character: RecentCharacter) { + binding.tvName.text = character.name + Glide.with(context) + .load(character.profileImageUrl) + .into(binding.ivProfile) + + binding.root.setOnClickListener { onCharacterClick(character) } + } } - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { - val view = LayoutInflater.from(parent.context) - .inflate(R.layout.item_recent_character, parent, false) - return ViewHolder(view) - } + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = ViewHolder( + parent.context, + ItemRecentCharacterBinding.inflate( + LayoutInflater.from(parent.context), + parent, + false + ) + ) override fun onBindViewHolder(holder: ViewHolder, position: Int) { - val character = characters[position] - - holder.tvName.text = character.name - - // TODO: 이미지 로딩 라이브러리 사용 (Glide, Picasso 등) - // Glide.with(holder.itemView.context) - // .load(character.profileImageUrl) - // .into(holder.ivProfile) - - holder.itemView.setOnClickListener { - onCharacterClick(character) - } + holder.bind(characters[position]) } override fun getItemCount(): Int = characters.size diff --git a/app/src/main/res/layout/fragment_character_tab.xml b/app/src/main/res/layout/fragment_character_tab.xml index 3f4492e0..1388e7fe 100644 --- a/app/src/main/res/layout/fragment_character_tab.xml +++ b/app/src/main/res/layout/fragment_character_tab.xml @@ -105,7 +105,7 @@ android:textSize="24sp" /> - + android:paddingHorizontal="24dp" /> @@ -167,7 +166,7 @@ android:layout_height="wrap_content" android:layout_marginTop="16dp" android:clipToPadding="false" - android:paddingStart="24dp" /> + android:paddingHorizontal="24dp" /> @@ -177,7 +176,5 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="24dp" /> - - - \ No newline at end of file +