feat(widget): 캐릭터 채팅 썸네일 컴포넌트를 추가한다
This commit is contained in:
@@ -0,0 +1,19 @@
|
||||
package kr.co.vividnext.sodalive.v2.widget.characterchatthumbnail
|
||||
|
||||
import java.util.Locale
|
||||
import kotlin.math.floor
|
||||
|
||||
object CharacterChatCountFormatter {
|
||||
fun format(count: Long): String {
|
||||
val safeCount = count.coerceAtLeast(0)
|
||||
if (safeCount < 10_000) return safeCount.toString()
|
||||
if (safeCount >= 100_000) return "${safeCount / 10_000}만"
|
||||
|
||||
val value = safeCount / 10_000.0
|
||||
return if (safeCount % 10_000L == 0L) {
|
||||
"${safeCount / 10_000}만"
|
||||
} else {
|
||||
String.format(Locale.KOREAN, "%.1f만", floor(value * 10) / 10)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package kr.co.vividnext.sodalive.v2.widget.characterchatthumbnail
|
||||
|
||||
data class CharacterChatThumbnailItem(
|
||||
val characterId: Long,
|
||||
val imageUrl: String,
|
||||
val characterName: String,
|
||||
val characterDescription: String,
|
||||
val chatMessageCount: Long,
|
||||
val hasOriginal: Boolean,
|
||||
val originalTitle: String
|
||||
) {
|
||||
val shouldShowOriginalTitle: Boolean = hasOriginal
|
||||
|
||||
val shouldShowChatCountBadge: Boolean = chatMessageCount >= 100
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
package kr.co.vividnext.sodalive.v2.widget.characterchatthumbnail
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Outline
|
||||
import android.util.AttributeSet
|
||||
import android.view.View
|
||||
import android.view.ViewOutlineProvider
|
||||
import android.widget.FrameLayout
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import kr.co.vividnext.sodalive.R
|
||||
|
||||
class CharacterChatThumbnailView @JvmOverloads constructor(
|
||||
context: Context,
|
||||
attrs: AttributeSet? = null,
|
||||
defStyleAttr: Int = 0
|
||||
) : FrameLayout(context, attrs, defStyleAttr) {
|
||||
|
||||
private var image: ImageView? = null
|
||||
private var chatCountBadge: View? = null
|
||||
private var chatCountText: TextView? = null
|
||||
private var characterNameText: TextView? = null
|
||||
private var characterDescriptionText: TextView? = null
|
||||
private var originalTitleText: TextView? = null
|
||||
private var currentItem: CharacterChatThumbnailItem? = null
|
||||
private var clickListener: ((CharacterChatThumbnailItem) -> Unit)? = null
|
||||
|
||||
override fun onFinishInflate() {
|
||||
super.onFinishInflate()
|
||||
image = findViewById(R.id.iv_character_chat_thumbnail_image)
|
||||
chatCountBadge = findViewById(R.id.ll_character_chat_count_badge)
|
||||
chatCountText = findViewById(R.id.tv_character_chat_count)
|
||||
characterNameText = findViewById(R.id.tv_character_chat_name)
|
||||
characterDescriptionText = findViewById(R.id.tv_character_chat_description)
|
||||
originalTitleText = findViewById(R.id.tv_character_chat_original_title)
|
||||
clipToOutline = true
|
||||
outlineProvider = roundedCardOutlineProvider()
|
||||
}
|
||||
|
||||
fun bind(item: CharacterChatThumbnailItem) {
|
||||
currentItem = item
|
||||
requireNotNull(chatCountText).text = CharacterChatCountFormatter.format(item.chatMessageCount)
|
||||
requireNotNull(characterNameText).text = item.characterName
|
||||
requireNotNull(characterDescriptionText).text = item.characterDescription
|
||||
requireNotNull(originalTitleText).apply {
|
||||
text = item.originalTitle
|
||||
visibility = if (item.shouldShowOriginalTitle) View.VISIBLE else View.INVISIBLE
|
||||
}
|
||||
requireNotNull(chatCountBadge).visibility = if (item.shouldShowChatCountBadge) View.VISIBLE else View.GONE
|
||||
applyClickState(item)
|
||||
}
|
||||
|
||||
fun imageView(): ImageView = requireNotNull(image)
|
||||
|
||||
fun setOnCharacterClick(listener: ((CharacterChatThumbnailItem) -> Unit)?) {
|
||||
clickListener = listener
|
||||
currentItem?.let(::applyClickState)
|
||||
}
|
||||
|
||||
private fun applyClickState(item: CharacterChatThumbnailItem) {
|
||||
val listener = clickListener
|
||||
setOnClickListener(if (listener == null) null else View.OnClickListener { listener(item) })
|
||||
isClickable = listener != null
|
||||
}
|
||||
|
||||
private fun roundedCardOutlineProvider() = object : ViewOutlineProvider() {
|
||||
override fun getOutline(view: View, outline: Outline) {
|
||||
val radius = resources.getDimension(R.dimen.radius_14)
|
||||
outline.setRoundRect(0, 0, view.width, view.height, radius)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user