和笔记相关的页面:编辑笔记和展示笔记 以及相关的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 更新当前 bookId
    LaunchedEffect(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.content
                    currentEditingNoteId = note.id
                    showDialog = 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) }) { // 当点击删除按钮时,调用 onDeleteClick
                        Icon(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( // 重命名为 NotesScreen
    navController: NavController,
    bookId:Int,
    modifier: Modifier = Modifier,
) {
    // 示例笔记数据
    val viewModel = LocalNotesViewModel.current


    // 通知 ViewModel 更新当前 bookId
    LaunchedEffect(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.BookRecord

import 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.launch

class NoteViewModel(application: Application) : AndroidViewModel(application) {
    private val repository: NoteRepository

    // 使用 MutableLiveData 来跟踪当前选中的 bookId
    private 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
    }


    // 添加笔记需要提供bookId
    fun 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)
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值