和笔记相关的页面:编辑笔记和展示笔记 以及相关的viewmodel

1. 编辑笔记

  1. EditNotesScreen:这是一个可编辑笔记的屏幕,它接收一个NavController对象、一个书籍的bookId和一个可选的modifier参数。它使用了LocalNotesViewModel来管理笔记的数据。
  • 它首先定义了几个状态变量,包括是否显示对话框、编辑内容和当前正在编辑的笔记ID。
  • 使用LaunchedEffect来通知viewModel更新当前的bookId。
  • 使用Scaffold构建UI布局,包括一个悬浮按钮,用于触发添加新笔记的操作。
  • 在Column中构建了屏幕的主体布局,包括一个返回箭头图标和标题文本。
  • 如果showDialog为真,则显示一个AlertDialog,用于添加或编辑笔记。对话框中包含一个文本字段和一个确认按钮,用于提交笔记内容。
  • 使用observeAsState观察LiveData,获取当前书籍的所有笔记,并将其转换为Compose可用的状态。
  • 最后,调用NotesListScreen来显示笔记列表,允许用户点击笔记进行编辑或删除。
  1. NotesListScreen:这是一个显示笔记列表的Composable函数,它接收一个笔记列表notes,以及点击笔记时的回调onNoteClick和删除笔记时的回调onDeleteClick。
  • 使用LazyColumn构建一个懒加载的列表,为每条笔记创建一个Card组件。
  • 在每个Card中,使用Row布局显示笔记内容和一个删除按钮。笔记内容部分是可点击的,当点击时会调用onNoteClick回调。删除按钮点击时会调用onDeleteClick回调。

app/src/main/java/com/example/BookRecord/EditNoteScreen.kt:


