feat(character detail): 캐릭터 상세 페이지 UI 추가
This commit is contained in:
		@@ -282,5 +282,8 @@
 | 
			
		||||
            android:name="com.facebook.FacebookActivity"
 | 
			
		||||
            android:configChanges="keyboard|keyboardHidden|screenLayout|screenSize|orientation" />
 | 
			
		||||
        <!-- [END facebook] -->
 | 
			
		||||
 | 
			
		||||
        <!-- Character Detail -->
 | 
			
		||||
        <activity android:name=".chat.character.detail.CharacterDetailActivity" />
 | 
			
		||||
    </application>
 | 
			
		||||
</manifest>
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,207 @@
 | 
			
		||||
package kr.co.vividnext.sodalive.chat.character.detail
 | 
			
		||||
 | 
			
		||||
import android.content.Intent
 | 
			
		||||
import android.graphics.Rect
 | 
			
		||||
import android.os.Bundle
 | 
			
		||||
import android.text.TextUtils
 | 
			
		||||
import android.view.View
 | 
			
		||||
import androidx.activity.viewModels
 | 
			
		||||
import androidx.core.net.toUri
 | 
			
		||||
import androidx.recyclerview.widget.LinearLayoutManager
 | 
			
		||||
import androidx.recyclerview.widget.RecyclerView
 | 
			
		||||
import coil.load
 | 
			
		||||
import kr.co.vividnext.sodalive.R
 | 
			
		||||
import kr.co.vividnext.sodalive.base.BaseActivity
 | 
			
		||||
import kr.co.vividnext.sodalive.databinding.ActivityCharacterDetailBinding
 | 
			
		||||
import kr.co.vividnext.sodalive.extensions.dpToPx
 | 
			
		||||
 | 
			
		||||
