feat(character): 캐릭터 탭 UI 및 기본 기능 구현
This commit is contained in:
@@ -0,0 +1,9 @@
|
||||
package kr.co.vividnext.sodalive.chat.character
|
||||
|
||||
data class Character(
|
||||
val id: String,
|
||||
val name: String,
|
||||
val description: String,
|
||||
val imageUrl: String,
|
||||
val ranking: Int? = null // 인기 캐릭터에서만 사용
|
||||
)
|
||||
@@ -0,0 +1,63 @@
|
||||
package kr.co.vividnext.sodalive.chat.character
|
||||
|
||||
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
|
||||
|
||||
class CharacterAdapter(
|
||||
private var characters: List<Character> = emptyList(),
|
||||
private val showRanking: Boolean = false,
|
||||
private val onCharacterClick: (Character) -> Unit = {}
|
||||
) : RecyclerView.Adapter<CharacterAdapter.ViewHolder>() {
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
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 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)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int = characters.size
|
||||
|
||||
fun updateCharacters(newCharacters: List<Character>) {
|
||||
characters = newCharacters
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
}
|
||||
@@ -2,15 +2,162 @@ package kr.co.vividnext.sodalive.chat.character
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import kr.co.vividnext.sodalive.base.BaseFragment
|
||||
import kr.co.vividnext.sodalive.chat.character.curation.CurationSection
|
||||
import kr.co.vividnext.sodalive.chat.character.curation.CurationSectionAdapter
|
||||
import kr.co.vividnext.sodalive.chat.character.recent.RecentCharacter
|
||||
import kr.co.vividnext.sodalive.chat.character.recent.RecentCharacterAdapter
|
||||
import kr.co.vividnext.sodalive.databinding.FragmentCharacterTabBinding
|
||||
|
||||
// 캐릭터 탭 프래그먼트
|
||||
class CharacterTabFragment : BaseFragment<FragmentCharacterTabBinding>(
|
||||
FragmentCharacterTabBinding::inflate
|
||||
) {
|
||||
|
||||
private lateinit var recentCharacterAdapter: RecentCharacterAdapter
|
||||
private lateinit var popularCharacterAdapter: CharacterAdapter
|
||||
private lateinit var newCharacterAdapter: CharacterAdapter
|
||||
private lateinit var curationSectionAdapter: CurationSectionAdapter
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
// 캐릭터 탭 초기화 로직
|
||||
setupRecyclerViews()
|
||||
loadData()
|
||||
}
|
||||
|
||||
private fun setupRecyclerViews() {
|
||||
// 최근 대화한 캐릭터 RecyclerView 설정
|
||||
recentCharacterAdapter = RecentCharacterAdapter { character ->
|
||||
// 캐릭터 클릭 처리
|
||||
onRecentCharacterClick(character)
|
||||
}
|
||||
binding.rvRecentCharacters.apply {
|
||||
layoutManager = LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false)
|
||||
adapter = recentCharacterAdapter
|
||||
}
|
||||
|
||||
// 인기 캐릭터 RecyclerView 설정 (순위 표시)
|
||||
popularCharacterAdapter = CharacterAdapter(
|
||||
showRanking = true
|
||||
) { character ->
|
||||
// 캐릭터 클릭 처리
|
||||
onCharacterClick(character)
|
||||
}
|
||||
binding.rvPopularCharacters.apply {
|
||||
layoutManager = LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false)
|
||||
adapter = popularCharacterAdapter
|
||||
}
|
||||
|
||||
// 신규 캐릭터 RecyclerView 설정
|
||||
newCharacterAdapter = CharacterAdapter(
|
||||
showRanking = false
|
||||
) { character ->
|
||||
// 캐릭터 클릭 처리
|
||||
onCharacterClick(character)
|
||||
}
|
||||
binding.rvNewCharacters.apply {
|
||||
layoutManager = LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false)
|
||||
adapter = newCharacterAdapter
|
||||
}
|
||||
|
||||
// 큐레이션 섹션 RecyclerView 설정
|
||||
curationSectionAdapter = CurationSectionAdapter { character ->
|
||||
// 캐릭터 클릭 처리
|
||||
onCharacterClick(character)
|
||||
}
|
||||
binding.rvCurationSections.apply {
|
||||
layoutManager = LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false)
|
||||
adapter = curationSectionAdapter
|
||||
}
|
||||
|
||||
// 전체보기 버튼 클릭 리스너
|
||||
binding.tvFamousCharacterAll.setOnClickListener {
|
||||
// 인기 캐릭터 전체보기 처리
|
||||
}
|
||||
|
||||
binding.tvNewCharacterAll.setOnClickListener {
|
||||
// 신규 캐릭터 전체보기 처리
|
||||
}
|
||||
}
|
||||
|
||||
private fun loadData() {
|
||||
// TODO: 실제 데이터 로딩 로직 구현
|
||||
loadRecentCharacters()
|
||||
loadPopularCharacters()
|
||||
loadNewCharacters()
|
||||
loadCurationSections()
|
||||
}
|
||||
|
||||
private fun loadRecentCharacters() {
|
||||
// TODO: 서버에서 최근 대화한 캐릭터 데이터 로드
|
||||
val recentCharacters = listOf(
|
||||
RecentCharacter("1", "Yubin...", ""),
|
||||
RecentCharacter("2", "Yubin...", ""),
|
||||
RecentCharacter("3", "Yubin...", ""),
|
||||
RecentCharacter("4", "Yubin...", ""),
|
||||
RecentCharacter("5", "Yubin...", "")
|
||||
)
|
||||
|
||||
recentCharacterAdapter.updateCharacters(recentCharacters)
|
||||
binding.tvLatestCharacterCount.text = recentCharacters.size.toString()
|
||||
}
|
||||
|
||||
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)
|
||||
)
|
||||
|
||||
popularCharacterAdapter.updateCharacters(popularCharacters)
|
||||
}
|
||||
|
||||
private fun loadNewCharacters() {
|
||||
// TODO: 서버에서 신규 캐릭터 데이터 로드
|
||||
val newCharacters = listOf(
|
||||
Character("1", "캐릭터 이름", "캐릭터 한줄 소개인데 2줄까", ""),
|
||||
Character("2", "하이퍼나이프", "캐릭터 한줄 소개인데 2줄까", ""),
|
||||
Character("3", "내일", "#태그#태그", "")
|
||||
)
|
||||
|
||||
newCharacterAdapter.updateCharacters(newCharacters)
|
||||
}
|
||||
|
||||
private fun loadCurationSections() {
|
||||
// TODO: 서버에서 큐레이션 섹션 데이터 로드
|
||||
val curationSections = listOf(
|
||||
CurationSection(
|
||||
"1",
|
||||
"큐레이션",
|
||||
listOf(
|
||||
Character("1", "캐릭터 이름", "캐릭터 한줄 소개인데 2줄까", ""),
|
||||
Character("2", "하이퍼나이프", "캐릭터 한줄 소개인데 2줄까", ""),
|
||||
Character("3", "내일", "#태그#태그", "")
|
||||
)
|
||||
),
|
||||
CurationSection(
|
||||
"2",
|
||||
"큐레이션",
|
||||
listOf(
|
||||
Character("4", "캐릭터 이름", "캐릭터 한줄 소개인데 2줄까", ""),
|
||||
Character("5", "하이퍼나이프", "캐릭터 한줄 소개인데 2줄까", ""),
|
||||
Character("6", "내일", "#태그#태그", "")
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
curationSectionAdapter.updateSections(curationSections)
|
||||
}
|
||||
|
||||
private fun onRecentCharacterClick(character: RecentCharacter) {
|
||||
// TODO: 최근 대화한 캐릭터 클릭 처리
|
||||
}
|
||||
|
||||
private fun onCharacterClick(character: Character) {
|
||||
// TODO: 캐릭터 클릭 처리
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
package kr.co.vividnext.sodalive.chat.character.curation
|
||||
|
||||
import kr.co.vividnext.sodalive.chat.character.Character
|
||||
|
||||
data class CurationSection(
|
||||
val id: String,
|
||||
val title: String,
|
||||
val characters: List<Character>
|
||||
)
|
||||
@@ -0,0 +1,54 @@
|
||||
package kr.co.vividnext.sodalive.chat.character.curation
|
||||
|
||||
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
|
||||
|
||||
class CurationSectionAdapter(
|
||||
private var sections: List<CurationSection> = emptyList(),
|
||||
private val onCharacterClick: (Character) -> Unit = {}
|
||||
) : RecyclerView.Adapter<CurationSectionAdapter.ViewHolder>() {
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
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 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
|
||||
}
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int = sections.size
|
||||
|
||||
fun updateSections(newSections: List<CurationSection>) {
|
||||
sections = newSections
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package kr.co.vividnext.sodalive.chat.character.recent
|
||||
|
||||
data class RecentCharacter(
|
||||
val id: String,
|
||||
val name: String,
|
||||
val profileImageUrl: String
|
||||
)
|
||||
@@ -0,0 +1,50 @@
|
||||
package kr.co.vividnext.sodalive.chat.character.recent
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
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
|
||||
|
||||
class RecentCharacterAdapter(
|
||||
private var characters: List<RecentCharacter> = emptyList(),
|
||||
private val onCharacterClick: (RecentCharacter) -> Unit = {}
|
||||
) : RecyclerView.Adapter<RecentCharacterAdapter.ViewHolder>() {
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
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 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)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int = characters.size
|
||||
|
||||
@SuppressLint("NotifyDataSetChanged")
|
||||
fun updateCharacters(newCharacters: List<RecentCharacter>) {
|
||||
characters = newCharacters
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
}
|
||||
14
app/src/main/res/drawable/gradient_ranking_bg.xml
Normal file
14
app/src/main/res/drawable/gradient_ranking_bg.xml
Normal file
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<gradient
|
||||
android:angle="135"
|
||||
android:startColor="#80000000"
|
||||
android:centerColor="#99000000"
|
||||
android:endColor="#CC000000"
|
||||
android:type="linear" />
|
||||
<corners
|
||||
android:bottomLeftRadius="16dp"
|
||||
android:bottomRightRadius="0dp"
|
||||
android:topLeftRadius="0dp"
|
||||
android:topRightRadius="0dp" />
|
||||
</shape>
|
||||
@@ -1,19 +1,183 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
<androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/black">
|
||||
android:background="@color/color_131313"
|
||||
android:fillViewport="true">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="캐릭터 탭"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="20sp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
android:orientation="vertical">
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
<!-- 배너 섹션 -->
|
||||
<LinearLayout
|
||||
android:id="@+id/ll_banner"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="48dp"
|
||||
android:orientation="vertical">
|
||||
|
||||
<com.zhpan.bannerview.BannerViewPager
|
||||
android:id="@+id/event_banner_slider"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:clipChildren="false"
|
||||
android:clipToPadding="false" />
|
||||
|
||||
<com.zhpan.indicator.IndicatorView
|
||||
android:id="@+id/indicator_event_banner"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginTop="28dp" />
|
||||
</LinearLayout>
|
||||
|
||||
<!-- 최근 대화한 캐릭터 섹션 -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="48dp"
|
||||
android:orientation="vertical">
|
||||
|
||||
<!-- 제목 -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal"
|
||||
android:paddingHorizontal="24dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="@font/pretendard_bold"
|
||||
android:text="최근 대화한 캐릭터"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="20sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_latest_character_count"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="6dp"
|
||||
android:fontFamily="@font/pretendard_bold"
|
||||
android:textColor="@color/color_fdca2f"
|
||||
android:textSize="20sp"
|
||||
tools:text="14" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- 프로필 리스트 -->
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/rv_recent_characters"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:clipToPadding="false"
|
||||
android:paddingHorizontal="24dp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- 인기 캐릭터 섹션 -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="48dp"
|
||||
android:orientation="vertical">
|
||||
|
||||
<!-- 제목과 전체보기 -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal"
|
||||
android:paddingHorizontal="24dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:fontFamily="@font/pretendard_bold"
|
||||
android:text="인기 캐릭터"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="24sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_famous_character_all"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="@font/pretendard_regular"
|
||||
android:text="전체보기"
|
||||
android:textColor="#90A4AE"
|
||||
android:textSize="14sp" />
|
||||
</LinearLayout>
|
||||
|
||||
<!-- 캐릭터 카드 리스트 -->
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/rv_popular_characters"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:clipToPadding="false"
|
||||
android:paddingStart="24dp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- 신규 캐릭터 섹션 -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="48dp"
|
||||
android:orientation="vertical">
|
||||
|
||||
<!-- 제목과 전체보기 -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal"
|
||||
android:paddingHorizontal="24dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:fontFamily="@font/pretendard_bold"
|
||||
android:text="신규 캐릭터"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="24sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_new_character_all"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="@font/pretendard_regular"
|
||||
android:text="전체보기"
|
||||
android:textColor="#90A4AE"
|
||||
android:textSize="14sp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- 캐릭터 카드 리스트 -->
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/rv_new_characters"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:clipToPadding="false"
|
||||
android:paddingStart="24dp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- 큐레이션 섹션들 -->
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/rv_curation_sections"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="24dp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
71
app/src/main/res/layout/item_character.xml
Normal file
71
app/src/main/res/layout/item_character.xml
Normal file
@@ -0,0 +1,71 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="168dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="16dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_character"
|
||||
android:layout_width="168dp"
|
||||
android:layout_height="168dp"
|
||||
android:background="@color/color_777777"
|
||||
android:scaleType="centerCrop" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="6dp"
|
||||
android:layout_marginTop="4dp"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_character_name"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="@font/pretendard_regular"
|
||||
android:textColor="@color/color_b0bec5"
|
||||
android:textSize="18sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_character_description"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="6dp"
|
||||
android:layout_marginTop="4dp"
|
||||
android:fontFamily="@font/pretendard_regular"
|
||||
android:textColor="#78909C"
|
||||
android:textSize="14sp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- 순위 표시 (인기 캐릭터에서만 보임) -->
|
||||
<LinearLayout
|
||||
android:id="@+id/ll_ranking"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom"
|
||||
android:background="@drawable/gradient_ranking_bg"
|
||||
android:gravity="center"
|
||||
android:orientation="horizontal"
|
||||
android:paddingHorizontal="16dp"
|
||||
android:paddingVertical="8dp"
|
||||
android:visibility="gone">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_ranking"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="@font/pretendard_bold"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="72sp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</FrameLayout>
|
||||
36
app/src/main/res/layout/item_curation_section.xml
Normal file
36
app/src/main/res/layout/item_curation_section.xml
Normal file
@@ -0,0 +1,36 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="48dp"
|
||||
android:orientation="vertical">
|
||||
|
||||
<!-- 제목 -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal"
|
||||
android:paddingHorizontal="24dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_section_title"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:fontFamily="@font/pretendard_bold"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="24sp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- 캐릭터 카드 리스트 -->
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/rv_characters"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:clipToPadding="false"
|
||||
android:paddingStart="24dp" />
|
||||
|
||||
</LinearLayout>
|
||||
27
app/src/main/res/layout/item_recent_character.xml
Normal file
27
app/src/main/res/layout/item_recent_character.xml
Normal file
@@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="76dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_profile"
|
||||
android:layout_width="76dp"
|
||||
android:layout_height="76dp"
|
||||
android:background="@color/color_777777"
|
||||
android:contentDescription="@null"
|
||||
android:scaleType="centerCrop" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_name"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="6dp"
|
||||
android:ellipsize="end"
|
||||
android:fontFamily="@font/pretendard_regular"
|
||||
android:gravity="center"
|
||||
android:maxLines="1"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="18sp" />
|
||||
</LinearLayout>
|
||||
Reference in New Issue
Block a user