# 开发了一个综合影视字幕或音乐歌词的android单词学习软件

**URL:** <https://forum.freemdict.com/t/topic/36518>\
**Category:** 软件经验交流展望\
**Tags:** opensource, 日语, ﻿英语\
**Created:** [2025 年2 月 11 日 05:44 UTC](https://forum.freemdict.com/t/topic/36518 "2025-02-11T05:44:01Z")\
**Posts on this page:** 6\
**Page:** 3

<div class="post-metadata">

作者： ![coda251](https://forumcdn.freemdict.com/letter_avatar_proxy/v4/letter/c/d6d6ee/32.png) [@coda251](https://forum.freemdict.com/u/coda251)\
发布日期： [2026 年3 月 30 日 14:39 UTC](https://forum.freemdict.com/t/topic/36518/41 "2026-03-30T14:39:02Z")

</div>

谢谢建议:)  
媒体库目前做得确实比较简陋，只面向一次性导入媒体文件和字幕文件的场景（比如一个季度的影片，一张专辑里的歌曲）。重新扫描文件夹的功能后面可以加上。  
单击查词这个问题我最近也遇到了。应该会增加一些选项，比如你说的开关选项，还有循环播放当前例句的选项。  
查词跳转其它辞典应用暂时没有计划做。感觉如果只是在其它辞典中录入生词就有点背离这个app的初衷了 🤔

---

<div class="post-metadata">

作者： ![784](https://forumcdn.freemdict.com/user_avatar/forum.freemdict.com/784/32/85531_2.png) [@784](https://forum.freemdict.com/u/784)\
发布日期： [2026 年3 月 31 日 23:30 UTC](https://forum.freemdict.com/t/topic/36518/42 "2026-03-31T23:30:22Z")

</div>

太好啦！感谢！期待之后的更新;P

想加外部词典的弹窗，主要还是感觉论坛里大家分享的很多词典的词条和释义要更详尽一些。要是能打通，就能把这些资源也充分利用起来了。  
不过现有的网络词典虽然相对精简一点，但也像提示卡一样一览无余，可以方便快速反应，用来复习还挺好用的。感觉也是各有所长。（这也许是因为我在这里看的都是英文视频？）

借Gemini的帮助单独调整了一下PlayerWordBottomSheet函数，用欧路弹窗替代原本的弹窗（同时自动静默加入应用内的生词本），自用暂时是没有问题了。弹窗可以自由拖动和调整大小，调好以后感觉内容观感还不错。

_效果是这样：_

 ![Screenshot](https://forumcdn.freemdict.com/uploads/default/original/3X/6/9/69f0c7e7f9bde899c93b5aedef216a74c59469b0.jpeg)

_具体是在PlayerWordBottomSheet.kt里新增了：_

```auto
import android.content.Intent
import android.net.Uri
import androidx.compose.ui.platform.LocalContext

```

_然后把PlayerWordBottomSheet函数改成了：_

```auto
@Composable
internal fun PlayerWordBottomSheet(
    onDismiss: () -> Unit,
    viewModel: PlayerWordViewModel = koinViewModel()
) {
    val route = viewModel.route
    val wordContextUiState by viewModel.wordContextUiState.collectAsStateWithLifecycle()
    val wordQueryUiState by viewModel.wordQueryUiState.collectAsStateWithLifecycle()
    val context = LocalContext.current

    var hasLaunchedEudic by remember(route.word) { mutableStateOf(false) }
    var hasFinished by remember(route.word) { mutableStateOf(false) }

    LaunchedEffect(route.word) {
        if (!hasLaunchedEudic) {
            try {
                val uri = Uri.parse("eudic://peek/${route.word}")
                val intent = Intent(Intent.ACTION_VIEW, uri)
                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
                context.startActivity(intent)
            } catch (e: Exception) {
            }
            hasLaunchedEudic = true
        }
    }

    LaunchedEffect(wordContextUiState) {
        if (wordContextUiState is WordContextUiState.Existed && !hasFinished) {
            hasFinished = true
            onDismiss()
        }
    }

    LaunchedEffect(wordQueryUiState) {
        if (!hasFinished) {
            when (val query = wordQueryUiState) {
                is WordQueryUiState.ResultDb -> {
                    val wordInfo = query.word.asWordInfo()
                    if (wordInfo.isNotEmpty()) {
                        viewModel.insertWordWithContext(wordInfo)
                        hasFinished = true
                        onDismiss()
                    }
                }
                is WordQueryUiState.ResultWeb -> {
                    val firstTrans = query.translations.firstOrNull()
                    val infoState = firstTrans?.infoState
                    if (infoState is RemoteWordInfoState.Single) {
                        viewModel.insertWordWithContext(infoState.info)
                        hasFinished = true
                        onDismiss()
                    } else if (infoState is RemoteWordInfoState.Multiple && infoState.infos.isNotEmpty()) {
                        viewModel.insertWordWithContext(infoState.infos.first())
                        hasFinished = true
                        onDismiss()
                    }
                }
                WordQueryUiState.NoTranslatorError -> {
                    viewModel.insertWordWithContext(null)
                    hasFinished = true
                    onDismiss()
                }
                else -> {} 
            }
        }
    }

    LaunchedEffect(route.word) {
        kotlinx.coroutines.delay(2500) 
        if (!hasFinished) {
            viewModel.insertWordWithContext(null) 
            hasFinished = true
            onDismiss() 
        }
    }
}

```

不过还不太知道该怎么处理那些文档间相互关联着的内容，比如新设相关的界面开关/选项之类的。还要再慢慢学习一下 🤧

---

<div class="post-metadata">

作者： ![784](https://forumcdn.freemdict.com/user_avatar/forum.freemdict.com/784/32/85531_2.png) [@784](https://forum.freemdict.com/u/784)\
发布日期： [2026 年4 月 3 日 16:03 UTC](https://forum.freemdict.com/t/topic/36518/43 "2026-04-03T16:03:02Z")

</div>

> **[SituLearner\_260403](https://cloud.freemdict.com/index.php/s/gtiBJwnKCy2yF9o)**
>
> FreeMdict Cloud - A FreeMdict Storage

* * *

这两天试着靠AI加了一些功能，不过不太会整理代码，有点乱糟糟的  
修补了一些小漏洞，在自己的手机上用着还可以，但也还需要再修整修整（虽然暂时已经燃尽了 🤕）

尽管还不确定能不能完全适用，总之先发上来抛砖引玉了

* * *

#### _稍微整理了一下修改了的部分：_

**媒体库**

- 新增添加媒体时的进度条显示
- 新增单个媒体合集内删除该媒体合集的按钮

**单词**

- 无联网释义单词增加对应标注
- 应用内网络词典中存在释义但未成功保存释义的词条 在下次联网点选查词时可自动更新弹窗及单词库内的释义

**设置**

- 新设可在点击查词时自动将单词加入单词本的功能开关  
_＊目前在查日语词时会默认收藏第一个词典的释义；书签图标反应较实际保存速度稍有些缓慢_
- 新设查词时自动暂停/播放的开关（仅对应用内默认词典生效）
- 新设选择词典的选项（默认词典、欧路词典、深蓝词典、DictTango）

**播放页面**

- 增加横屏播放显示，横屏播放时：  
‐播放控件集合至单行  
‐字幕按时间轴显示（不驻留）  
‐点选查词时高亮待查单词  
‐双击画面控制：  
・中部1/2=暂停/恢复播放  
・左侧1/4=跳转至上句起始处播放  
・右侧1/4=跳转至下句起始处播放

---

<div class="post-metadata">

作者： ![coda251](https://forumcdn.freemdict.com/letter_avatar_proxy/v4/letter/c/d6d6ee/32.png) [@coda251](https://forum.freemdict.com/u/coda251)\
发布日期： [2026 年4 月 4 日 05:27 UTC](https://forum.freemdict.com/t/topic/36518/45 "2026-04-04T05:27:28Z")

</div>

厉害厉害 👏  
媒体库的删除合集功能倒是有做（长按媒体库中的合集），不过确实缺少一些使用引导。另外，看你传上来的包的大小有100+MB，感觉是debug包而非release包？debug包的话有些地方确实可能卡顿。

如果对开发感兴趣的话，可以参考[deepwiki](https://deepwiki.com/coda251/situlearner)，它提供了整个项目的架构说明（不过也基本是参考now in android了）。如果愿意参与项目开发，使用github的pull request会方便些。

---

<div class="post-metadata">

作者： ![784](https://forumcdn.freemdict.com/user_avatar/forum.freemdict.com/784/32/85531_2.png) [@784](https://forum.freemdict.com/u/784)\
发布日期： [2026 年4 月 4 日 05:43 UTC](https://forum.freemdict.com/t/topic/36518/46 "2026-04-04T05:43:21Z")

</div>

今天后来凌晨捣鼓的时候一不小心长按了一下，也意外发现了这个删除选项，还有重命名。深藏不露哈哈哈 😆  
确实是debug包。半夜也是发现了这个大小区别太多，试了一下导release包，但是还是有100MB不到一点，看了一下是language-models里把其他语言也全都下上了，但是操作了半天还是没办法只留下中日英就先休息了  
虽然很感兴趣，但是这方面欠缺的理论知识实在是有点太多，隔空指挥AI还能行，要整理整合修改涉及的内容就有点心有余而力不足了 🥹

---

<div class="post-metadata">

作者： ![coda251](https://forumcdn.freemdict.com/letter_avatar_proxy/v4/letter/c/d6d6ee/32.png) [@coda251](https://forum.freemdict.com/u/coda251)\
发布日期： [2026 年4 月 29 日 13:22 UTC](https://forum.freemdict.com/t/topic/36518/47 "2026-04-29T13:22:38Z")

</div>

根据自己的使用情况和坛友的建议，更新了两个版本到v0.10.0。  
特性：

- 支持选择今日到期的单词用于测验
- 支持更新媒体合集的封面图
- 支持扫描媒体合集目录下的图片作为封面图
- 设置界面添加关于app的说明
- 支持在字幕文件中搜索单词
- 横屏视频的全屏界面
- 单词测试中添加“记错了”选项
- 自动检查app版本更新
- 测验界面可查看未来两周的任务
- 翻译测验界面允许在回答前刷新问题
- 支持更新媒体库内的媒体文件
- 可设置点击单词后播放器的播放状态
- 字幕列表界面支持仅展示原文（点击显示译文）

优化：

- 通知界面以及系统媒体的播放信息
- 单词编辑界面的操作ui
- 单词及其所属字幕的获取逻辑
- 媒体库、单词的增删查改操作界面
- 设置界面

修复：

- 从播放列表界面导航返回播放界面时，播放状态被错误更改

[上一页](https://forum.freemdict.com/t/topic/36518.md?page=2)
