feat(chat): 메시지 괄호 지문 색상을 회색으로 변경

This commit is contained in:
2025-08-27 14:10:30 +09:00
parent a941d0bfab
commit 02df0b6774
2 changed files with 52 additions and 2 deletions

View File

@@ -6,8 +6,13 @@
package kr.co.vividnext.sodalive.chat.talk.room package kr.co.vividnext.sodalive.chat.talk.room
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.graphics.Typeface
import android.os.Bundle import android.os.Bundle
import android.text.SpannableStringBuilder
import android.text.Spanned
import android.text.TextUtils import android.text.TextUtils
import android.text.style.ForegroundColorSpan
import android.text.style.StyleSpan
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
@@ -16,6 +21,7 @@ import android.view.animation.AnimationUtils
import android.widget.TextView import android.widget.TextView
import androidx.annotation.LayoutRes import androidx.annotation.LayoutRes
import androidx.annotation.VisibleForTesting import androidx.annotation.VisibleForTesting
import androidx.core.content.ContextCompat
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
@@ -106,6 +112,41 @@ class ChatMessageAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
val isLast = !isSameSender(curr, next) val isLast = !isSameSender(curr, next)
return grouped to isLast return grouped to isLast
} }
// 소괄호 텍스트 스타일링 유틸: 회색 + 기울임꼴
private val PAREN_REGEX = Regex("\\([^()]*\\)")
fun applyParentheticalStyle(tv: TextView, raw: CharSequence?, color: Int? = null) {
if (raw.isNullOrEmpty()) {
tv.text = raw ?: ""
return
}
val text = raw.toString()
val builder = SpannableStringBuilder(text)
val targetColor = color ?: ContextCompat.getColor(
tv.context,
R.color.color_7fe2e2e2
)
PAREN_REGEX.findAll(text).forEach { match ->
val start = match.range.first
val end = match.range.last + 1
if (start in 0 until end && end <= builder.length) {
builder.setSpan(
ForegroundColorSpan(targetColor),
start,
end,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
)
builder.setSpan(
StyleSpan(Typeface.ITALIC),
start,
end,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
)
}
}
tv.text = builder
}
} }
private val items: MutableList<ChatListItem> = mutableListOf() private val items: MutableList<ChatListItem> = mutableListOf()
@@ -414,7 +455,14 @@ class ChatMessageAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
private val binding: ItemChatUserMessageBinding private val binding: ItemChatUserMessageBinding
) : RecyclerView.ViewHolder(binding.root) { ) : RecyclerView.ViewHolder(binding.root) {
fun bind(data: ChatMessage, showTime: Boolean, isGrouped: Boolean) { fun bind(data: ChatMessage, showTime: Boolean, isGrouped: Boolean) {
binding.tvMessage.text = data.message applyParentheticalStyle(
binding.tvMessage,
data.message,
ContextCompat.getColor(
binding.root.context,
R.color.color_333333
)
)
// 화면 너비의 65%를 최대 폭으로 적용 // 화면 너비의 65%를 최대 폭으로 적용
binding.tvMessage.maxWidth = binding.tvMessage.maxWidth =
(itemView.resources.displayMetrics.widthPixels * 0.65f).toInt() (itemView.resources.displayMetrics.widthPixels * 0.65f).toInt()
@@ -542,7 +590,7 @@ class ChatMessageAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
// 텍스트 메시지 // 텍스트 메시지
binding.imageContainer.visibility = View.GONE binding.imageContainer.visibility = View.GONE
binding.messageContainer.visibility = View.VISIBLE binding.messageContainer.visibility = View.VISIBLE
binding.tvMessage.text = data.message applyParentheticalStyle(binding.tvMessage, data.message)
binding.tvMessage.maxWidth = binding.tvMessage.maxWidth =
(itemView.resources.displayMetrics.widthPixels * 0.90f).toInt() (itemView.resources.displayMetrics.widthPixels * 0.90f).toInt()
} }

View File

@@ -96,6 +96,8 @@ class ChatRoomActivity : BaseActivity<ActivityChatRoomBinding>(
binding.tvName.text = "" binding.tvName.text = ""
binding.ivProfile.setImageResource(R.drawable.ic_placeholder_profile) binding.ivProfile.setImageResource(R.drawable.ic_placeholder_profile)
binding.ivBackgroundProfile.setImageResource(R.drawable.ic_placeholder_profile) binding.ivBackgroundProfile.setImageResource(R.drawable.ic_placeholder_profile)
// 저장된 배경이 있으면 즉시 적용 (네트워크 응답 전 초기 진입에서도 반영)
applyBackgroundFromPrefsOrProfile("")
// 배지는 기본 Clone으로 둔다가 실제 값으로 갱신 (디자인 기본 배경도 clone) // 배지는 기본 Clone으로 둔다가 실제 값으로 갱신 (디자인 기본 배경도 clone)
binding.tvCharacterTypeBadge.text = "Clone" binding.tvCharacterTypeBadge.text = "Clone"
binding.tvCharacterTypeBadge.setBackgroundResource(R.drawable.bg_character_status_clone) binding.tvCharacterTypeBadge.setBackgroundResource(R.drawable.bg_character_status_clone)