VocabVerse创新实训(9)-安卓环境修改&音标表格和单词笔记模式前端修改
第十一周创新实训记录-对于安卓虚拟机和gradle环境的修改&音标表格/单词笔记前端修改
因为C盘内存只剩下8G左右,为了下面软件开发,将最占内存的.gradle和.android文件转移到D盘,最终C盘内存还有26G左右(从来没这么富裕过)
一、安卓虚拟机和gradle修改(目前是没发现什么问题,仅供参考)
1.1 安卓虚拟机文件转移
首先看代码环境设置里面是否含有相关安卓虚拟机的地址设置(有的话需要修改成之后到D盘的绝对地址,没有直接移动),.android存放的是AVD虚拟机相关的文件
下面是移动后的结果
修改后会发现IDEA里面没有之前的虚拟机,显示让你再创建新的虚拟机,我觉得可能IDEA找不到移动后的虚拟机位置(下面是我已经成功的界面)
这个时候不要慌,打开系统环境变量,添加avd的绝对路径(变量不要变,值设置成自己AVD存的绝对路径)
这个时候重启电脑,再打开IDEA就会发现之前的虚拟机又出现了(๑•̀ㅂ•́)و✧(显示我上面成功界面应该就是成功了)
还有最后一步就是确认运行代码时虚拟机是否能打开,运行代码时虚拟机会出现app界面然后会有个弹窗(USB啥的),一定要点确认或者yes(我忘记了),因为这会影响到运行代码虚拟机不会启动问题
目前来看没发现啥问题,此方法仅供参考
1.2 .gradle文件转移
这个比较简单,先转移.gradle文件到D盘
然后修改IDEA里面的环境路径,就是修改gradle用户主目录(修改成目前修改后的.gradle绝对路径)
就上述两步骤,等待加载就行了
二、前端修改
2.1 音标表格前端修改
2.1.1 IpaListItem
首先是@preview预览界面函数
1、针对Ipa实体类进行构造测试数据
2、调用IpaListItem的界面函数进行预览
@Preview(showBackground = true) @Composable fun PreviewIpaListItem() { // 1. 构造测试数据 val ipa = Ipa( type = Ipa.Type.VOWELS, text = "æ", exampleWordSpelling = "cat", exampleWordIpa = "/kæt/", exampleWordPronName = "cat_pron" ) // 2. 调用要预览的 Composable 函数 IpaListItem( ipa = ipa, playPron = { pronName -> println("Playing pronunciation for: $pronName") } ) }
下面是预览界面展示
2.1.2 IpaScreen
@preview预览函数
1、看清要预览的 Composable 需要哪些参数
2、给数据参数造假数据(如 IpaUiState、List)
3、 给函数参数写 mock 函数(用 println 或空函数)
4、状态参数用 remember 和 mutableStateOf
5、 调用目标 Composable,传入这些模拟值
6、包装在一个带 @Preview 注解的 Composable 中
@Preview(showBackground = true) @Composable fun PreviewIpaScreen() { // 模拟数据 val mockIpaList = listOf( Ipa(Ipa.Type.CONSONANTS, "b", "ball", "bɔːl", "ball"), Ipa(Ipa.Type.VOWELS, "a", "cat", "kæt", "cat") ) // 模拟UI状态 val mockUiState = IpaUiState.Success( ipaType = Ipa.Type.CONSONANTS, ipaList = mockIpaList ) // 这里模拟 IpaType 的选择界面 val ipaTypeMenuState = remember { mutableStateOf(false) } // 模拟 playPron 和 navigateTo 的功能 IpaContent( uiState = mockUiState, setIpaType = { type -> // 模拟设置类型的行为 println("Selected IPA Type: ${type.cnValue}") }, ipaTypeMenuState = ipaTypeMenuState, playPron = { ipa -> println("Playing pronunciation for $ipa") }, navigateTo = { destination -> println("Navigating to $destination") } ) }
下面是预览界面
在整体的音标列表界面上增加了下面的细节
校徽展示
// 外层 Box,确保 Icon 在中央 Box( modifier = Modifier .fillMaxSize() // 包裹整个 Box .wrapContentSize(Alignment.Center) // 使内容居中 ) { Icon( painter = painterResource(R.drawable.sdu_logo_1), // 替换图标资源 contentDescription = "Central Icon", tint = MaterialTheme.colorScheme.outline, modifier = Modifier .size(300.dp) // 设置图标大小 .alpha(0.2f) // 设置透明度,0.3f 表示30%的透明度 ) }
将整个内容用对话框框起来
Box( contentAlignment = Alignment.Center, modifier = Modifier .weight(1f) .fillMaxWidth() .padding(8.dp) // 调整外边距 .background(MaterialTheme.colorScheme.surface, shape = RoundedCornerShape(16.dp)) // 背景色和圆角效果 .border(2.dp, MaterialTheme.colorScheme.outline, shape = RoundedCornerShape(16.dp)) // 设置更粗的边框和圆角 .alpha(0.8f) // 设置透明度 ) { 。。。。。。 }
相关图标设计
Row(verticalAlignment = Alignment.CenterVertically) { Icon( painter = painterResource(R.drawable.ic_ipa_fuyin_24dp), contentDescription = null, tint = Color.Unspecified, modifier = Modifier.size(24.dp) ) Spacer(modifier = Modifier.width(8.dp)) // 图标和文本之间的间隔 Text(text = Ipa.Type.CONSONANTS.cnValue) }
2.1.3 最终展示
夹带私货的主题(bushi)
2.2 单词笔记
这个涉及太多的界面修改(共8个前端文件,相类似的一块解释了)
2.2.1 WrongWordNumHeader&NoteAlphabetHeader
首先是预览函数
和上面的类似(构建虚拟的数据,调用相关界面函数)
//NoteAlphabetHeader 的预览界面(生词列表表头) @Preview(showBackground = true) @Composable fun PreviewNoteAlphabetHeader() { NoteAlphabetHeader( alphabet = "A" // 使用一个示例字母 ) } //WrongWordNumHeader 的预览界面(错词列表表头) @Preview(showBackground = true) @Composable fun WrongWordNumHeaderPreview() { MaterialTheme( colorScheme = darkColorScheme( primary = Color.Cyan, secondary = Color.Green, onBackground = Color.Gray ) ) { WrongWordNumHeader(num = 5) } }
预览界面
2.2.2 单词展示(WrongWord和NoteWord)
因为类似,只写了WrongWord的预览函数(该函数仅仅展示界面,不依赖于任何viewmodel)
@Preview(showBackground = true) @Composable fun PreviewWrongWord() { WrongWord( progressWrongWord = ProgressWrongWord( studyProgressId = 1L, // 这里添加一个 ID spelling = "example", ipa = "/ɪɡˈzæmpəl/", cn = mapOf("definition" to listOf("示例", "例子")), en = mapOf("definition" to listOf("a typical instance of something")), pronName = "example_pron" ), openExplainDialog = { spelling, explanations -> // Handle dialog open logic }, playPron = { pronName -> // Handle pronunciation logic } ) }
预览界面
相关修改--单词背景改为统一的灰色透明
Column( modifier = Modifier .fillMaxWidth() .padding(vertical = 2.dp) .background( Color(0xFFE3E3E3).copy(alpha = 0.4f), shape = RoundedCornerShape(4.dp) ) //.shadow(2.dp, shape = RoundedCornerShape(4.dp), clip = false) // 阴影效果 .padding(horizontal = 1.dp) ) {。。。。。}
2.2.3 单词展示界面(NotePager&WrongPager)
应为将整个内容用对话框框起来(涉及的代码太简单,因此没写preview预览函数)
相关代码
Column( modifier = Modifier .padding(8.dp) .fillMaxSize() .background(MaterialTheme.colorScheme.surface, shape = RoundedCornerShape(16.dp)) // 背景色和圆角效果 .border(2.dp, MaterialTheme.colorScheme.outline, shape = RoundedCornerShape(16.dp)) // 设置更粗的边框和圆角 .alpha(0.8f) // 设置透明度 ){。。。。。。}
2.2.4 整个界面展示(NoteScreen)
主要设计点为(选择不同界面对应的图标不同)
1、在变量上添加图标变量
2、根据不同的 title 为每个标签设置不同的图标
相关代码
private fun NoteContent( isDarkMode: Boolean, uiState: NoteUiState, removeNote: (String, Long) -> Unit, addNote: (String, Long) -> Unit, openDictionaryDialog: (Word) -> Unit, openReverseDialog: () -> Unit, openExplainDialog: (String, Map) -> Unit, closeDialog: () -> Unit, playPron: (String) -> Unit, navigateTo: (String) -> Unit, ) { val pagerState = rememberPagerState() val titleList = listOf("生词列表", "错词列表") // 对应的图标资源 val icons = listOf( R.drawable.ic_note_shengci_24dp, // "生词列表" 的图标 R.drawable.ic_note_paodaxing_24dp // "错词列表" 的图标 ) 。。。。。。。。 Row(verticalAlignment = Alignment.CenterVertically) { // 根据不同的 title 为每个标签设置不同的图标 Icon( painter = painterResource(icons[index]), // 动态获取图标资源 contentDescription = null, tint = MaterialTheme.colorScheme.tertiary, modifier = Modifier.size(25.dp) ) Spacer(modifier = Modifier.width(8.dp)) // 图标和文字之间的间隔 Text( text = title, style = MaterialTheme.typography.titleSmall ) }
2.2.5 删除单词弹窗(NoteReverseDialog)
@preview预览函数代码(包含相关解释)
@Preview(showBackground = true) @Composable fun NoteReverseDialogPreview() { // 提供一些假数据 val removedNoteList = listOf( "单词1" to 1L, "单词2" to 2L, "单词3" to 3L ) // 预览时不需要实际的 addNote 和 onDismiss 实现,可以传入空的 lambda 函数 NoteReverseDialog( removedNoteList = removedNoteList, addNote = { _, _ -> }, onDismiss = {} ) }
预览界面展示
前端细节代码修改
Column( modifier = Modifier .padding(8.dp) .fillMaxWidth() .background(MaterialTheme.colorScheme.surface, shape = RoundedCornerShape(16.dp)) // 背景色和圆角效果 .border(2.dp, MaterialTheme.colorScheme.outline, shape = RoundedCornerShape(16.dp)) // 设置更粗的边框和圆角 .alpha(0.8f) // 设置透明度 ){。。。。 Row( verticalAlignment = Alignment.CenterVertically, // 垂直对齐方式,使图标和文本在垂直方向对齐 modifier = Modifier.fillMaxWidth() ) { Spacer(modifier = Modifier.width(10.dp)) // 图标和文本之间的间隔 Icon( painter = painterResource(R.drawable.ic_note_zhangyuge_24dp), contentDescription = null, tint = MaterialTheme.colorScheme.tertiary, modifier = Modifier.size(20.dp) ) Spacer(modifier = Modifier.width(8.dp)) // 图标和文本之间的间隔 Text( text = "临时记录", style = MaterialTheme.typography.titleMedium, color = MaterialTheme.colorScheme.tertiary, ) Spacer(modifier = Modifier.padding(vertical = 4.dp)) } } OutlinedButton( onClick = onDismiss, modifier = Modifier.padding(4.dp) ) { Icon( painter = painterResource(R.drawable.ic_note_pilaoban_24dp), contentDescription = null, tint = MaterialTheme.colorScheme.outline, modifier = Modifier.size(20.dp) ) Spacer(modifier = Modifier.width(8.dp)) // 图标和文本之间的间隔 Text(text = stringResource(R.string.cancel)) }
注意:使用OutlinedButto(与简单的TextButton不同)
OutlinedButton 的默认行为:OutlinedButton 是带有边框的按钮,默认情况下有一个椭圆形的边框。当按钮内容(在此情况下是 Text)的尺寸较小时,按钮的边框会自动调整以适应内容,并且可能呈现出椭圆形