心情素材对应替换

This commit is contained in:
ddshi 2025-10-27 11:35:40 +08:00
parent 874b83b5a2
commit 37e1f1bd3e
67 changed files with 222 additions and 24 deletions

View File

@ -24,7 +24,13 @@
"Bash(magick:*)",
"Bash(convert:*)",
"Bash(python:*)",
"Bash(rm:*)"
"Bash(rm:*)",
"Bash(cp:*)",
"Bash(robocopy:*)",
"Bash(dir:*)",
"Bash(copy:*)",
"Bash(.gradlew:*)",
"Bash(gradlew.bat assembleDebug:*)"
],
"deny": [],
"ask": []

View File

@ -4,15 +4,26 @@ import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.chick_mood.data.model.Emotion
import com.chick_mood.utils.EmotionResourceManager
import com.daodaoshi.chick_mood.databinding.ItemChickImageBinding
/**
* 小鸡形象数据类
* @param emotion 情绪类型
* @param moodValue 心情值 (0-100)
*/
data class ChickEmotionData(
val emotion: Emotion,
val moodValue: Int = 50 // 默认值
)
/**
* 小鸡形象适配器
* 用于展示不同情绪对应的小鸡图标
* 用于展示不同情绪和心情值对应的小鸡图标
*/
class ChickImageAdapter : RecyclerView.Adapter<ChickImageAdapter.ChickImageViewHolder>() {
private var emotions: List<Emotion> = emptyList()
private var chickEmotions: List<ChickEmotionData> = emptyList()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ChickImageViewHolder {
val binding = ItemChickImageBinding.inflate(
@ -22,16 +33,24 @@ class ChickImageAdapter : RecyclerView.Adapter<ChickImageAdapter.ChickImageViewH
}
override fun onBindViewHolder(holder: ChickImageViewHolder, position: Int) {
holder.bind(emotions[position])
holder.bind(chickEmotions[position])
}
override fun getItemCount(): Int = emotions.size
override fun getItemCount(): Int = chickEmotions.size
/**
* 更新数据
*/
fun updateData(newEmotions: List<Emotion>) {
emotions = newEmotions
fun updateData(newChickEmotions: List<ChickEmotionData>) {
chickEmotions = newChickEmotions
notifyDataSetChanged()
}
/**
* 更新数据兼容旧版本只提供情绪类型
*/
fun updateDataFromEmotions(newEmotions: List<Emotion>) {
chickEmotions = newEmotions.map { ChickEmotionData(it) }
notifyDataSetChanged()
}
@ -39,18 +58,14 @@ class ChickImageAdapter : RecyclerView.Adapter<ChickImageAdapter.ChickImageViewH
private val binding: ItemChickImageBinding
) : RecyclerView.ViewHolder(binding.root) {
fun bind(emotion: Emotion) {
// 根据情绪类型设置对应的小鸡图标
val chickDrawable = when (emotion) {
Emotion.HAPPY -> com.daodaoshi.chick_mood.R.drawable.ic_placeholder_chick_happy
Emotion.SAD -> com.daodaoshi.chick_mood.R.drawable.ic_placeholder_chick_sad
Emotion.ANGRY -> com.daodaoshi.chick_mood.R.drawable.ic_placeholder_chick_angry
Emotion.WORRIED -> com.daodaoshi.chick_mood.R.drawable.ic_placeholder_chick_worried
Emotion.LONELY -> com.daodaoshi.chick_mood.R.drawable.ic_placeholder_chick_lonely
Emotion.SCARED -> com.daodaoshi.chick_mood.R.drawable.ic_placeholder_chick_scared
}
fun bind(chickEmotionData: ChickEmotionData) {
// 直接使用新的表情资源,自动处理找不到资源的情况
val resourceId = EmotionResourceManager.getEmotionResourceId(
chickEmotionData.emotion,
chickEmotionData.moodValue
)
binding.ivChick.setImageResource(chickDrawable)
binding.ivChick.setImageResource(resourceId)
}
}
}

View File

@ -0,0 +1,152 @@
package com.chick_mood.utils
import com.chick_mood.data.model.Emotion
import com.daodaoshi.chick_mood.R
/**
* 心情表情资源映射器
* 根据情绪类型和心情值动态选择对应的表情图片
*/
object EmotionResourceManager {
/**
* 根据情绪类型和心情值获取对应的表情资源名称
* @param emotion 情绪类型
* @param moodValue 心情值 (0-100)
* @return 表情资源名称英文名称
*/
fun getEmotionResourceName(emotion: Emotion, moodValue: Int): String {
val degreeLevel = getDegreeLevel(moodValue)
val emotionPrefix = getEmotionEnglishPrefix(emotion)
return "${emotionPrefix}_${degreeLevel}"
}
/**
* 根据心情值获取程度级别
* @param moodValue 心情值 (0-100)
* @return 程度级别描述
*/
private fun getDegreeLevel(moodValue: Int): String {
return when (moodValue) {
in 0..20 -> "level1" // 有些
in 21..40 -> "level2" // 非常
in 41..60 -> "level3" // 超级
in 61..80 -> "level4" // 超级非常
in 81..100 -> "level5" // 无法控制
else -> "level1"
}
}
/**
* 根据情绪类型获取对应的英文前缀
* @param emotion 情绪类型
* @return 英文前缀
*/
private fun getEmotionEnglishPrefix(emotion: Emotion): String {
return when (emotion) {
Emotion.HAPPY -> "happy"
Emotion.SAD -> "sad"
Emotion.ANGRY -> "angry"
Emotion.WORRIED -> "worried"
Emotion.LONELY -> "lonely"
Emotion.SCARED -> "scared"
}
}
/**
* 获取情绪选择弹窗中使用的表情资源基础表情
* 在心情选择界面使用统一的基础表情
* @param emotion 情绪类型
* @return 基础表情资源ID
*/
fun getEmotionSelectionResource(emotion: Emotion): String {
return when (emotion) {
Emotion.HAPPY -> "ic_emotion_happy"
Emotion.SAD -> "ic_emotion_sad"
Emotion.ANGRY -> "ic_emotion_angry"
Emotion.WORRIED -> "ic_emotion_worried"
Emotion.LONELY -> "ic_emotion_lonely"
Emotion.SCARED -> "ic_emotion_scared"
}
}
/**
* 获取基于心情值的表情资源ID
* @param emotion 情绪类型
* @param moodValue 心情值 (0-100)
* @return 表情资源ID如果找不到则返回占位符资源
*/
fun getEmotionResourceId(emotion: Emotion, moodValue: Int): Int {
val degreeLevel = getDegreeLevel(moodValue)
val emotionPrefix = getEmotionEnglishPrefix(emotion)
val resourceName = "${emotionPrefix}_${degreeLevel}"
return try {
// 使用反射获取资源ID
val resourceIdField = R.drawable::class.java.getDeclaredField(resourceName)
resourceIdField.getInt(null)
} catch (e: Exception) {
// 如果找不到对应的表情资源,返回占位符资源
getPlaceholderResourceId(emotion)
}
}
/**
* 获取占位符资源ID
* @param emotion 情绪类型
* @return 占位符资源ID
*/
private fun getPlaceholderResourceId(emotion: Emotion): Int {
return when (emotion) {
Emotion.HAPPY -> R.drawable.ic_placeholder_chick_happy
Emotion.SAD -> R.drawable.ic_placeholder_chick_sad
Emotion.ANGRY -> R.drawable.ic_placeholder_chick_angry
Emotion.WORRIED -> R.drawable.ic_placeholder_chick_worried
Emotion.LONELY -> R.drawable.ic_placeholder_chick_lonely
Emotion.SCARED -> R.drawable.ic_placeholder_chick_scared
}
}
/**
* 获取占位符小鸡表情资源
* 在没有心情值数据时使用的默认表情
* @param emotion 情绪类型
* @return 占位符资源ID
*/
fun getPlaceholderEmotionResource(emotion: Emotion): String {
return when (emotion) {
Emotion.HAPPY -> "ic_placeholder_chick_happy"
Emotion.SAD -> "ic_placeholder_chick_sad"
Emotion.ANGRY -> "ic_placeholder_chick_angry"
Emotion.WORRIED -> "ic_placeholder_chick_worried"
Emotion.LONELY -> "ic_placeholder_chick_lonely"
Emotion.SCARED -> "ic_placeholder_chick_scared"
}
}
/**
* 根据心情值和情绪类型获取表情图片文件的完整路径
* 这个方法用于后续直接复制文件到drawable目录后的资源引用
*/
fun getEmotionImagePath(emotion: Emotion, moodValue: Int): String {
val degreeLevel = when {
moodValue <= 20 -> "有些"
moodValue <= 40 -> "非常"
moodValue <= 60 -> "超级"
moodValue <= 80 -> "这也太"
else -> "无法控制"
}
val emotionName = when (emotion) {
Emotion.HAPPY -> "开心"
Emotion.SAD -> "悲伤"
Emotion.ANGRY -> "生气"
Emotion.WORRIED -> "烦恼"
Emotion.LONELY -> "孤单"
Emotion.SCARED -> "害怕"
}
return "${emotionName}${degreeLevel}"
}
}

View File

@ -24,6 +24,7 @@ import androidx.core.content.ContextCompat
import android.os.Vibrator
import android.os.VibrationEffect
import com.chick_mood.data.model.Emotion
import com.chick_mood.utils.EmotionResourceManager
import java.text.DecimalFormat
/**
@ -252,6 +253,9 @@ class AddActivity : AppCompatActivity(), SensorEventListener {
tvMoodText.text = "开始!"
tvMoodValue.text = moodValueFormatter.format(currentMoodValue)
progressBar.progress = 0
// 更新小鸡表情使用基础表情因为心情值为0
updateChickExpression()
}
/**
@ -284,10 +288,24 @@ class AddActivity : AppCompatActivity(), SensorEventListener {
tvMoodValue.text = moodValueFormatter.format(currentMoodValue)
progressBar.progress = currentMoodValue
// 更新小鸡表情(基于心情值和情绪类型)
updateChickExpression()
// 更新心情文案
updateMoodText()
}
/**
* 更新小鸡表情
*/
private fun updateChickExpression() {
selectedEmotion?.let { emotion ->
// 直接使用新的表情资源,自动处理找不到资源的情况
val resourceId = EmotionResourceManager.getEmotionResourceId(emotion, currentMoodValue)
ivChick.setImageResource(resourceId)
}
}
/**
* 更新心情文案
*/

View File

@ -14,6 +14,7 @@ import androidx.appcompat.app.AppCompatActivity
import com.chick_mood.data.database.SimpleDatabaseManager
import com.chick_mood.data.model.Emotion
import com.chick_mood.data.model.MoodRecord
import com.chick_mood.utils.EmotionResourceManager
import com.daodaoshi.chick_mood.ImageUtils
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
@ -88,8 +89,9 @@ class DetailActivity : AppCompatActivity() {
// 设置时间显示
timeText.text = formatTime(record.timestamp)
// 设置小鸡形象
chickImage.setImageResource(getEmotionIconResource(record.emotion))
// 设置小鸡形象(基于心情值和情绪类型)
val resourceId = EmotionResourceManager.getEmotionResourceId(record.emotion, record.moodIntensity)
chickImage.setImageResource(resourceId)
// 设置心情值和文案
moodValueText.text = record.moodIntensity.toString()

View File

@ -16,6 +16,7 @@ import androidx.appcompat.app.AppCompatActivity
import com.chick_mood.data.database.SimpleDatabaseManager
import com.chick_mood.data.model.Emotion
import com.chick_mood.data.model.MoodRecord
import com.chick_mood.utils.EmotionResourceManager
import com.daodaoshi.chick_mood.ImageUtils
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
@ -249,8 +250,9 @@ class EditActivity : AppCompatActivity() {
// 设置时间显示
timeText.text = formatTime(record.timestamp)
// 设置小鸡形象
chickImage.setImageResource(getEmotionIconResource(record.emotion))
// 设置小鸡形象(基于心情值和情绪类型)
val resourceId = EmotionResourceManager.getEmotionResourceId(record.emotion, record.moodIntensity)
chickImage.setImageResource(resourceId)
// 设置心情值和文案
moodValueText.text = record.moodIntensity.toString()

View File

@ -13,6 +13,7 @@ import com.chick_mood.data.database.SimpleDatabaseManager
import com.chick_mood.ui.emotion.EmotionSelectorDialog
import com.chick_mood.ui.adapter.MoodCardAdapter
import com.chick_mood.ui.adapter.ChickImageAdapter
import com.chick_mood.ui.adapter.ChickEmotionData
import com.chick_mood.data.model.Emotion
import com.chick_mood.data.model.MoodRecord
import java.text.SimpleDateFormat
@ -396,8 +397,10 @@ class MainActivitySimple : AppCompatActivity() {
moodCardAdapter.updateData(records)
// 更新小鸡形象适配器
val emotions = records.map { it.emotion }
chickImageAdapter.updateData(emotions)
val chickEmotions = records.map {
ChickEmotionData(it.emotion, it.moodIntensity)
}
chickImageAdapter.updateData(chickEmotions)
// 更新时间信息(显示第一条记录的时间)
updateTimeInfo(0)

Binary file not shown.

After

Width:  |  Height:  |  Size: 136 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 142 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 155 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 155 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 155 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 136 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 142 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 155 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 155 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 155 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 136 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 142 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 155 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 155 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 155 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 136 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 142 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 155 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 155 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 155 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 136 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 142 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 155 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 155 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 155 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 136 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 142 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 155 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 155 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 155 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 155 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 136 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 124 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 155 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 142 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 155 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 136 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 124 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 155 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 142 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 155 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 136 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 124 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 155 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 142 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 155 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 136 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 124 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 155 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 142 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 155 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 136 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 124 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 155 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 142 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 155 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 136 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 124 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 155 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 142 KiB