@Composable
fun EditNotesScreen(navController: NavController,bookId: Int,modifier: Modifier = Modifier,
){var showDialog by remember { mutableStateOf(false) }var editingContent by remember { mutableStateOf("") }var currentEditingNoteId by remember { mutableStateOf<Int?>(null) }val viewModel = LocalNotesViewModel.current// 通知 ViewModel 更新当前 bookIdLaunchedEffect(bookId) {viewModel.setBookId(bookId)}Scaffold(floatingActionButton = {SmallAddButton(onClick = {// 在这里定义点击悬浮按钮后的动作editingContent = ""currentEditingNoteId = null // 表示添加新笔记showDialog = true})},floatingActionButtonPosition = FabPosition.End, // 将按钮放在右下角){ paddingValues ->Column(modifier = Modifier.padding(paddingValues).padding(16.dp)){Row(modifier = Modifier.fillMaxWidth(),verticalAlignment = Alignment.CenterVertically // 垂直居中对齐 Row 内的元素) {Column(modifier = Modifier.weight(1f),horizontalAlignment = Alignment.CenterHorizontally){Icon(imageVector = Icons.Filled.ArrowBack,contentDescription = "Back",tint = Color(0xFF6650a4),modifier = Modifier.size(40.dp).clickable {navController.navigate("Book")})}Column(modifier = Modifier.weight(9f)) {Text(text = "Edit Notes",fontSize = 25.sp,fontWeight = FontWeight.Bold,color = Color(0xFF6650a4),modifier = Modifier.padding(start = 20.dp) // 根据需要调整文本的右边距)}}// 显示添加或编辑笔记的对话框if (showDialog) {AlertDialog(onDismissRequest = { showDialog = false },title = { Text(if (currentEditingNoteId == null) "Add Note" else "Edit Note") },text = {TextField(value = editingContent,onValueChange = { editingContent = it },label = { Text("Content") })},confirmButton = {Button(onClick = {if (currentEditingNoteId == null) {// 添加新笔记viewModel.addNote(editingContent, bookId = bookId)} else {// 更新现有笔记currentEditingNoteId?.let { noteId ->// 注意:这里同样假设 bookId 不会是 null,以及你有一个接收 noteId 和 noteContent 的 editNote 方法。// 如果你的 editNote 方法需要不同的参数,请相应地调整。viewModel.editNote(noteId = noteId, editingContent, bookId = bookId) // 如果 bookId 是 null,则需要决定如何处理}}showDialog = false}) { Text("OK") }},dismissButton = {Button(onClick = { showDialog = false }) { Text("Cancel") }})}// 观察 LiveData 并将其转换为 Compose 可用的状态val notesByBookId = viewModel.notesByBookId.observeAsState(initial = emptyList())// 笔记列表...NotesListScreen(notes = notesByBookId.value,onNoteClick = { note ->editingContent = note.contentcurrentEditingNoteId = note.idshowDialog = true},onDeleteClick = { note ->viewModel.deleteNote(note)})}}}@Composable
fun NotesListScreen(notes: List<Note>,onNoteClick: (Note) -> Unit,onDeleteClick: (Note) -> Unit
) {LazyColumn {items(items = notes, key = { it.id }) { note ->Card(modifier = Modifier.padding(4.dp).fillMaxWidth()) {Row(modifier = Modifier.padding(8.dp).fillMaxWidth(), verticalAlignment = Alignment.CenterVertically) {Text(text = note.content,modifier = Modifier.weight(1f).clickable { onNoteClick(note) })IconButton(onClick = { onDeleteClick(note) }) { // 当点击删除按钮时,调用 onDeleteClickIcon(Icons.Default.Delete, contentDescription = "Delete")}}}}}
}

2. 展示笔记

  1. NotesScreen:这是一个用于查看笔记的屏幕,它接收一个NavController对象、一个书籍的bookId和一个可选的modifier参数。它使用了LocalNotesViewModel来管理笔记的数据。
  • 它首先定义了一个viewModel实例,用于获取和更新笔记数据。
  • 使用LaunchedEffect来通知viewModel更新当前的bookId,这样viewModel就可以加载与该书籍相关的笔记。
  • 使用Scaffold构建UI布局,这是Compose中的一个主要布局组件,用于提供材料设计的基础结构。
  • 在Column中构建了屏幕的主体布局,包括一个返回箭头图标和标题文本“View Notes”。
  • 返回箭头图标是可点击的,当用户点击时,它将使用NavController导航回到“Bookshelf”路由。
  • NoteList Composable函数被用来显示笔记列表,它接收一个笔记列表notes和一个modifier参数。
  1. NoteList:这是一个用于显示笔记列表的Composable函数,它接收一个笔记列表notes和一个可选的modifier参数。
  • 使用LazyColumn构建一个懒加载的列表,这是Compose中的一个性能优化组件,用于高效地显示大量列表项。
  • 列表中的每个项目都是一个Card组件,它显示了单个笔记的内容。
  • Column用于在卡片内部创建一个垂直布局,其中包含笔记的文本内容。

app/src/main/java/com/example/BookRecord/NotesScreen.kt:

@Composable
fun NotesScreen( // 重命名为 NotesScreennavController: NavController,bookId:Int,modifier: Modifier = Modifier,
) {// 示例笔记数据val viewModel = LocalNotesViewModel.current// 通知 ViewModel 更新当前 bookIdLaunchedEffect(bookId) {viewModel.setBookId(bookId)}// 观察 LiveData 并将其转换为 Compose 可用的状态val notesByBookId = viewModel.notesByBookId.observeAsState(initial = emptyList())Scaffold() {paddingValues ->Column(modifier = modifier.padding(paddingValues)){Row(modifier = Modifier.fillMaxWidth().padding(0.dp),verticalAlignment = Alignment.CenterVertically // 垂直居中对齐 Row 内的元素){Column(modifier = Modifier.weight(1f),horizontalAlignment = Alignment.CenterHorizontally){Icon(imageVector = Icons.Filled.ArrowBack,contentDescription = "Back",tint = Color(0xFF6650a4),modifier = Modifier.size(40.dp).clickable {navController.navigate("Bookshelf")})}Column(modifier = Modifier.weight(9f)) {Text(text = "View Notes",fontSize = 25.sp,fontWeight = FontWeight.Bold,color = Color(0xFF6650a4),modifier = Modifier.padding(start = 20.dp) // 根据需要调整文本的右边距)}}// 笔记列表NoteList(notes = notesByBookId.value, modifier = modifier.padding(paddingValues).padding(16.dp))}}
}@Composable
fun NoteList(notes: List<Note>, modifier: Modifier = Modifier) {LazyColumn(modifier = modifier) {items(items = notes, key = { note -> note.hashCode() }) { note ->Card(modifier = Modifier.fillMaxWidth().padding(vertical = 4.dp),) {Column(modifier = Modifier.padding(16.dp)) {Text(text = note.content)}}}}
}

3. NoteViewModel.

  1. 构造函数:接收一个 Application 对象,并在初始化块中创建 NoteRepository 实例。NoteRepository 用于访问数据库和执行数据库操作。

  2. 数据库访问:通过 AppDatabase.getDatabase(application) 获取数据库实例,然后通过 noteDao() 方法获取 NotesDao 实例,这是与笔记表交互的接口。

  3. 当前选中的 BookId:使用 MutableLiveData<Int?> 来跟踪当前选中的书籍 ID (_currentBookId)。这个值用于确定要加载哪个书籍的笔记列表。

  4. 笔记列表:notesByBookId 是一个 LiveData<List> 属性,它使用 switchMap 函数根据当前的 bookId 获取对应的笔记列表。如果 bookId 为 null,则返回一个包含空列表的 MutableLiveData。

  5. 设置书籍 ID:setBookId 函数用于更新 _currentBookId 的值,这将触发 notesByBookId 重新获取对应书籍的笔记列表。

  6. 添加笔记:addNote 函数接收笔记内容和书籍 ID,然后在协程作用域内调用 repository.insert 方法将新笔记插入数据库。

  7. 删除笔记:deleteNote 函数接收一个 Note 对象,然后在协程作用域内调用 repository.delete 方法从数据库中删除该笔记。

  8. 编辑笔记:editNote 函数接收笔记 ID、更新后的笔记内容和书籍 ID,然后在协程作用域内调用 repository.update 方法更新数据库中的笔记。

  9. 协程处理:使用 viewModelScope.launch 在 ViewModel 的作用域内启动协程,以便在后台线程上执行数据库操作。

app/src/main/java/com/example/BookRecord/NoteViewModel.kt

package com.example.BookRecordimport android.app.Application
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateOf
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.switchMap
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.launchclass NoteViewModel(application: Application) : AndroidViewModel(application) {private val repository: NoteRepository// 使用 MutableLiveData 来跟踪当前选中的 bookIdprivate val _currentBookId = MutableLiveData<Int?>()init {val appDatabase = AppDatabase.getDatabase(application)val notesDao = appDatabase.noteDao()repository = NoteRepository(notesDao)}// 使用 switchMap 来根据当前的 bookId 获取对应的笔记列表val notesByBookId: LiveData<List<Note>> = _currentBookId.switchMap { bookId ->bookId?.let {repository.getNotesByBookId(it)} ?: MutableLiveData(emptyList())}fun setBookId(bookId: Int) {_currentBookId.value = bookId}// 添加笔记需要提供bookIdfun addNote(noteContent: String, bookId: Int) = viewModelScope.launch {val newNote = Note(content = noteContent, bookId = bookId)repository.insert(newNote)}// 删除笔记fun deleteNote(note: Note) = viewModelScope.launch {repository.delete(note)}// 编辑笔记fun editNote(noteId: Int, noteContent: String, bookId: Int) = viewModelScope.launch {val noteToUpdate = Note(id = noteId, content = noteContent, bookId = bookId)repository.update(noteToUpdate)}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/54188.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C++ ——string的模拟实现

目录 前言 浅记 1. reserve&#xff08;扩容&#xff09; 2. push_back&#xff08;尾插&#xff09; 3. iterator&#xff08;迭代器&#xff09; 4. append&#xff08;尾插一个字符串&#xff09; 5. insert 5.1 按pos位插入一个字符 5.2 按pos位插入一个字符串 …

后端入门 (JQuery基础) 01

引入jQuery资源&#xff08;https://cdn.staticfile.net/jquery/1.10.2/jquery.min.js&#xff09; <script src"jquery.js"></script> <!-- 引入jQuery资源 --> 绑定事件的方式&#xff1a; 1. 直接使用事件函数 $("p").click(func…

C++第五十一弹---IO流实战:高效文件读写与格式化输出

✨个人主页&#xff1a; 熬夜学编程的小林 &#x1f497;系列专栏&#xff1a; 【C语言详解】 【数据结构详解】【C详解】 目录 1. C语言的输入与输出 2. 流是什么 3. CIO流 3.1 C标准IO流 3.2 C文件IO流 3.2.1 以写方式打开文件 3.2.1 以读方式打开文件 4 stringstre…

flask框架

Flask 1 flask简介 我们之所以在浏览器中输入localhost:8080然后就可以把webapps下面的项目文件以浏览器的方式打开&#xff0c;功臣在与tomcat。python语言写的项目&#xff0c;转换为web&#xff0c;Flask框架 轻量级web应用框架。 环境准备&#xff1a; pip install fl…

【C语言】内存函数详细讲解

文章目录 前言strerror的声明和使用字符串分类函数字符转换函数内存拷贝函数&#xff08;memcpy)memcpy的声明和使用memcpy函数的模拟实现 内存拷贝函数&#xff08;memmove&#xff09;memmove的声明和使用memmove模拟实现 内存比较函数&#xff08;memcmp&#xff09;memcmp的…

UDP_SOCKET编程实现

文章目录 socket编程接口认识struct sockaddr类 编写一个server服务Client代码查看启动结果代码修正1.获取内核分配给客户端的信息2.修正不匹配ip不能访问的问题 不同机器之间的通信利用xftp将udp_client传给wsl的ubuntu机器进行演示现在模拟在windows下的udp_client代码: 对方…

时序预测 | MATLAB实现BKA-XGBoost(黑翅鸢优化算法优化极限梯度提升树)时间序列预测

时序预测 | MATLAB实现BKA-XGBoost(黑翅鸢优化算法优化极限梯度提升树)时间序列预测 目录 时序预测 | MATLAB实现BKA-XGBoost(黑翅鸢优化算法优化极限梯度提升树)时间序列预测预测效果基本介绍模型描述程序设计参考资料 预测效果 基本介绍 Matlab实现BKA-XGBoost时间序列预测&a…

WPF UpdateSourceTrigger属性

在WPF&#xff08;Windows Presentation Foundation&#xff09;中&#xff0c;UpdateSourceTrigger 是一个属性&#xff0c;通常用于数据绑定中&#xff0c;它控制着何时将绑定目标&#xff08;即UI元素&#xff09;的值更新到绑定源&#xff08;即数据对象&#xff09;。当UI…

Go语言现代web开发08 if和switch分支语句

if语句 If is the most common conditional statement in programming languages. If the result of the condition caculation is positive(true), the code inside if statement will be executed. In the next example, value a will be incremented if it is less than 10…

《黑神话:悟空》:中国游戏界的新篇章

引言&#xff1a; 在数字娱乐的浪潮中&#xff0c;游戏已成为连接全球文化的重要媒介。 《黑神话&#xff1a;悟空》的问世&#xff0c;不仅是中国游戏产业的一个里程碑&#xff0c;更是文化自信的闪耀展现。 这款游戏以其独特的艺术风格和深刻的文化内涵&#xff0c;在全球范…

k8s中的认证授权

目录 一、kubernetes API 访问控制 1.1 UserAccount与ServiceAccount 1.1.1 ServiceAccount 1.1.2 ServiceAccount示例 二、认证(在k8s中建立认证用户) 2.1 创建UserAccount 2.2 RBAC&#xff08;Role Based Access Control&#xff09; 2.2.1 基于角色访问控制授权&…

RT-DETR改进策略:BackBone改进|使用StarNet改进RT-DERT,显著提升性能与效率

摘要 本文介绍了我们如何将最新的StarNet模型成功应用于实时目标检测任务中,特别是用于改进RT-DERT(一种高效的实时目标检测网络)的主干网络部分。通过详尽的实验和理论分析,我们证明了StarNet不仅能够显著增强RT-DERT的检测精度,同时保持了高效的计算性能和低延迟特性。…

C++从入门到起飞之——继承下篇(万字详解) 全方位剖析!

&#x1f308;个人主页&#xff1a;秋风起&#xff0c;再归来~&#x1f525;系列专栏&#xff1a;C从入门到起飞 &#x1f516;克心守己&#xff0c;律己则安 目录 1、派⽣类的默认成员函数 1.1 四个常⻅默认成员函数 1.2 实现⼀个不能被继承的类 ​编辑 2. 继承与友…

力扣题解2390

大家好&#xff0c;欢迎来到无限大的频道。 今日继续给大家带来力扣题解。 题目描述​&#xff08;中等&#xff09;&#xff1a; 从字符串中移除星号 给你一个包含若干星号 * 的字符串 s 。 在一步操作中&#xff0c;你可以&#xff1a; 选中 s 中的一个星号。 移除星号…

力扣刷题(6)

两数之和 II - 输入有序数组 两数之和 II - 输入有序数组-力扣 思路&#xff1a; 因为该数组是非递减顺序排列&#xff0c;因此可以设两个左右下标当左右下标的数相加大于target时&#xff0c;则表示右下标的数字过大&#xff0c;因此将右下标 - -当左右下标的数相加小于targ…

HashMap线程不安全|Hashtable|ConcurrentHashMap

文章目录 常见集合线程安全性HashMap为什么线程不安全&#xff1f;怎么保证HashMap线程安全 HashtableConcurrentHashMap 引入细粒度锁代码中分析总结 小结 常见集合线程安全性 ArrayList、LinkedList、TreeSet、HashSet、HashMap、TreeMap等都是线程不安全的。 HashTable是线…

C语言:数组

1. 数组的概念 数组是⼀组相同类型元素的集合&#xff1b;从这个概念中我们就可以发现2个有价值的信息&#xff1a; • 数组中存放的是1个或者多个数据&#xff0c;但是数组元素个数不能为0。 • 数组中存放的多个数据&#xff0c;类型是相同的。 数组分为⼀维数组和多维数组…

【C语言必学知识点七】你知道在动态内存管理中存在的内存泄露问题吗?遇到内存泄露时应该如何处理?今天跟你好好介绍一下如何正确使用calloc与realloc!!!

动态内存管理——动态函数&#xff08;calloc、realloc&#xff09;的使用 导读一、calloc函数1.1 函数介绍1.2 calloc的使用1.3 calloc与malloc 二、realloc函数2.1 函数介绍2.2 realloc的使用2.3 realloc的空间分配2.3.1 空间分配成功——地址的改变2.3.2 空间分配失败——内…

【在Linux世界中追寻伟大的One Piece】数据链路层

目录 1 -> 数据链路层 2 -> 对比理解“数据链路层”和“网络层” 3 -> 以太网 3.1 -> 以太网的帧格式 4 -> 认识MAC地址 4.1 -> 对比理解MAC地址和IP地址 5 -> 认识MTU 5.1 -> MTU对IP协议的影响 5.2 -> MTU对UDP协议的影响 5.3 -> MT…

ElasticSearch介绍+使用

ElasticSearch 1.背景 ElasticSearch的最明显的优势在于其分布式特性&#xff0c;能够扩展到上百台服务器&#xff0c;极大地提高了服务器的容错率。在大数据时代背景下&#xff0c;ElasticSearch与传统的数据库相比较&#xff0c;能够应对大规模的并发搜索请求&#xff0c;同…