class CharacterDetailActivity : BaseActivity<ActivityCharacterDetailBinding>(
 | 
			
		||||
    ActivityCharacterDetailBinding::inflate
 | 
			
		||||
) {
 | 
			
		||||
    private val viewModel: CharacterDetailViewModel by viewModels()
 | 
			
		||||
 | 
			
		||||
    private val adapter by lazy {
 | 
			
		||||
        OtherCharacterAdapter(
 | 
			
		||||
            onItemClick = { item ->
 | 
			
		||||
                startActivity(
 | 
			
		||||
                    Intent(this, CharacterDetailActivity::class.java).apply {
 | 
			
		||||
                        putExtra(EXTRA_CHARACTER_ID, item.characterId)
 | 
			
		||||
                    }
 | 
			
		||||
                )
 | 
			
		||||
            }
 | 
			
		||||
        )
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private var isWorldviewExpanded = false
 | 
			
		||||
    private var isPersonalityExpanded = false
 | 
			
		||||
 | 
			
		||||
    override fun onCreate(savedInstanceState: Bundle?) {
 | 
			
		||||
        super.onCreate(savedInstanceState)
 | 
			
		||||
        // 더미 데이터 로드 (추후 Intent/Repository 연동)
 | 
			
		||||
        val characterId = intent.getLongExtra(EXTRA_CHARACTER_ID, 0)
 | 
			
		||||
 | 
			
		||||
//        if (characterId <= 0) {
 | 
			
		||||
//            showToast("잘못된 접근 입니다.")
 | 
			
		||||
//            finish()
 | 
			
		||||
//        }
 | 
			
		||||
 | 
			
		||||
        viewModel.loadMock(characterId)
 | 
			
		||||
        bindObservers()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override fun setupView() {
 | 
			
		||||
        // 뒤로 가기
 | 
			
		||||
        binding.detailToolbar.tvBack.setOnClickListener { finish() }
 | 
			
		||||
 | 
			
		||||
        // 다른 캐릭터 리스트: 가로 스크롤
 | 
			
		||||
        val recyclerView = binding.rvOtherCharacters
 | 
			
		||||
        recyclerView.layoutManager = LinearLayoutManager(
 | 
			
		||||
            this,
 | 
			
		||||
            LinearLayoutManager.HORIZONTAL,
 | 
			
		||||
            false
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        recyclerView.addItemDecoration(object : RecyclerView.ItemDecoration() {
 | 
			
		||||
            override fun getItemOffsets(
 | 
			
		||||
                outRect: Rect,
 | 
			
		||||
                view: View,
 | 
			
		||||
                parent: RecyclerView,
 | 
			
		||||
                state: RecyclerView.State
 | 
			
		||||
            ) {
 | 
			
		||||
                super.getItemOffsets(outRect, view, parent, state)
 | 
			
		||||
 | 
			
		||||
                when (parent.getChildAdapterPosition(view)) {
 | 
			
		||||
                    0 -> {
 | 
			
		||||
                        outRect.left = 0
 | 
			
		||||
                        outRect.right = 8f.dpToPx().toInt()
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    adapter.itemCount - 1 -> {
 | 
			
		||||
                        outRect.left = 8f.dpToPx().toInt()
 | 
			
		||||
                        outRect.right = 0
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    else -> {
 | 
			
		||||
                        outRect.left = 8f.dpToPx().toInt()
 | 
			
		||||
                        outRect.right = 8f.dpToPx().toInt()
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        })
 | 
			
		||||
 | 
			
		||||
        recyclerView.adapter = adapter
 | 
			
		||||
 | 
			
		||||
        // 세계관 전체보기 토글 클릭 리스너
 | 
			
		||||
        binding.llWorldviewExpand.setOnClickListener {
 | 
			
		||||
            toggleWorldviewExpand()
 | 
			
		||||
        }
 | 
			
		||||
        // 성격 전체보기 토글 클릭 리스너
 | 
			
		||||
        binding.llPersonalityExpand.setOnClickListener {
 | 
			
		||||
            togglePersonalityExpand()
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun bindObservers() {
 | 
			
		||||
        viewModel.uiState.observe(this) { state ->
 | 
			
		||||
            val detail = state.detail ?: return@observe
 | 
			
		||||
 | 
			
		||||
            // 배경 이미지
 | 
			
		||||
            binding.ivCharacterBackground.load(detail.imageUrl) { crossfade(true) }
 | 
			
		||||
 | 
			
		||||
            // 기본 정보
 | 
			
		||||
            binding.detailToolbar.tvBack.text = detail.name
 | 
			
		||||
            binding.tvCharacterName.text = detail.name
 | 
			
		||||
            binding.tvCharacterStatus.text = when (detail.characterType) {
 | 
			
		||||
                CharacterType.CLONE -> "Clone"
 | 
			
		||||
                CharacterType.CHARACTER -> "Character"
 | 
			
		||||
            }
 | 
			
		||||
            // 캐릭터 타입에 따른 배경 설정
 | 
			
		||||
            binding.tvCharacterStatus.setBackgroundResource(
 | 
			
		||||
                when (detail.characterType) {
 | 
			
		||||
                    CharacterType.CLONE -> R.drawable.bg_character_status_clone
 | 
			
		||||
                    CharacterType.CHARACTER -> R.drawable.bg_character_status_character
 | 
			
		||||
                }
 | 
			
		||||
            )
 | 
			
		||||
            binding.tvCharacterDescription.text = detail.description
 | 
			
		||||
            binding.tvCharacterTags.text = detail.tags
 | 
			
		||||
 | 
			
		||||
            // 세계관 내용과 버튼 가시성 초기화
 | 
			
		||||
            val worldviewText = detail.backgrounds?.description.orEmpty()
 | 
			
		||||
            binding.tvWorldviewContent.text = worldviewText
 | 
			
		||||
            applyWorldviewCollapsedLayout()
 | 
			
		||||
            binding.tvWorldviewContent.post {
 | 
			
		||||
                val needExpand = binding.tvWorldviewContent.lineCount > 3
 | 
			
		||||
                binding.llWorldviewExpand.visibility = if (needExpand) View.VISIBLE else View.GONE
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // 성격 내용과 버튼 가시성 초기화
 | 
			
		||||
            val personalityText = detail.personalities?.description.orEmpty()
 | 
			
		||||
            binding.tvPersonalityContent.text = personalityText
 | 
			
		||||
            applyPersonalityCollapsedLayout()
 | 
			
		||||
            binding.tvPersonalityContent.post {
 | 
			
		||||
                val needExpand = binding.tvPersonalityContent.lineCount > 3
 | 
			
		||||
                binding.llPersonalityExpand.visibility = if (needExpand) View.VISIBLE else View.GONE
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // 원작 섹션 표시/숨김
 | 
			
		||||
            if (detail.originalTitle.isNullOrBlank() || detail.originalLink.isNullOrBlank()) {
 | 
			
		||||
                binding.llOriginalSection.visibility = View.GONE
 | 
			
		||||
            } else {
 | 
			
		||||
                binding.llOriginalSection.visibility = View.VISIBLE
 | 
			
		||||
                binding.tvOriginalContent.text = detail.originalTitle
 | 
			
		||||
                binding.tvOriginalLink.setOnClickListener {
 | 
			
		||||
                    runCatching {
 | 
			
		||||
                        startActivity(Intent(Intent.ACTION_VIEW, detail.originalLink.toUri()))
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // 다른 캐릭터 리스트
 | 
			
		||||
            adapter.submitList(detail.others)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun toggleWorldviewExpand() {
 | 
			
		||||
        isWorldviewExpanded = !isWorldviewExpanded
 | 
			
		||||
        if (isWorldviewExpanded) {
 | 
			
		||||
            // 확장 상태
 | 
			
		||||
            binding.tvWorldviewContent.maxLines = Integer.MAX_VALUE
 | 
			
		||||
            binding.tvWorldviewContent.ellipsize = null
 | 
			
		||||
            binding.tvWorldviewExpand.text = "간략히"
 | 
			
		||||
            binding.ivWorldviewExpand.setImageResource(R.drawable.ic_chevron_up)
 | 
			
		||||
        } else {
 | 
			
		||||
            // 접힘 상태 (3줄)
 | 
			
		||||
            applyWorldviewCollapsedLayout()
 | 
			
		||||
            binding.tvWorldviewExpand.text = "전체보기"
 | 
			
		||||
            binding.ivWorldviewExpand.setImageResource(R.drawable.ic_chevron_down)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun applyWorldviewCollapsedLayout() {
 | 
			
		||||
        binding.tvWorldviewContent.maxLines = 3
 | 
			
		||||
        binding.tvWorldviewContent.ellipsize = TextUtils.TruncateAt.END
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun togglePersonalityExpand() {
 | 
			
		||||
        isPersonalityExpanded = !isPersonalityExpanded
 | 
			
		||||
        if (isPersonalityExpanded) {
 | 
			
		||||
            binding.tvPersonalityContent.maxLines = Integer.MAX_VALUE
 | 
			
		||||
            binding.tvPersonalityContent.ellipsize = null
 | 
			
		||||
            binding.tvPersonalityExpand.text = "간략히"
 | 
			
		||||
            binding.ivPersonalityExpand.setImageResource(R.drawable.ic_chevron_up)
 | 
			
		||||
        } else {
 | 
			
		||||
            applyPersonalityCollapsedLayout()
 | 
			
		||||
            binding.tvPersonalityExpand.text = "전체보기"
 | 
			
		||||
            binding.ivPersonalityExpand.setImageResource(R.drawable.ic_chevron_down)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun applyPersonalityCollapsedLayout() {
 | 
			
		||||
        binding.tvPersonalityContent.maxLines = 3
 | 
			
		||||
        binding.tvPersonalityContent.ellipsize = TextUtils.TruncateAt.END
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    companion object {
 | 
			
		||||
        const val EXTRA_CHARACTER_ID = "extra_character_id"
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,48 @@
 | 
			
		||||
package kr.co.vividnext.sodalive.chat.character.detail
 | 
			
		||||
 | 
			
		||||
import androidx.annotation.Keep
 | 
			
		||||
import com.google.gson.annotations.SerializedName
 | 
			
		||||
 | 
			
		||||
@Keep
 | 
			
		||||
data class CharacterDetailResponse(
 | 
			
		||||
    @SerializedName("characterId") val characterId: Long,
 | 
			
		||||
    @SerializedName("name") val name: String,
 | 
			
		||||
    @SerializedName("description") val description: String,
 | 
			
		||||
    @SerializedName("mbti") val mbti: String?,
 | 
			
		||||
    @SerializedName("imageUrl") val imageUrl: String,
 | 
			
		||||
    @SerializedName("personalities") val personalities: CharacterPersonalityResponse?,
 | 
			
		||||
    @SerializedName("backgrounds") val backgrounds: CharacterBackgroundResponse?,
 | 
			
		||||
    @SerializedName("tags") val tags: String,
 | 
			
		||||
    @SerializedName("originalTitle") val originalTitle: String?,
 | 
			
		||||
    @SerializedName("originalLink") val originalLink: String?,
 | 
			
		||||
    @SerializedName("characterType") val characterType: CharacterType,
 | 
			
		||||
    @SerializedName("others") val others: List<OtherCharacter>
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
@Keep
 | 
			
		||||
enum class CharacterType {
 | 
			
		||||
    @SerializedName("CLONE")
 | 
			
		||||
    CLONE,
 | 
			
		||||
    @SerializedName("CHARACTER")
 | 
			
		||||
    CHARACTER
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@Keep
 | 
			
		||||
data class OtherCharacter(
 | 
			
		||||
    @SerializedName("characterId") val characterId: Long,
 | 
			
		||||
    @SerializedName("name") val name: String,
 | 
			
		||||
    @SerializedName("imageUrl") val imageUrl: String,
 | 
			
		||||
    @SerializedName("tags") val tags: String
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
@Keep
 | 
			
		||||
data class CharacterPersonalityResponse(
 | 
			
		||||
    @SerializedName("trait") val trait: String,
 | 
			
		||||
    @SerializedName("description") val description: String
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
@Keep
 | 
			
		||||
data class CharacterBackgroundResponse(
 | 
			
		||||
    @SerializedName("topic") val topic: String,
 | 
			
		||||
    @SerializedName("description") val description: String
 | 
			
		||||
)
 | 
			
		||||
@@ -0,0 +1,73 @@
 | 
			
		||||
package kr.co.vividnext.sodalive.chat.character.detail
 | 
			
		||||
 | 
			
		||||
import androidx.lifecycle.LiveData
 | 
			
		||||
import androidx.lifecycle.MutableLiveData
 | 
			
		||||
import kr.co.vividnext.sodalive.base.BaseViewModel
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 캐릭터 상세 화면에서 사용하는 ViewModel.
 | 
			
		||||
 * - 캐릭터 명과 상태
 | 
			
		||||
 * - 캐릭터 소개
 | 
			
		||||
 * - 태그 문자열 (예: "#태그1 #태그2")
 | 
			
		||||
 * - 세계관 내용 (3줄 이상일 경우 전체보기 토글)
 | 
			
		||||
 * - 원작 섹션 (빈 값이면 UI에서 숨김)
 | 
			
		||||
 * - 다른 캐릭터 목록 (이미지, 캐릭터 명, 태그)
 | 
			
		||||
 */
 | 
			
		||||
class CharacterDetailViewModel : BaseViewModel() {
 | 
			
		||||
    // UiState를 CharacterDetailResponse 구조에 맞게 변경
 | 
			
		||||
    data class UiState(
 | 
			
		||||
        val detail: CharacterDetailResponse? = null
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    private val _uiState = MutableLiveData(UiState())
 | 
			
		||||
    val uiState: LiveData<UiState> get() = _uiState
 | 
			
		||||
 | 
			
		||||
    fun loadMock(characterId: Long) {
 | 
			
		||||
        // TODO: Repository 연동 예정. 현재는 더미 데이터로 표시
 | 
			
		||||
        val demoWorldview = CharacterBackgroundResponse(
 | 
			
		||||
            topic = "세계관",
 | 
			
		||||
            description = "특별한 꽃을 길러낼 수 있는 능력을 가진 리엘라.\n그녀는 호손 공작의 상속자가 되고 말아버리는데...\n\n뜻하지 않은 만남과 비밀이 펼쳐진다."
 | 
			
		||||
        )
 | 
			
		||||
        val demoPersonality = CharacterPersonalityResponse(
 | 
			
		||||
            trait = "밝음, 고집",
 | 
			
		||||
            description = "밝고 쾌활하지만 고집이 있으며, 친구를 소중히 여기고 어려움 앞에서도 물러서지 않습니다.\n상황에 따라 유연하게 대처하지만 신념은 확고합니다.\n\n상황에 따라 유연하게 대처하지만 신념은 확고합니다.\n\n\n상황에 따라 유연하게 대처하지만 신념은 확고합니다."
 | 
			
		||||
        )
 | 
			
		||||
        val others = listOf(
 | 
			
		||||
            OtherCharacter(
 | 
			
		||||
                characterId = 1,
 | 
			
		||||
                name = "엘리시아",
 | 
			
		||||
                imageUrl = "https://picsum.photos/seed/char1/300/300",
 | 
			
		||||
                tags = "#마법 #학생 #쾌활"
 | 
			
		||||
            ),
 | 
			
		||||
            OtherCharacter(
 | 
			
		||||
                characterId = 2,
 | 
			
		||||
                name = "루카",
 | 
			
		||||
                imageUrl = "https://picsum.photos/seed/char2/300/300",
 | 
			
		||||
                tags = "#기사 #충직 #과묵"
 | 
			
		||||
            ),
 | 
			
		||||
            OtherCharacter(
 | 
			
		||||
                characterId = 3,
 | 
			
		||||
                name = "세라",
 | 
			
		||||
                imageUrl = "https://picsum.photos/seed/char3/300/300",
 | 
			
		||||
                tags = "#암살자 #쿨 #시크"
 | 
			
		||||
            )
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        val response = CharacterDetailResponse(
 | 
			
		||||
            characterId = characterId,
 | 
			
		||||
            name = "리엘라",
 | 
			
		||||
            description = "꽃을 키우는 공작가의 상속자",
 | 
			
		||||
            mbti = "ENFP",
 | 
			
		||||
            imageUrl = "https://picsum.photos/seed/bg1/1000/1000",
 | 
			
		||||
            personalities = demoPersonality,
 | 
			
		||||
            backgrounds = demoWorldview,
 | 
			
		||||
            tags = "#커버곡 #라이브 #연애 #썸 #채팅 #라방",
 | 
			
		||||
            originalTitle = "네이버 시리즈 독 안에 든 선생님",
 | 
			
		||||
            originalLink = "https://series.naver.com/",
 | 
			
		||||
            characterType = CharacterType.CLONE,
 | 
			
		||||
            others = others
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        _uiState.value = UiState(detail = response)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,58 @@
 | 
			
		||||
package kr.co.vividnext.sodalive.chat.character.detail
 | 
			
		||||
 | 
			
		||||
import android.annotation.SuppressLint
 | 
			
		||||
import android.view.LayoutInflater
 | 
			
		||||
import android.view.ViewGroup
 | 
			
		||||
import androidx.recyclerview.widget.RecyclerView
 | 
			
		||||
import coil.load
 | 
			
		||||
import coil.transform.RoundedCornersTransformation
 | 
			
		||||
import kr.co.vividnext.sodalive.R
 | 
			
		||||
import kr.co.vividnext.sodalive.databinding.ItemOtherCharacterBinding
 | 
			
		||||
import kr.co.vividnext.sodalive.extensions.dpToPx
 | 
			
		||||
 | 
			
		||||
class OtherCharacterAdapter(
 | 
			
		||||
    private var items: List<OtherCharacter> = emptyList(),
 | 
			
		||||
    private val onItemClick: ((OtherCharacter) -> Unit)? = null
 | 
			
		||||
) : RecyclerView.Adapter<OtherCharacterAdapter.OtherCharacterViewHolder>() {
 | 
			
		||||
 | 
			
		||||
    @SuppressLint("NotifyDataSetChanged")
 | 
			
		||||
    fun submitList(newItems: List<OtherCharacter>) {
 | 
			
		||||
        items = newItems
 | 
			
		||||
        notifyDataSetChanged()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): OtherCharacterViewHolder {
 | 
			
		||||
        return OtherCharacterViewHolder(
 | 
			
		||||
            ItemOtherCharacterBinding.inflate(
 | 
			
		||||
                LayoutInflater.from(parent.context),
 | 
			
		||||
                parent,
 | 
			
		||||
                false
 | 
			
		||||
            )
 | 
			
		||||
        )
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override fun onBindViewHolder(holder: OtherCharacterViewHolder, position: Int) {
 | 
			
		||||
        holder.bind(items[position])
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override fun getItemCount(): Int = items.size
 | 
			
		||||
 | 
			
		||||
    inner class OtherCharacterViewHolder(
 | 
			
		||||
        private val binding: ItemOtherCharacterBinding
 | 
			
		||||
    ) : RecyclerView.ViewHolder(binding.root) {
 | 
			
		||||
        fun bind(item: OtherCharacter) {
 | 
			
		||||
            binding.tvName.text = item.name
 | 
			
		||||
            binding.tvTags.text = item.tags
 | 
			
		||||
            binding.ivThumb.load(item.imageUrl) {
 | 
			
		||||
                crossfade(true)
 | 
			
		||||
                placeholder(R.drawable.ic_place_holder)
 | 
			
		||||
                transformations(RoundedCornersTransformation(16f.dpToPx()))
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
            binding.root.setOnClickListener {
 | 
			
		||||
                onItemClick?.invoke(item)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,6 @@
 | 
			
		||||
<?xml version="1.0" encoding="utf-8"?>
 | 
			
		||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
 | 
			
		||||
    android:shape="rectangle">
 | 
			
		||||
    <solid android:color="#009D68" />
 | 
			
		||||
    <corners android:radius="6dp" />
 | 
			
		||||
</shape>
 | 
			
		||||
							
								
								
									
										6
									
								
								app/src/main/res/drawable/bg_character_status_clone.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								app/src/main/res/drawable/bg_character_status_clone.xml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,6 @@
 | 
			
		||||
<?xml version="1.0" encoding="utf-8"?>
 | 
			
		||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
 | 
			
		||||
    android:shape="rectangle">
 | 
			
		||||
    <solid android:color="#0020C9" />
 | 
			
		||||
    <corners android:radius="6dp" />
 | 
			
		||||
</shape>
 | 
			
		||||
@@ -0,0 +1,6 @@
 | 
			
		||||
<?xml version="1.0" encoding="utf-8"?>
 | 
			
		||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
 | 
			
		||||
    android:shape="rectangle">
 | 
			
		||||
    <solid android:color="#F86660" />
 | 
			
		||||
    <corners android:radius="6dp" />
 | 
			
		||||
</shape>
 | 
			
		||||
@@ -0,0 +1,6 @@
 | 
			
		||||
<?xml version="1.0" encoding="utf-8"?>
 | 
			
		||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
 | 
			
		||||
    android:shape="rectangle">
 | 
			
		||||
    <corners android:radius="16dp" />
 | 
			
		||||
    <solid android:color="@color/color_3bb9f1" />
 | 
			
		||||
</shape>
 | 
			
		||||
@@ -0,0 +1,9 @@
 | 
			
		||||
<?xml version="1.0" encoding="utf-8"?>
 | 
			
		||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
 | 
			
		||||
    android:shape="rectangle">
 | 
			
		||||
    <solid android:color="@android:color/transparent" />
 | 
			
		||||
    <stroke
 | 
			
		||||
        android:width="1dp"
 | 
			
		||||
        android:color="#37474F" />
 | 
			
		||||
    <corners android:radius="16dp" />
 | 
			
		||||
</shape>
 | 
			
		||||
@@ -0,0 +1,9 @@
 | 
			
		||||
<?xml version="1.0" encoding="utf-8"?>
 | 
			
		||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
 | 
			
		||||
    android:shape="rectangle">
 | 
			
		||||
    <solid android:color="@android:color/transparent" />
 | 
			
		||||
    <stroke
 | 
			
		||||
        android:width="1dp"
 | 
			
		||||
        android:color="#3BB9F1" />
 | 
			
		||||
    <corners android:radius="16dp" />
 | 
			
		||||
</shape>
 | 
			
		||||
							
								
								
									
										14
									
								
								app/src/main/res/drawable/ic_chevron_down.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								app/src/main/res/drawable/ic_chevron_down.xml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,14 @@
 | 
			
		||||
<?xml version="1.0" encoding="utf-8"?>
 | 
			
		||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
 | 
			
		||||
    android:width="24dp"
 | 
			
		||||
    android:height="24dp"
 | 
			
		||||
    android:viewportWidth="24"
 | 
			
		||||
    android:viewportHeight="24">
 | 
			
		||||
    <path
 | 
			
		||||
        android:fillColor="@android:color/transparent"
 | 
			
		||||
        android:strokeColor="#607D8B"
 | 
			
		||||
        android:strokeWidth="2"
 | 
			
		||||
        android:strokeLineCap="round"
 | 
			
		||||
        android:strokeLineJoin="round"
 | 
			
		||||
        android:pathData="M7,10L12,15L17,10" />
 | 
			
		||||
</vector>
 | 
			
		||||
							
								
								
									
										14
									
								
								app/src/main/res/drawable/ic_chevron_up.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								app/src/main/res/drawable/ic_chevron_up.xml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,14 @@
 | 
			
		||||
<?xml version="1.0" encoding="utf-8"?>
 | 
			
		||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
 | 
			
		||||
    android:width="24dp"
 | 
			
		||||
    android:height="24dp"
 | 
			
		||||
    android:viewportWidth="24"
 | 
			
		||||
    android:viewportHeight="24">
 | 
			
		||||
    <path
 | 
			
		||||
        android:fillColor="@android:color/transparent"
 | 
			
		||||
        android:strokeColor="#607D8B"
 | 
			
		||||
        android:strokeWidth="2"
 | 
			
		||||
        android:strokeLineCap="round"
 | 
			
		||||
        android:strokeLineJoin="round"
 | 
			
		||||
        android:pathData="M17,14L12,9L7,14" />
 | 
			
		||||
</vector>
 | 
			
		||||
							
								
								
									
										389
									
								
								app/src/main/res/layout/activity_character_detail.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										389
									
								
								app/src/main/res/layout/activity_character_detail.xml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,389 @@
 | 
			
		||||
<?xml version="1.0" encoding="utf-8"?>
 | 
			
		||||
<RelativeLayout 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"
 | 
			
		||||
    android:layout_width="match_parent"
 | 
			
		||||
    android:layout_height="match_parent"
 | 
			
		||||
    android:background="@color/color_131313">
 | 
			
		||||
 | 
			
		||||
    <!-- 상단 툴바 -->
 | 
			
		||||
    <include
 | 
			
		||||
        android:id="@+id/detail_toolbar"
 | 
			
		||||
        layout="@layout/detail_toolbar" />
 | 
			
		||||
 | 
			
		||||
    <!-- 메인 스크롤 영역 -->
 | 
			
		||||
    <androidx.core.widget.NestedScrollView
 | 
			
		||||
        android:id="@+id/scroll_view_character_detail"
 | 
			
		||||
        android:layout_width="match_parent"
 | 
			
		||||
        android:layout_height="match_parent"
 | 
			
		||||
        android:layout_above="@+id/btn_chat"
 | 
			
		||||
        android:layout_below="@+id/detail_toolbar"
 | 
			
		||||
        android:clipToPadding="false"
 | 
			
		||||
        android:fillViewport="true">
 | 
			
		||||
 | 
			
		||||
        <LinearLayout
 | 
			
		||||
            android:layout_width="match_parent"
 | 
			
		||||
            android:layout_height="wrap_content"
 | 
			
		||||
            android:orientation="vertical">
 | 
			
		||||
 | 
			
		||||
            <!-- 캐릭터 이미지 및 프로필 영역 -->
 | 
			
		||||
            <androidx.constraintlayout.widget.ConstraintLayout
 | 
			
		||||
                android:id="@+id/rl_character_profile"
 | 
			
		||||
                android:layout_width="match_parent"
 | 
			
		||||
                android:layout_height="wrap_content"
 | 
			
		||||
                android:layout_marginBottom="16dp">
 | 
			
		||||
 | 
			
		||||
                <!-- 캐릭터 배경 이미지 -->
 | 
			
		||||
                <ImageView
 | 
			
		||||
                    android:id="@+id/iv_character_background"
 | 
			
		||||
                    android:layout_width="0dp"
 | 
			
		||||
                    android:layout_height="0dp"
 | 
			
		||||
                    android:contentDescription="@null"
 | 
			
		||||
                    android:scaleType="centerCrop"
 | 
			
		||||
                    app:layout_constraintBottom_toBottomOf="parent"
 | 
			
		||||
                    app:layout_constraintDimensionRatio="1:1"
 | 
			
		||||
                    app:layout_constraintEnd_toEndOf="parent"
 | 
			
		||||
                    app:layout_constraintStart_toStartOf="parent"
 | 
			
		||||
                    app:layout_constraintTop_toTopOf="parent" />
 | 
			
		||||
 | 
			
		||||
                <!-- 딤 처리 -->
 | 
			
		||||
                <View
 | 
			
		||||
                    android:id="@+id/view_character_dim"
 | 
			
		||||
                    android:layout_width="0dp"
 | 
			
		||||
                    android:layout_height="0dp"
 | 
			
		||||
                    android:background="@color/color_99000000"
 | 
			
		||||
                    app:layout_constraintBottom_toBottomOf="parent"
 | 
			
		||||
                    app:layout_constraintEnd_toEndOf="parent"
 | 
			
		||||
                    app:layout_constraintStart_toStartOf="parent"
 | 
			
		||||
                    app:layout_constraintTop_toTopOf="parent" />
 | 
			
		||||
 | 
			
		||||
                <!-- 캐릭터 정보 -->
 | 
			
		||||
                <LinearLayout
 | 
			
		||||
                    android:id="@+id/ll_character_info"
 | 
			
		||||
                    android:layout_width="0dp"
 | 
			
		||||
                    android:layout_height="wrap_content"
 | 
			
		||||
                    android:layout_marginHorizontal="24dp"
 | 
			
		||||
                    android:layout_marginBottom="24dp"
 | 
			
		||||
                    android:orientation="vertical"
 | 
			
		||||
                    app:layout_constraintBottom_toBottomOf="parent"
 | 
			
		||||
                    app:layout_constraintEnd_toEndOf="parent"
 | 
			
		||||
                    app:layout_constraintStart_toStartOf="parent">
 | 
			
		||||
 | 
			
		||||
                    <!-- 캐릭터명과 상태 -->
 | 
			
		||||
                    <LinearLayout
 | 
			
		||||
                        android:id="@+id/ll_character_name_status"
 | 
			
		||||
                        android:layout_width="match_parent"
 | 
			
		||||
                        android:layout_height="wrap_content"
 | 
			
		||||
                        android:gravity="center_vertical"
 | 
			
		||||
                        android:orientation="horizontal">
 | 
			
		||||
 | 
			
		||||
                        <TextView
 | 
			
		||||
                            android:id="@+id/tv_character_name"
 | 
			
		||||
                            android:layout_width="wrap_content"
 | 
			
		||||
                            android:layout_height="wrap_content"
 | 
			
		||||
                            android:fontFamily="@font/pretendard_bold"
 | 
			
		||||
                            android:textColor="@color/white"
 | 
			
		||||
                            android:textSize="26sp"
 | 
			
		||||
                            tools:text="캐릭터명" />
 | 
			
		||||
 | 
			
		||||
                        <TextView
 | 
			
		||||
                            android:id="@+id/tv_character_status"
 | 
			
		||||
                            android:layout_width="wrap_content"
 | 
			
		||||
                            android:layout_height="wrap_content"
 | 
			
		||||
                            android:layout_marginStart="8dp"
 | 
			
		||||
                            android:background="@drawable/bg_character_status_clone"
 | 
			
		||||
                            android:fontFamily="@font/pretendard_regular"
 | 
			
		||||
                            android:paddingHorizontal="5dp"
 | 
			
		||||
                            android:paddingVertical="1dp"
 | 
			
		||||
                            android:textColor="@color/white"
 | 
			
		||||
                            android:textSize="12sp"
 | 
			
		||||
                            tools:text="Clone" />
 | 
			
		||||
                    </LinearLayout>
 | 
			
		||||
 | 
			
		||||
                    <!-- 캐릭터 소개 -->
 | 
			
		||||
                    <TextView
 | 
			
		||||
                        android:id="@+id/tv_character_description"
 | 
			
		||||
                        android:layout_width="match_parent"
 | 
			
		||||
                        android:layout_height="wrap_content"
 | 
			
		||||
                        android:layout_marginTop="8dp"
 | 
			
		||||
                        android:fontFamily="@font/pretendard_regular"
 | 
			
		||||
                        android:textColor="@color/color_b0bec5"
 | 
			
		||||
                        android:textSize="18sp"
 | 
			
		||||
                        tools:text="캐릭터 한줄 소개" />
 | 
			
		||||
 | 
			
		||||
                    <!-- 태그 -->
 | 
			
		||||
                    <TextView
 | 
			
		||||
                        android:id="@+id/tv_character_tags"
 | 
			
		||||
                        android:layout_width="match_parent"
 | 
			
		||||
                        android:layout_height="wrap_content"
 | 
			
		||||
                        android:layout_marginTop="8dp"
 | 
			
		||||
                        android:fontFamily="@font/pretendard_regular"
 | 
			
		||||
                        android:textColor="@color/color_3bb9f1"
 | 
			
		||||
                        android:textSize="14sp"
 | 
			
		||||
                        tools:text="#커버곡 #라이브 #연애 #썸 #채팅 #라방" />
 | 
			
		||||
                </LinearLayout>
 | 
			
		||||
            </androidx.constraintlayout.widget.ConstraintLayout>
 | 
			
		||||
 | 
			
		||||
            <!-- 세계관 섹션 -->
 | 
			
		||||
            <LinearLayout
 | 
			
		||||
                android:id="@+id/ll_worldview_section"
 | 
			
		||||
                android:layout_width="match_parent"
 | 
			
		||||
                android:layout_height="wrap_content"
 | 
			
		||||
                android:layout_marginHorizontal="24dp"
 | 
			
		||||
                android:layout_marginBottom="16dp"
 | 
			
		||||
                android:orientation="vertical">
 | 
			
		||||
 | 
			
		||||
                <!-- 섹션 제목 -->
 | 
			
		||||
                <TextView
 | 
			
		||||
                    android:id="@+id/tv_worldview_title"
 | 
			
		||||
                    android:layout_width="match_parent"
 | 
			
		||||
                    android:layout_height="wrap_content"
 | 
			
		||||
                    android:fontFamily="@font/pretendard_bold"
 | 
			
		||||
                    android:text="세계관"
 | 
			
		||||
                    android:textColor="@color/white"
 | 
			
		||||
                    android:textSize="16sp" />
 | 
			
		||||
 | 
			
		||||
                <!-- 세계관 내용 -->
 | 
			
		||||
                <TextView
 | 
			
		||||
                    android:id="@+id/tv_worldview_content"
 | 
			
		||||
                    android:layout_width="match_parent"
 | 
			
		||||
                    android:layout_height="wrap_content"
 | 
			
		||||
                    android:layout_marginTop="8dp"
 | 
			
		||||
                    android:fontFamily="@font/pretendard_regular"
 | 
			
		||||
                    android:lineSpacingExtra="4dp"
 | 
			
		||||
                    android:textColor="@color/color_b0bec5"
 | 
			
		||||
                    android:textSize="16sp"
 | 
			
		||||
                    tools:text="특별한 꽃을 길러낼 수 있는 능력을 가진 리엘라.\n\n그녀는 호손 공작의 상속자가 되고 말아버리는데..." />
 | 
			
		||||
 | 
			
		||||
                <!-- 전체보기 버튼 -->
 | 
			
		||||
                <LinearLayout
 | 
			
		||||
                    android:id="@+id/ll_worldview_expand"
 | 
			
		||||
                    android:layout_width="wrap_content"
 | 
			
		||||
                    android:layout_height="wrap_content"
 | 
			
		||||
                    android:layout_gravity="end"
 | 
			
		||||
                    android:layout_marginTop="8dp"
 | 
			
		||||
                    android:gravity="center_vertical"
 | 
			
		||||
                    android:orientation="horizontal">
 | 
			
		||||
 | 
			
		||||
                    <ImageView
 | 
			
		||||
                        android:id="@+id/iv_worldview_expand"
 | 
			
		||||
                        android:layout_width="20dp"
 | 
			
		||||
                        android:layout_height="20dp"
 | 
			
		||||
                        android:contentDescription="@null"
 | 
			
		||||
                        android:src="@drawable/ic_chevron_down" />
 | 
			
		||||
 | 
			
		||||
                    <TextView
 | 
			
		||||
                        android:id="@+id/tv_worldview_expand"
 | 
			
		||||
                        android:layout_width="wrap_content"
 | 
			
		||||
                        android:layout_height="wrap_content"
 | 
			
		||||
                        android:fontFamily="@font/pretendard_regular"
 | 
			
		||||
                        android:text="전체보기"
 | 
			
		||||
                        android:textColor="@color/color_607d8b"
 | 
			
		||||
                        android:textSize="14sp" />
 | 
			
		||||
                </LinearLayout>
 | 
			
		||||
            </LinearLayout>
 | 
			
		||||
 | 
			
		||||
            <!-- 성격 섹션 (세계관과 동일 UI) -->
 | 
			
		||||
            <LinearLayout
 | 
			
		||||
                android:id="@+id/ll_personality_section"
 | 
			
		||||
                android:layout_width="match_parent"
 | 
			
		||||
                android:layout_height="wrap_content"
 | 
			
		||||
                android:layout_marginHorizontal="24dp"
 | 
			
		||||
                android:layout_marginBottom="16dp"
 | 
			
		||||
                android:orientation="vertical">
 | 
			
		||||
 | 
			
		||||
                <!-- 섹션 제목 -->
 | 
			
		||||
                <TextView
 | 
			
		||||
                    android:id="@+id/tv_personality_title"
 | 
			
		||||
                    android:layout_width="match_parent"
 | 
			
		||||
                    android:layout_height="wrap_content"
 | 
			
		||||
                    android:fontFamily="@font/pretendard_bold"
 | 
			
		||||
                    android:text="성격"
 | 
			
		||||
                    android:textColor="@color/white"
 | 
			
		||||
                    android:textSize="16sp" />
 | 
			
		||||
 | 
			
		||||
                <!-- 성격 내용 -->
 | 
			
		||||
                <TextView
 | 
			
		||||
                    android:id="@+id/tv_personality_content"
 | 
			
		||||
                    android:layout_width="match_parent"
 | 
			
		||||
                    android:layout_height="wrap_content"
 | 
			
		||||
                    android:layout_marginTop="8dp"
 | 
			
		||||
                    android:fontFamily="@font/pretendard_regular"
 | 
			
		||||
                    android:lineSpacingExtra="4dp"
 | 
			
		||||
                    android:textColor="@color/color_b0bec5"
 | 
			
		||||
                    android:textSize="16sp"
 | 
			
		||||
                    tools:text="밝고 쾌활하지만 때로는 고집이 센 면모도 있습니다.\n\n친구를 소중히 여기며, 어려움 앞에서도 물러서지 않습니다." />
 | 
			
		||||
 | 
			
		||||
                <!-- 전체보기 버튼 -->
 | 
			
		||||
                <LinearLayout
 | 
			
		||||
                    android:id="@+id/ll_personality_expand"
 | 
			
		||||
                    android:layout_width="wrap_content"
 | 
			
		||||
                    android:layout_height="wrap_content"
 | 
			
		||||
                    android:layout_gravity="end"
 | 
			
		||||
                    android:layout_marginTop="8dp"
 | 
			
		||||
                    android:gravity="center_vertical"
 | 
			
		||||
                    android:orientation="horizontal">
 | 
			
		||||
 | 
			
		||||
                    <ImageView
 | 
			
		||||
                        android:id="@+id/iv_personality_expand"
 | 
			
		||||
                        android:layout_width="20dp"
 | 
			
		||||
                        android:layout_height="20dp"
 | 
			
		||||
                        android:contentDescription="@null"
 | 
			
		||||
                        android:src="@drawable/ic_chevron_down" />
 | 
			
		||||
 | 
			
		||||
                    <TextView
 | 
			
		||||
                        android:id="@+id/tv_personality_expand"
 | 
			
		||||
                        android:layout_width="wrap_content"
 | 
			
		||||
                        android:layout_height="wrap_content"
 | 
			
		||||
                        android:fontFamily="@font/pretendard_regular"
 | 
			
		||||
                        android:text="전체보기"
 | 
			
		||||
                        android:textColor="@color/color_607d8b"
 | 
			
		||||
                        android:textSize="14sp" />
 | 
			
		||||
                </LinearLayout>
 | 
			
		||||
            </LinearLayout>
 | 
			
		||||
 | 
			
		||||
            <!-- 원작 섹션 -->
 | 
			
		||||
            <LinearLayout
 | 
			
		||||
                android:id="@+id/ll_original_section"
 | 
			
		||||
                android:layout_width="match_parent"
 | 
			
		||||
                android:layout_height="wrap_content"
 | 
			
		||||
                android:layout_marginHorizontal="24dp"
 | 
			
		||||
                android:layout_marginBottom="16dp"
 | 
			
		||||
                android:orientation="vertical">
 | 
			
		||||
 | 
			
		||||
                <!-- 섹션 제목 -->
 | 
			
		||||
                <TextView
 | 
			
		||||
                    android:id="@+id/tv_original_title"
 | 
			
		||||
                    android:layout_width="match_parent"
 | 
			
		||||
                    android:layout_height="wrap_content"
 | 
			
		||||
                    android:fontFamily="@font/pretendard_bold"
 | 
			
		||||
                    android:text="[원작]"
 | 
			
		||||
                    android:textColor="@color/white"
 | 
			
		||||
                    android:textSize="16sp" />
 | 
			
		||||
 | 
			
		||||
                <!-- 원작 내용 -->
 | 
			
		||||
                <TextView
 | 
			
		||||
                    android:id="@+id/tv_original_content"
 | 
			
		||||
                    android:layout_width="match_parent"
 | 
			
		||||
                    android:layout_height="wrap_content"
 | 
			
		||||
                    android:layout_marginTop="8dp"
 | 
			
		||||
                    android:fontFamily="@font/pretendard_regular"
 | 
			
		||||
                    android:textColor="@color/color_b0bec5"
 | 
			
		||||
                    android:textSize="16sp"
 | 
			
		||||
                    tools:text="네이버 시리즈 독 안에 든 선생님" />
 | 
			
		||||
 | 
			
		||||
                <!-- 원작 보러가기 버튼 -->
 | 
			
		||||
                <TextView
 | 
			
		||||
                    android:id="@+id/tv_original_link"
 | 
			
		||||
                    android:layout_width="match_parent"
 | 
			
		||||
                    android:layout_height="54dp"
 | 
			
		||||
                    android:layout_marginTop="8dp"
 | 
			
		||||
                    android:background="@drawable/bg_round_corner_16_stroke_3bb9f1"
 | 
			
		||||
                    android:fontFamily="@font/pretendard_bold"
 | 
			
		||||
                    android:gravity="center"
 | 
			
		||||
                    android:text="원작 보러가기"
 | 
			
		||||
                    android:textColor="@color/color_3bb9f1"
 | 
			
		||||
                    android:textSize="16sp" />
 | 
			
		||||
            </LinearLayout>
 | 
			
		||||
 | 
			
		||||
            <!-- 캐릭터톡 대화 가이드 섹션 -->
 | 
			
		||||
            <LinearLayout
 | 
			
		||||
                android:id="@+id/ll_chat_guide_section"
 | 
			
		||||
                android:layout_width="match_parent"
 | 
			
		||||
                android:layout_height="wrap_content"
 | 
			
		||||
                android:layout_marginHorizontal="24dp"
 | 
			
		||||
                android:layout_marginBottom="24dp"
 | 
			
		||||
                android:background="@drawable/bg_round_corner_16_stroke_37474f"
 | 
			
		||||
                android:orientation="vertical"
 | 
			
		||||
                android:paddingHorizontal="16dp"
 | 
			
		||||
                android:paddingVertical="12dp">
 | 
			
		||||
 | 
			
		||||
                <!-- 가이드 제목 -->
 | 
			
		||||
                <TextView
 | 
			
		||||
                    android:id="@+id/tv_chat_guide_title"
 | 
			
		||||
                    android:layout_width="match_parent"
 | 
			
		||||
                    android:layout_height="wrap_content"
 | 
			
		||||
                    android:fontFamily="@font/pretendard_bold"
 | 
			
		||||
                    android:text="⚠️ 캐릭터톡 대화 가이드"
 | 
			
		||||
                    android:textColor="@color/color_b0bec5"
 | 
			
		||||
                    android:textSize="16sp" />
 | 
			
		||||
 | 
			
		||||
                <!-- 가이드 내용 -->
 | 
			
		||||
                <TextView
 | 
			
		||||
                    android:id="@+id/tv_chat_guide_content"
 | 
			
		||||
                    android:layout_width="match_parent"
 | 
			
		||||
                    android:layout_height="wrap_content"
 | 
			
		||||
                    android:layout_marginTop="8dp"
 | 
			
		||||
                    android:fontFamily="@font/pretendard_regular"
 | 
			
		||||
                    android:lineSpacingExtra="4dp"
 | 
			
		||||
                    android:text="보이스온 AI캐릭터톡은 대화의 자유도가 높아 대화에 참여하는 당신은 누구든 될 수 있습니다.\n\n세계관 속 캐릭터로 대화를 하거나 새로운 인물로\n캐릭터와 당신만의 스토리를 만들어보세요."
 | 
			
		||||
                    android:textColor="@color/color_7c7c80"
 | 
			
		||||
                    android:textSize="16sp" />
 | 
			
		||||
 | 
			
		||||
                <!-- 주의사항 -->
 | 
			
		||||
                <TextView
 | 
			
		||||
                    android:id="@+id/tv_chat_guide_notice"
 | 
			
		||||
                    android:layout_width="match_parent"
 | 
			
		||||
                    android:layout_height="wrap_content"
 | 
			
		||||
                    android:layout_marginTop="8dp"
 | 
			
		||||
                    android:fontFamily="@font/pretendard_regular"
 | 
			
		||||
                    android:lineSpacingExtra="4dp"
 | 
			
		||||
                    android:text="※ AI캐릭터톡은 오픈베타 서비스 중이며, 캐릭터의 대화가 어색하거나 불완전할 수 있습니다. 대화 초반에 캐릭터 붕괴가 느껴진다면 대화를 리셋하고 다시 시도해보세요."
 | 
			
		||||
                    android:textColor="@color/color_7c7c80"
 | 
			
		||||
                    android:textSize="14sp" />
 | 
			
		||||
            </LinearLayout>
 | 
			
		||||
 | 
			
		||||
            <!-- 장르의 다른 캐릭터 섹션 -->
 | 
			
		||||
            <LinearLayout
 | 
			
		||||
                android:id="@+id/ll_other_characters_section"
 | 
			
		||||
                android:layout_width="match_parent"
 | 
			
		||||
                android:layout_height="wrap_content"
 | 
			
		||||
                android:layout_marginBottom="24dp"
 | 
			
		||||
                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_other_characters_title"
 | 
			
		||||
                        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="26sp" />
 | 
			
		||||
                </LinearLayout>
 | 
			
		||||
 | 
			
		||||
                <!-- 캐릭터 리스트 -->
 | 
			
		||||
                <androidx.recyclerview.widget.RecyclerView
 | 
			
		||||
                    android:id="@+id/rv_other_characters"
 | 
			
		||||
                    android:layout_width="match_parent"
 | 
			
		||||
                    android:layout_height="wrap_content"
 | 
			
		||||
                    android:layout_marginTop="16dp"
 | 
			
		||||
                    android:clipToPadding="false"
 | 
			
		||||
                    android:paddingHorizontal="24dp" />
 | 
			
		||||
            </LinearLayout>
 | 
			
		||||
        </LinearLayout>
 | 
			
		||||
    </androidx.core.widget.NestedScrollView>
 | 
			
		||||
 | 
			
		||||
    <!-- 하단 고정 대화하기 버튼 -->
 | 
			
		||||
    <TextView
 | 
			
		||||
        android:id="@+id/btn_chat"
 | 
			
		||||
        android:layout_width="match_parent"
 | 
			
		||||
        android:layout_height="54dp"
 | 
			
		||||
        android:layout_alignParentBottom="true"
 | 
			
		||||
        android:layout_marginHorizontal="24dp"
 | 
			
		||||
        android:layout_marginBottom="10dp"
 | 
			
		||||
        android:background="@drawable/bg_round_corner_16_solid_3bb9f1"
 | 
			
		||||
        android:fontFamily="@font/pretendard_bold"
 | 
			
		||||
        android:gravity="center"
 | 
			
		||||
        android:text="대화하기"
 | 
			
		||||
        android:textColor="@color/white"
 | 
			
		||||
        android:textSize="16sp" />
 | 
			
		||||
</RelativeLayout>
 | 
			
		||||
							
								
								
									
										38
									
								
								app/src/main/res/layout/item_other_character.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								app/src/main/res/layout/item_other_character.xml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,38 @@
 | 
			
		||||
<?xml version="1.0" encoding="utf-8"?>
 | 
			
		||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 | 
			
		||||
    xmlns:tools="http://schemas.android.com/tools"
 | 
			
		||||
    android:layout_width="168dp"
 | 
			
		||||
    android:layout_height="wrap_content"
 | 
			
		||||
    android:orientation="vertical">
 | 
			
		||||
 | 
			
		||||
    <ImageView
 | 
			
		||||
        android:id="@+id/iv_thumb"
 | 
			
		||||
        android:layout_width="match_parent"
 | 
			
		||||
        android:layout_height="168dp"
 | 
			
		||||
        android:contentDescription="@null" />
 | 
			
		||||
 | 
			
		||||
    <TextView
 | 
			
		||||
        android:id="@+id/tv_name"
 | 
			
		||||
        android:layout_width="match_parent"
 | 
			
		||||
        android:layout_height="wrap_content"
 | 
			
		||||
        android:layout_marginTop="8dp"
 | 
			
		||||
        android:ellipsize="end"
 | 
			
		||||
        android:fontFamily="@font/pretendard_bold"
 | 
			
		||||
        android:maxLines="1"
 | 
			
		||||
        android:textColor="@color/white"
 | 
			
		||||
        android:textSize="14sp"
 | 
			
		||||
        tools:text="이름" />
 | 
			
		||||
 | 
			
		||||
    <TextView
 | 
			
		||||
        android:id="@+id/tv_tags"
 | 
			
		||||
        android:layout_width="match_parent"
 | 
			
		||||
        android:layout_height="wrap_content"
 | 
			
		||||
        android:layout_marginTop="4dp"
 | 
			
		||||
        android:ellipsize="end"
 | 
			
		||||
        android:fontFamily="@font/pretendard_regular"
 | 
			
		||||
        android:maxLines="1"
 | 
			
		||||
        android:textColor="@color/color_3bb9f1"
 | 
			
		||||
        android:textSize="12sp"
 | 
			
		||||
        tools:text="#태그" />
 | 
			
		||||
 | 
			
		||||
</LinearLayout>
 | 
			
		||||
@@ -133,4 +133,6 @@
 | 
			
		||||
    <color name="color_7849bc">#7849BC</color>
 | 
			
		||||
    <color name="color_607d8b">#607D8B</color>
 | 
			
		||||
    <color name="color_b0bec5">#B0BEC5</color>
 | 
			
		||||
    <color name="color_7c7c80">#7C7C80</color>
 | 
			
		||||
    <color name="color_37474f">#37474F</color>
 | 
			
		||||
</resources>
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user