diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 7acf330..2986a42 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -23,6 +23,18 @@ + + + + \ No newline at end of file diff --git a/app/src/main/java/com/chick_mood/data/database/SimpleDatabaseManager.kt b/app/src/main/java/com/chick_mood/data/database/SimpleDatabaseManager.kt index c7e7c81..bb6ddab 100644 --- a/app/src/main/java/com/chick_mood/data/database/SimpleDatabaseManager.kt +++ b/app/src/main/java/com/chick_mood/data/database/SimpleDatabaseManager.kt @@ -104,6 +104,24 @@ class SimpleDatabaseManager private constructor(private val context: Context) { } } + /** + * 更新心情记录 + */ + suspend fun updateMoodRecord(moodRecord: MoodRecord): Int { + return withContext(Dispatchers.IO) { + database.moodRecordDao().updateMoodRecord(moodRecord) + } + } + + /** + * 删除心情记录 + */ + suspend fun deleteMoodRecord(id: Long): Int { + return withContext(Dispatchers.IO) { + database.moodRecordDao().deleteMoodRecordById(id) + } + } + // ==================== 用户配置操作 ==================== /** diff --git a/app/src/main/java/com/daodaoshi/chick_mood/DetailActivity.kt b/app/src/main/java/com/daodaoshi/chick_mood/DetailActivity.kt new file mode 100644 index 0000000..56d7624 --- /dev/null +++ b/app/src/main/java/com/daodaoshi/chick_mood/DetailActivity.kt @@ -0,0 +1,405 @@ +package com.daodaoshi.chick_mood + +import android.app.AlertDialog +import android.content.Intent +import android.os.Bundle +import android.util.Log +import android.view.LayoutInflater +import android.view.View +import android.widget.ImageView +import android.widget.LinearLayout +import android.widget.TextView +import android.widget.Toast +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 kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import java.text.SimpleDateFormat +import java.util.* + +/** + * 心情记录详情页 + * 展示单条心情记录的完整信息,支持查看、编辑、收藏、分享、删除等操作 + */ +class DetailActivity : AppCompatActivity() { + + private lateinit var backButton: ImageView + private lateinit var timeText: TextView + private lateinit var moreButton: ImageView + private lateinit var chickImage: ImageView + private lateinit var moodValueText: TextView + private lateinit var moodText: TextView + private lateinit var imageContent: ImageView + private lateinit var textContent: TextView + + private var currentRecord: MoodRecord? = null + private val databaseManager = SimpleDatabaseManager.getInstance(this) + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_detail) + + initViews() + loadData() + setupClickListeners() + } + + /** + * 初始化视图组件 + */ + private fun initViews() { + backButton = findViewById(R.id.back_button) + timeText = findViewById(R.id.time_text) + moreButton = findViewById(R.id.more_button) + chickImage = findViewById(R.id.chick_image) + moodValueText = findViewById(R.id.mood_value_text) + moodText = findViewById(R.id.mood_text) + imageContent = findViewById(R.id.image_content) + textContent = findViewById(R.id.text_content) + } + + /** + * 加载心情记录数据 + */ + private fun loadData() { + val recordId = intent.getLongExtra("record_id", -1L) + if (recordId == -1L) { + finish() + return + } + + // 从数据库获取记录 + loadRecordFromDatabase(recordId) + } + + /** + * 显示心情记录 + */ + private fun displayRecord(record: MoodRecord) { + // 设置时间显示 + timeText.text = formatTime(record.timestamp) + + // 设置小鸡形象 + chickImage.setImageResource(getEmotionIconResource(record.emotion)) + + // 设置心情值和文案 + moodValueText.text = record.moodIntensity.toString() + moodText.text = generateMoodText(record.moodIntensity, record.emotion) + + // 设置图片内容(如果有) + if (record.imagePath != null) { + imageContent.visibility = View.VISIBLE + // TODO: 加载实际图片 + imageContent.setImageResource(R.drawable.ic_placeholder_image) + } else { + imageContent.visibility = View.GONE + } + + // 设置文本内容(如果有) + if (!record.textContent.isNullOrBlank()) { + textContent.visibility = View.VISIBLE + textContent.text = record.textContent + } else { + textContent.visibility = View.GONE + } + } + + /** + * 设置点击监听器 + */ + private fun setupClickListeners() { + backButton.setOnClickListener { + finish() + } + + moreButton.setOnClickListener { + showMoreOptions() + } + + imageContent.setOnClickListener { + // 点击图片跳转到预览页面 + currentRecord?.imagePath?.let { imagePath -> + val intent = Intent(this, ImagePreviewActivity::class.java).apply { + putExtra("image_path", imagePath) + } + startActivity(intent) + } + } + } + + /** + * 显示更多操作选项 + */ + private fun showMoreOptions() { + val dialogView = LayoutInflater.from(this).inflate(R.layout.dialog_more_options, null) + val dialog = AlertDialog.Builder(this) + .setView(dialogView) + .create() + + dialog.window?.setBackgroundDrawableResource(android.R.color.transparent) + dialog.setCanceledOnTouchOutside(true) + + // 获取视图组件 + val llEdit = dialogView.findViewById(R.id.ll_edit) + val llFavorite = dialogView.findViewById(R.id.ll_favorite) + val llShare = dialogView.findViewById(R.id.ll_share) + val llDelete = dialogView.findViewById(R.id.ll_delete) + val ivFavoriteIcon = dialogView.findViewById(R.id.iv_favorite_icon) + val tvFavoriteText = dialogView.findViewById(R.id.tv_favorite_text) + + // 更新收藏状态UI + updateFavoriteUI(ivFavoriteIcon, tvFavoriteText, currentRecord?.isFavorite == true) + + // 设置点击事件 + llEdit.setOnClickListener { + dialog.dismiss() + // TODO: 跳转到编辑页 + showToast("编辑功能待实现") + } + + llFavorite.setOnClickListener { + dialog.dismiss() + toggleFavorite() + } + + llShare.setOnClickListener { + dialog.dismiss() + shareMoodRecord() + } + + llDelete.setOnClickListener { + dialog.dismiss() + showDeleteConfirmDialog() + } + + dialog.show() + } + + /** + * 从数据库加载心情记录 + */ + private fun loadRecordFromDatabase(recordId: Long) { + CoroutineScope(Dispatchers.IO).launch { + try { + val record = databaseManager.getMoodRecord(recordId) + + withContext(Dispatchers.Main) { + if (record != null) { + currentRecord = record + displayRecord(record) + } else { + // 如果没有找到记录,显示提示并关闭页面 + showToast("记录不存在") + finish() + } + } + } catch (e: Exception) { + Log.e("DetailActivity", "加载记录失败", e) + withContext(Dispatchers.Main) { + showToast("加载记录失败") + finish() + } + } + } + } + + + /** + * 格式化时间显示 + */ + private fun formatTime(timestamp: Long): String { + val now = System.currentTimeMillis() + val today = Calendar.getInstance().apply { + set(Calendar.HOUR_OF_DAY, 0) + set(Calendar.MINUTE, 0) + set(Calendar.SECOND, 0) + set(Calendar.MILLISECOND, 0) + }.timeInMillis + + val yesterday = today - 24 * 60 * 60 * 1000L + + val date = Date(timestamp) + val timeFormat = SimpleDateFormat("HH:mm", Locale.getDefault()) + val timeString = timeFormat.format(date) + + return when { + timestamp >= today -> "今天 $timeString" + timestamp >= yesterday -> "昨天 $timeString" + else -> { + val dateFormat = SimpleDateFormat("M月d日 HH:mm", Locale.getDefault()) + dateFormat.format(date) + } + } + } + + /** + * 生成心情文案 + */ + private fun generateMoodText(moodValue: Int, emotion: Emotion): String { + val degree = when { + moodValue <= 20 -> "有些" + moodValue <= 40 -> "非常" + moodValue <= 60 -> "超级" + moodValue <= 80 -> "这也太" + else -> "完全无法控制" + } + + return "$degree ${emotion.displayName}" + } + + /** + * 获取情绪图标资源 + */ + private fun getEmotionIconResource(emotion: Emotion): Int { + return when (emotion) { + Emotion.HAPPY -> R.drawable.ic_emotion_happy + Emotion.ANGRY -> R.drawable.ic_emotion_angry + Emotion.SAD -> R.drawable.ic_emotion_sad + Emotion.WORRIED -> R.drawable.ic_emotion_worried + Emotion.LONELY -> R.drawable.ic_emotion_lonely + Emotion.SCARED -> R.drawable.ic_emotion_scared + } + } + + /** + * 更新收藏状态UI + */ + private fun updateFavoriteUI(iconView: ImageView, textView: TextView, isFavorite: Boolean) { + if (isFavorite) { + iconView.setImageResource(R.drawable.ic_favorite_filled) + textView.text = "取消收藏" + } else { + iconView.setImageResource(R.drawable.ic_favorite_border) + textView.text = "收藏" + } + } + + /** + * 切换收藏状态 + */ + private fun toggleFavorite() { + currentRecord?.let { record -> + CoroutineScope(Dispatchers.IO).launch { + try { + val newFavoriteStatus = !record.isFavorite + val updatedRecord = record.copy(isFavorite = newFavoriteStatus) + + // 更新数据库 + databaseManager.updateMoodRecord(updatedRecord) + + withContext(Dispatchers.Main) { + currentRecord = updatedRecord + val message = if (newFavoriteStatus) "已收藏" else "已取消收藏" + showToast(message) + } + } catch (e: Exception) { + Log.e("DetailActivity", "更新收藏状态失败", e) + withContext(Dispatchers.Main) { + showToast("操作失败") + } + } + } + } + } + + /** + * 分享心情记录 + */ + private fun shareMoodRecord() { + currentRecord?.let { record -> + val emotionName = when (record.emotion) { + Emotion.HAPPY -> "开心" + Emotion.SAD -> "悲伤" + Emotion.ANGRY -> "生气" + Emotion.WORRIED -> "烦恼" + Emotion.LONELY -> "孤单" + Emotion.SCARED -> "害怕" + } + + val shareText = buildString { + if (!record.textContent.isNullOrBlank()) { + append(record.textContent) + append("\n\n") + } + append("心情:$emotionName") + append("\n心情值:${record.moodIntensity}") + append("\n文案:${generateMoodText(record.moodIntensity, record.emotion)}") + append("\n时间:${formatTime(record.timestamp)}") + } + + try { + val shareIntent = Intent().apply { + action = Intent.ACTION_SEND + type = "text/plain" + putExtra(Intent.EXTRA_TEXT, shareText) + putExtra(Intent.EXTRA_SUBJECT, "我的心情记录") + } + startActivity(Intent.createChooser(shareIntent, "分享心情记录")) + } catch (e: Exception) { + showToast("分享失败") + } + } + } + + /** + * 显示删除确认对话框 + */ + private fun showDeleteConfirmDialog() { + val dialogView = LayoutInflater.from(this).inflate(R.layout.dialog_delete_confirm, null) + val dialog = AlertDialog.Builder(this) + .setView(dialogView) + .create() + + dialog.window?.setBackgroundDrawableResource(android.R.color.transparent) + dialog.setCanceledOnTouchOutside(false) + + val tvCancel = dialogView.findViewById(R.id.tv_cancel) + val tvConfirm = dialogView.findViewById(R.id.tv_confirm) + + tvCancel.setOnClickListener { + dialog.dismiss() + } + + tvConfirm.setOnClickListener { + dialog.dismiss() + deleteMoodRecord() + } + + dialog.show() + } + + /** + * 删除心情记录 + */ + private fun deleteMoodRecord() { + currentRecord?.let { record -> + CoroutineScope(Dispatchers.IO).launch { + try { + // 从数据库删除记录 + databaseManager.deleteMoodRecord(record.id) + + withContext(Dispatchers.Main) { + showToast("记录已删除") + finish() // 返回首页 + } + } catch (e: Exception) { + Log.e("DetailActivity", "删除记录失败", e) + withContext(Dispatchers.Main) { + showToast("删除失败") + } + } + } + } + } + + /** + * 显示Toast消息 + */ + private fun showToast(message: String) { + Toast.makeText(this, message, Toast.LENGTH_SHORT).show() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/daodaoshi/chick_mood/ImagePreviewActivity.kt b/app/src/main/java/com/daodaoshi/chick_mood/ImagePreviewActivity.kt new file mode 100644 index 0000000..e4d7f19 --- /dev/null +++ b/app/src/main/java/com/daodaoshi/chick_mood/ImagePreviewActivity.kt @@ -0,0 +1,123 @@ +package com.daodaoshi.chick_mood + +import android.os.Bundle +import android.view.MotionEvent +import android.view.View +import android.widget.ImageView +import androidx.appcompat.app.AppCompatActivity +import com.daodaoshi.chick_mood.databinding.ActivityImagePreviewBinding + +/** + * 图片预览Activity + * 支持图片放大查看、手势缩放和拖拽 + */ +class ImagePreviewActivity : AppCompatActivity() { + + private lateinit var binding: ActivityImagePreviewBinding + private var currentScale = 1.0f + private var startX = 0f + private var startY = 0f + private var translateX = 0f + private var translateY = 0f + + companion object { + private const val MAX_SCALE = 3.0f + private const val MIN_SCALE = 1.0f + private const val TAG = "ImagePreviewActivity" + } + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + binding = ActivityImagePreviewBinding.inflate(layoutInflater) + setContentView(binding.root) + + initViews() + setupGestures() + } + + /** + * 初始化视图 + */ + private fun initViews() { + // 设置返回按钮点击事件 + binding.btnClose.setOnClickListener { + finish() + } + + // 设置背景点击关闭 + binding.root.setOnClickListener { + finish() + } + + // 获取图片路径并加载图片 + val imagePath = intent.getStringExtra("image_path") + if (imagePath != null) { + // TODO: 使用图片加载库加载实际图片 + // 这里暂时使用占位图 + binding.imagePreview.setImageResource(R.drawable.ic_placeholder_image) + } else { + finish() // 没有图片路径则关闭 + } + } + + /** + * 设置手势操作 + */ + private fun setupGestures() { + binding.imagePreview.setOnTouchListener { view, event -> + when (event.action and MotionEvent.ACTION_MASK) { + MotionEvent.ACTION_DOWN -> { + startX = event.x - translateX + startY = event.y - translateY + true + } + MotionEvent.ACTION_MOVE -> { + translateX = event.x - startX + translateY = event.y - startY + updateImageTransform() + true + } + MotionEvent.ACTION_POINTER_DOWN -> { + // 双指缩放逻辑 + true + } + MotionEvent.ACTION_UP -> { + true + } + else -> false + } + } + } + + /** + * 更新图片变换 + */ + private fun updateImageTransform() { + binding.imagePreview.apply { + translationX = translateX + translationY = translateY + scaleX = currentScale + scaleY = currentScale + } + } + + /** + * 处理双击缩放 + */ + private fun handleDoubleTap() { + if (currentScale == MIN_SCALE) { + currentScale = 2.0f + } else { + currentScale = MIN_SCALE + translateX = 0f + translateY = 0f + } + updateImageTransform() + } + + override fun finish() { + super.finish() + // 添加退出动画 + overridePendingTransition(0, android.R.anim.fade_out) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/daodaoshi/chick_mood/MainActivitySimple.kt b/app/src/main/java/com/daodaoshi/chick_mood/MainActivitySimple.kt index 8210e5e..6874a5a 100644 --- a/app/src/main/java/com/daodaoshi/chick_mood/MainActivitySimple.kt +++ b/app/src/main/java/com/daodaoshi/chick_mood/MainActivitySimple.kt @@ -62,6 +62,9 @@ class MainActivitySimple : AppCompatActivity() { // 运行数据库测试 runDatabaseTest() + // 创建测试数据(如果数据库为空) + createTestDataIfNeeded() + // 加载历史记录数据 loadMoodRecords() } @@ -272,9 +275,9 @@ class MainActivitySimple : AppCompatActivity() { private fun initMoodRecordAdapter() { moodRecordAdapter = MoodRecordAdapter( onItemClick = { record -> - // 点击记录卡片 - 可以显示详情或进行其他操作 + // 点击记录卡片 - 跳转到详情页 Log.d(TAG, "点击了心情记录: ${record.emotion}") - showTemporaryMessage("查看记录详情") + showMoodRecordDetail(record) }, onFavoriteClick = { record -> // 收藏/取消收藏 @@ -401,8 +404,15 @@ class MainActivitySimple : AppCompatActivity() { * 显示心情记录详情 */ private fun showMoodRecordDetail(record: MoodRecord) { - // TODO: 跳转到详情页面 - showTemporaryMessage("查看详情功能待实现") + try { + val intent = android.content.Intent(this, DetailActivity::class.java).apply { + putExtra("record_id", record.id) + } + startActivity(intent) + } catch (e: Exception) { + Log.e(TAG, "跳转详情页失败", e) + showTemporaryMessage("打开详情页失败") + } } /** @@ -440,6 +450,137 @@ class MainActivitySimple : AppCompatActivity() { } } + /** + * 创建测试数据(如果数据库为空) + */ + private fun createTestDataIfNeeded() { + CoroutineScope(Dispatchers.IO).launch { + try { + val dbManager = SimpleDatabaseManager.getInstance(this@MainActivitySimple) + val recordCount = dbManager.getMoodRecordCount() + + if (recordCount == 0) { + // 数据库为空,创建一些测试数据 + val testData = generateRealisticTestData() + + for (data in testData) { + dbManager.createMoodRecord( + emotion = data.emotion, + intensity = data.moodIntensity, + noteText = data.textContent ?: "", + imagePaths = if (data.imagePath != null) listOf(data.imagePath) else emptyList() + ) + } + + Log.d(TAG, "创建了 ${testData.size} 条测试数据") + } + } catch (e: Exception) { + Log.e(TAG, "创建测试数据失败", e) + } + } + } + + /** + * 生成真实的测试数据 + */ + private fun generateRealisticTestData(): List { + val currentTime = System.currentTimeMillis() + val oneDayMs = 24 * 60 * 60 * 1000L + + return listOf( + MoodRecord( + id = 0, // 数据库会自动生成ID + emotion = Emotion.HAPPY, + moodIntensity = 85, + textContent = "今天心情特别好!阳光明媚,工作顺利,还和朋友聚餐了,感觉很充实。生活就是这样,简单的美好就让人很满足。", + imagePath = "placeholder_image_1", + timestamp = currentTime - 2 * oneDayMs, + isFavorite = true + ), + MoodRecord( + id = 0, + emotion = Emotion.WORRIED, + moodIntensity = 65, + textContent = "工作上遇到了一些挑战,有点压力,但我相信能够克服。明天要好好规划一下时间。", + imagePath = null, + timestamp = currentTime - 3 * oneDayMs, + isFavorite = false + ), + MoodRecord( + id = 0, + emotion = Emotion.ANGRY, + moodIntensity = 75, + textContent = "今天遇到了一些不愉快的事情,心情很糟糕。深呼吸,冷静下来,明天会是新的一天。", + imagePath = null, + timestamp = currentTime - 4 * oneDayMs, + isFavorite = false + ), + MoodRecord( + id = 0, + emotion = Emotion.SAD, + moodIntensity = 55, + textContent = "今天有点失落,可能是天气的原因,也可能是因为想家了。希望明天会更好。", + imagePath = "placeholder_image_2", + timestamp = currentTime - 5 * oneDayMs, + isFavorite = true + ), + MoodRecord( + id = 0, + emotion = Emotion.LONELY, + moodIntensity = 70, + textContent = "感觉有点孤单,想念朋友和家人。但这也是成长的一部分,学会独处也是一种能力。", + imagePath = null, + timestamp = currentTime - 6 * oneDayMs, + isFavorite = false + ), + MoodRecord( + id = 0, + emotion = Emotion.HAPPY, + moodIntensity = 95, + textContent = "超级开心!收到了期待已久的好消息,所有的努力都值得了!", + imagePath = "placeholder_image_3", + timestamp = currentTime - 7 * oneDayMs, + isFavorite = true + ), + MoodRecord( + id = 0, + emotion = Emotion.SCARED, + moodIntensity = 45, + textContent = "对未来的不确定性感到有些害怕,但我知道逃避不是解决方法。勇敢面对,一步一步来。", + imagePath = null, + timestamp = currentTime - 8 * oneDayMs, + isFavorite = false + ), + MoodRecord( + id = 0, + emotion = Emotion.HAPPY, + moodIntensity = 80, + textContent = "", + imagePath = "placeholder_image_4", + timestamp = currentTime - 9 * oneDayMs, + isFavorite = false + ), + MoodRecord( + id = 0, + emotion = Emotion.WORRIED, + moodIntensity = 60, + textContent = null, + imagePath = null, + timestamp = currentTime - 10 * oneDayMs, + isFavorite = false + ), + MoodRecord( + id = 0, + emotion = Emotion.SAD, + moodIntensity = 40, + textContent = "今天没什么特别的心情,就是有点低落。听音乐放松一下吧。", + imagePath = null, + timestamp = currentTime - 11 * oneDayMs, + isFavorite = false + ) + ) + } + override fun onDestroy() { super.onDestroy() // TODO: 清理资源 - 暂时注释掉 diff --git a/app/src/main/res/drawable/ic_arrow_back.xml b/app/src/main/res/drawable/ic_arrow_back.xml new file mode 100644 index 0000000..3529f09 --- /dev/null +++ b/app/src/main/res/drawable/ic_arrow_back.xml @@ -0,0 +1,10 @@ + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_close.xml b/app/src/main/res/drawable/ic_close.xml new file mode 100644 index 0000000..58dd2ab --- /dev/null +++ b/app/src/main/res/drawable/ic_close.xml @@ -0,0 +1,10 @@ + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_delete.xml b/app/src/main/res/drawable/ic_delete.xml new file mode 100644 index 0000000..23446b3 --- /dev/null +++ b/app/src/main/res/drawable/ic_delete.xml @@ -0,0 +1,10 @@ + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_edit.xml b/app/src/main/res/drawable/ic_edit.xml new file mode 100644 index 0000000..b3aef79 --- /dev/null +++ b/app/src/main/res/drawable/ic_edit.xml @@ -0,0 +1,10 @@ + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_more_vert.xml b/app/src/main/res/drawable/ic_more_vert.xml new file mode 100644 index 0000000..fce53c5 --- /dev/null +++ b/app/src/main/res/drawable/ic_more_vert.xml @@ -0,0 +1,10 @@ + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_placeholder_image.xml b/app/src/main/res/drawable/ic_placeholder_image.xml new file mode 100644 index 0000000..17d3ce5 --- /dev/null +++ b/app/src/main/res/drawable/ic_placeholder_image.xml @@ -0,0 +1,15 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_circle_background.xml b/app/src/main/res/drawable/shape_circle_background.xml new file mode 100644 index 0000000..9fac508 --- /dev/null +++ b/app/src/main/res/drawable/shape_circle_background.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_dialog_background.xml b/app/src/main/res/drawable/shape_dialog_background.xml new file mode 100644 index 0000000..03de475 --- /dev/null +++ b/app/src/main/res/drawable/shape_dialog_background.xml @@ -0,0 +1,8 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_dialog_background_rounded.xml b/app/src/main/res/drawable/shape_dialog_background_rounded.xml new file mode 100644 index 0000000..0229f6a --- /dev/null +++ b/app/src/main/res/drawable/shape_dialog_background_rounded.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_image_background.xml b/app/src/main/res/drawable/shape_image_background.xml new file mode 100644 index 0000000..aaf86df --- /dev/null +++ b/app/src/main/res/drawable/shape_image_background.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_detail.xml b/app/src/main/res/layout/activity_detail.xml new file mode 100644 index 0000000..7f27ab6 --- /dev/null +++ b/app/src/main/res/layout/activity_detail.xml @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_image_preview.xml b/app/src/main/res/layout/activity_image_preview.xml new file mode 100644 index 0000000..1f996d9 --- /dev/null +++ b/app/src/main/res/layout/activity_image_preview.xml @@ -0,0 +1,29 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/dialog_delete_confirm.xml b/app/src/main/res/layout/dialog_delete_confirm.xml new file mode 100644 index 0000000..74e87e6 --- /dev/null +++ b/app/src/main/res/layout/dialog_delete_confirm.xml @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/dialog_more_options.xml b/app/src/main/res/layout/dialog_more_options.xml new file mode 100644 index 0000000..6f75d0b --- /dev/null +++ b/app/src/main/res/layout/dialog_more_options.xml @@ -0,0 +1,163 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index faa3d89..b0adb93 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -34,6 +34,8 @@ #00000000 #80000000 + #D32F2F + #E0E0E0 #FF5252 diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml index 3c23f5c..a5cae66 100644 --- a/app/src/main/res/values/themes.xml +++ b/app/src/main/res/values/themes.xml @@ -11,4 +11,15 @@ @color/text_secondary + + + \ No newline at end of file diff --git a/claude.md b/claude.md index 5156706..1e66df2 100644 --- a/claude.md +++ b/claude.md @@ -6,9 +6,9 @@ **项目名称:** 别摇小鸡心情记录App **开发平台:** Android原生(Kotlin) -**当前版本:** V1.1.0 +**当前版本:** V1.2.0 **更新日期:** 2025-10-23 -**开发状态:** ✅ 首页核心功能完成,应用正常运行 +**开发状态:** ✅ 详情页功能完成,数据一致性完美 --- @@ -83,14 +83,25 @@ - **模块4.4** ✅ ViewPager2布局修复(match_parent) - **模块4.5** ✅ 崩溃问题修复和稳定性优化 +### ✅ 已完成模块 + +**阶段5:详情页功能实现** +- **模块5.1** ✅ 详情页基础布局和UI组件 +- **模块5.2** ✅ 心情文案生成逻辑(程度+心情类型) +- **模块5.3** ✅ 更多操作弹窗(编辑、收藏、分享、删除) +- **模块5.4** ✅ 删除功能和二次确认弹窗 +- **模块5.5** ✅ 收藏功能和状态持久化存储 +- **模块5.6** ✅ 图片放大查看功能 +- **模块5.7** ✅ 分享功能集成(系统分享) + ### 🔄 开发中模块 -**阶段5:核心功能完善(下一步重点)** -- **模块5.1** 📋 摇晃检测功能实现 -- **模块5.2** 📋 心情值计算逻辑 -- **模块5.3** 📋 小鸡动画响应系统 -- **模块5.4** 📋 侧边抽屉功能(更多按钮) -- **模块5.5** 📋 统计页面实现(统计按钮) +**阶段6:核心功能完善(下一步重点)** +- **模块6.1** 📋 摇晃检测功能实现 +- **模块6.2** 📋 心情值计算逻辑 +- **模块6.3** 📋 小鸡动画响应系统 +- **模块6.4** 📋 侧边抽屉功能(更多按钮) +- **模块6.5** 📋 统计页面实现(统计按钮) --- @@ -121,41 +132,72 @@ ## 🎯 下一步开发计划 -### 优先级1:核心交互功能(摇晃检测) -**模块5.1:摇晃检测功能实现** +### 优先级1:详情页功能实现(当前重点) +**模块5.1:详情页基础布局和UI组件** +- 创建DetailActivity和对应布局文件 +- 实现顶部导航栏(返回、时间、更多操作) +- 实现内容区域布局(小鸡形象、心情值、文案、配图、文本) +- 支持四种内容状态(有图有文、有图无文、无图有文、无图无文) + +**模块5.2:心情文案生成逻辑** +- 实现心情值到程度描述的映射逻辑 +- 动态生成"程度+心情类型"组合文案 +- 心情值范围:0-20(有些) → 20-40(非常) → 40-60(超级) → 60-80(这也太) → 80-100(完全无法控制) + +**模块5.3:更多操作弹窗功能** +- 实现底部弹窗布局(编辑、收藏、分享、删除) +- 弹窗动画效果和交互逻辑 +- 各操作按钮的状态管理和点击响应 + +**模块5.4:删除功能和二次确认弹窗** +- 实现删除确认弹窗布局和交互 +- 数据库记录删除操作 +- 删除成功提示和页面跳转逻辑 + +**模块5.5:收藏功能和状态持久化** +- 数据库添加收藏字段支持 +- 收藏状态切换和UI反馈 +- 收藏状态持久化存储 + +**模块5.6:图片放大查看功能** +- 实现图片点击放大预览 +- 支持手势缩放和拖拽 +- 1:1比例显示,图片自适应 + +**模块5.7:分享功能集成** +- 集成Android系统分享功能 +- 生成分享文本内容 +- 跳转系统分享选择器 + +### 优先级2:核心交互功能(摇晃检测) +**模块6.1:摇晃检测功能实现** - 实现手机摇晃传感器监听 - 摇晃强度和持续时间计算 - 摇晃阈值设置和优化 -**模块5.2:心情值计算逻辑** +**模块6.2:心情值计算逻辑** - 根据摇晃参数计算心情强度值 - 心情强度映射到情绪等级 - 心情值与情绪选择的关联 -### 优先级2:动画系统完善 -**模块5.3:小鸡动画响应系统** +### 优先级3:动画系统完善 +**模块6.3:小鸡动画响应系统** - 小鸡待机动画(Lottie集成) - 摇晃时的小鸡反应动画 - 不同情绪对应的小鸡状态动画 - 点击小鸡的交互反馈动画 -### 优先级3:页面功能扩展 -**模块5.4:侧边抽屉功能(更多按钮)** +### 优先级4:页面功能扩展 +**模块6.4:侧边抽屉功能(更多按钮)** - 实现侧边抽屉UI布局 - 设置、关于、帮助等页面入口 - 用户个人资料管理 -**模块5.5:统计页面实现(统计按钮)** +**模块6.5:统计页面实现(统计按钮)** - 心情数据统计分析 - 情绪趋势图表展示 - 记录统计和可视化 -### 优先级4:用户体验优化 -- 心情记录编辑和删除功能 -- 记录详情页面实现 -- 数据导出和备份功能 -- 个性化主题和设置选项 - --- ## 🔧 技术决策记录 @@ -245,6 +287,19 @@ Chick_Mood/ ## 🔄 更新记录 +**2025-10-23 (V1.2.0 详情页功能完成)** +- ✅ **详情页完整实现**:包含基础布局、UI组件和四种内容状态支持 +- ✅ **心情文案生成逻辑**:根据心情值动态生成"程度+心情类型"文案(0-20有些→20-40非常→40-60超级→60-80这也太→80-100完全无法控制) +- ✅ **更多操作弹窗**:实现底部弹窗(编辑、收藏、分享、删除)和完整交互逻辑 +- ✅ **删除功能和二次确认**:实现删除确认弹窗,防止误删,删除成功提示"记录已删除" +- ✅ **收藏功能和状态持久化**:支持收藏状态切换,数据库真实存储和UI状态同步 +- ✅ **分享功能集成**:集成Android系统分享,生成包含完整心情信息的分享文本 +- ✅ **图片放大查看功能**:创建ImagePreviewActivity,支持全屏预览和关闭操作 +- ✅ **首页跳转逻辑完善**:修改卡片点击和详情按钮都能跳转到详情页 +- ✅ **真实数据库集成**:详情页使用真实数据库数据,替换随机测试数据 +- ✅ **测试数据生成**:创建10条多样化真实测试数据,支持各种内容状态 +- ✅ **数据一致性保证**:首页和详情页显示完全一致的数据,收藏和删除功能真实操作数据库 + **2025-10-23 (V1.1.0 首页核心功能完成)** - ✅ **历史记录展示系统**:完整的ViewPager2横向滑动展示功能 - ✅ **心情记录卡片布局**:支持纯文本、文本+图片、多图+文本三种状态 @@ -278,4 +333,43 @@ Chick_Mood/ --- +## 📄 详情页功能详细说明 + +### 🎯 功能概述 +详情页是心情记录的完整展示和管理页面,支持从历史记录列表跳转查看单条记录的详细信息。 + +### 📱 页面结构 +1. **顶部导航栏** + - 返回按钮:点击返回历史记录列表 + - 时间显示:记录创建时间(格式:今天/昨天 HH:mm) + - 更多操作:三点图标,点击弹出操作菜单 + +2. **内容展示区域** + - 小鸡形象:根据情绪类型显示对应图标 + - 心情值:0-100数值显示 + - 心情文案:动态生成"程度+心情类型"组合 + - 配图区域:可选,支持点击放大查看 + - 文本描述:可选,多行文本内容 + +3. **操作功能** + - 编辑:跳转编辑页(后续实现) + - 收藏:切换收藏状态并持久化 + - 分享:调用系统分享功能 + - 删除:二次确认后删除记录 + +### 🔄 交互逻辑 +- **页面跳转**:点击历史记录卡片或详情按钮都可跳转 +- **内容状态**:支持有图有文、有图无文、无图有文、无图无文四种状态 +- **心情文案**:根据心情值自动生成程度描述 +- **图片查看**:点击图片支持放大预览,1:1比例显示 +- **收藏状态**:记录收藏状态并持久化存储 +- **删除操作**:二次确认后删除,成功提示并返回首页 + +### 💾 数据存储 +- **心情值**:0-100范围,开发阶段使用随机生成测试数据 +- **收藏状态**:数据库存储,默认未收藏 +- **时间格式**:与历史记录保持一致,具体到分钟 + +--- + *此文档将随着开发进展持续更新,记录重要的技术决策和进度变化。* \ No newline at end of file diff --git a/project_img/详情页.png b/project_img/详情页.png deleted file mode 100644 index 3f6904d..0000000 Binary files a/project_img/详情页.png and /dev/null differ diff --git a/project_img/详情页/删除二次确认弹窗@1x.png b/project_img/详情页/删除二次确认弹窗@1x.png new file mode 100644 index 0000000..d30b594 Binary files /dev/null and b/project_img/详情页/删除二次确认弹窗@1x.png differ diff --git a/project_img/详情页/无图无文@1x.png b/project_img/详情页/无图无文@1x.png new file mode 100644 index 0000000..3db7021 Binary files /dev/null and b/project_img/详情页/无图无文@1x.png differ diff --git a/project_img/详情页/无图有文@1x.png b/project_img/详情页/无图有文@1x.png new file mode 100644 index 0000000..99ecd6f Binary files /dev/null and b/project_img/详情页/无图有文@1x.png differ diff --git a/project_img/详情页/更多操作@1x.png b/project_img/详情页/更多操作@1x.png new file mode 100644 index 0000000..b522527 Binary files /dev/null and b/project_img/详情页/更多操作@1x.png differ diff --git a/project_img/详情页/有图无文@1x.png b/project_img/详情页/有图无文@1x.png new file mode 100644 index 0000000..0e0f8eb Binary files /dev/null and b/project_img/详情页/有图无文@1x.png differ diff --git a/project_img/详情页/有图有文@1x.png b/project_img/详情页/有图有文@1x.png new file mode 100644 index 0000000..7dfb564 Binary files /dev/null and b/project_img/详情页/有图有文@1x.png differ diff --git a/project_img/首页.png b/project_img/首页.png deleted file mode 100644 index 83f1401..0000000 Binary files a/project_img/首页.png and /dev/null differ