Link to the video of the problem: Video Link`
Sometimes many notes delete at once and the add functionality is not working. When I swipe the Lazy Column does not recompose and put everything in order again.
This is my code:
NoteButton:
@Composable
fun NoteButton(
modifier: Modifier = Modifier,
text: String,
enabled: Boolean = true,
shape: Shape = CircleShape,
onClick: () -> Unit
) {
Button(
modifier = modifier,
enabled = enabled,
shape = shape,
onClick = onClick
) {
Text(text)
}
}
NoteInputText:
@OptIn(ExperimentalComposeUiApi::class)
@Composable
fun NoteInputText(
modifier: Modifier = Modifier,
text: String,
label: String,
maxLines: Int = 1,
onTextChange: (String) -> Unit,
onImeAction: () -> Unit = {},
keyboardOptions: KeyboardOptions = KeyboardOptions.Default.copy(
imeAction = if (maxLines == 1) ImeAction.Done else ImeAction.None
)
) {
val keyboardController = LocalSoftwareKeyboardController.current
TextField(
modifier = modifier,
value = text,
onValueChange = onTextChange,
maxLines = maxLines,
label = { Text(text = label) },
keyboardOptions = keyboardOptions,
keyboardActions = KeyboardActions(
onDone = {
onImeAction()
keyboardController?.hide()
}
)
)
}
NoteItem:
private const val TAG = "NoteItem"
@OptIn(ExperimentalMaterialApi::class)
@Composable
fun NoteItem(modifier: Modifier = Modifier, note: Note, onSwipe: (Note) -> Unit) {
val dismissState = rememberDismissState(initialValue = DismissValue.Default) {
if (it == DismissValue.DismissedToStart) {
Log.d(TAG, "NoteItem: ${note.id}")
onSwipe(note)
}
true
}
SwipeToDismiss(
state = dismissState,
directions = setOf(DismissDirection.EndToStart),
background = {}
) {
Card(
modifier = modifier
.padding(5.dp)
.fillMaxWidth(),
shape = RoundedCornerShape(topEnd = 20.dp, bottomEnd = 20.dp),
elevation = 5.dp
) {
Column(modifier = Modifier.padding(horizontal = 15.dp, vertical = 5.dp)) {
Text(text = note.title, style = MaterialTheme.typography.h5)
Text(text = note.description, style = MaterialTheme.typography.body1)
}
}
}
}
NoteList:
private const val TAG = "NoteList"
@Composable
fun NoteList(modifier: Modifier = Modifier, onSwipe: (Note) -> Unit) {
val noteViewModel: NoteViewModel = viewModel()
val notes = noteViewModel.getAllNotes()
if(notes.isNotEmpty()) {
LazyColumn(modifier = modifier.padding(5.dp)) {
items(notes) { note ->
NoteItem(note = note, onSwipe = { onSwipe(note) })
}
}
}
}
Note:
data class Note(
val id: Long = assignIdForNote(),
val title: String,
val description: String,
val entryDate: LocalDateTime = LocalDateTime.now()
)
fun getNoteData() = mutableListOf(
Note(title = "A good day", description = "We went on a vacation by the lake"),
Note(title = "Android Compose", description = "Working on Android Compose course today"),
Note(title = "Keep at it...", description = "Sometimes things just happen"),
Note(title = "A movie day", description = "Watching a movie with family today"),
Note(title = "A movie day", description = "Watching a movie with family today"),
Note(title = "A movie day", description = "Watching a movie with family today"),
Note(title = "A movie day", description = "Watching a movie with family today"),
Note(title = "A movie day", description = "Watching a movie with family today"),
Note(title = "A movie day", description = "Watching a movie with family today"),
Note(title = "A movie day", description = "Watching a movie with family")
)
NoteViewModel:
class NoteViewModel: ViewModel() {
private var notesList = mutableStateListOf<Note>()
init {
notesList.addAll(getNoteData())
}
fun addNote(note: Note) {
notesList.add(note)
}
fun deleteNote(note: Note) {
notesList.removeIf { it.id == note.id }
}
fun getAllNotes() = notesList
}
Navigation:
@Composable
fun Navigation() {
val navController = rememberNavController()
NavHost(navController = navController, startDestination = Screen.NotesScreen.name) {
composable(Screen.NotesScreen.name) {
NotesScreen(navController)
}
composable(Screen.AddScreen.name) {
AddScreen(navController)
}
}
}
AddScreen:
private const val TAG = "AddScreen"
@Composable
fun AddScreen(navController: NavController) {
val noteViewModel: NoteViewModel = viewModel()
var title by remember {
mutableStateOf("")
}
var description by remember {
mutableStateOf("")
}
Log.d(TAG, "AddScreen: Title: $title")
Log.d(TAG, "AddScreen: Description: $description")
Column {
TopAppBar(title = { Text(text = stringResource(id = R.string.app_name)) },
navigationIcon = {
IconButton(onClick = { navController.popBackStack() }) {
Icon(imageVector = Icons.Filled.ArrowBack, contentDescription = "Go back")
}
})
Column(
modifier = Modifier
.padding(10.dp)
.fillMaxWidth(),
horizontalAlignment = Alignment.CenterHorizontally
) {
NoteInputText(
modifier = Modifier.background(Color.White),
text = title,
label = "Title",
onTextChange = {
title = it
}
)
NoteInputText(
modifier = Modifier.background(Color.White),
text = description,
label = "Description",
onTextChange = {
description = it
}
)
NoteButton(text = "Add") {
if(title.isNotBlank() && description.isNotBlank()) {
Log.d(TAG, "AddScreen: Cool, $title, $description")
noteViewModel.addNote(Note(title = title, description = description))
navController.popBackStack()
}
}
}
}
}
NotesScreen:
private const val TAG = "NotesScreen"
@Composable
fun NotesScreen(navController: NavController) {
val noteViewModel: NoteViewModel = viewModel()
val notes = noteViewModel.getAllNotes()
Column {
TopAppBar(
title = { Text(text = stringResource(id = R.string.app_name)) },
actions = {
IconButton(onClick = { navController.navigate(Screen.AddScreen.name) }) {
Icon(imageVector = Icons.Filled.Add, contentDescription = "Add")
}
}
)
if (notes.isNotEmpty()) {
NoteList(onSwipe = {
noteViewModel.deleteNote(it)
})
} else {
Text(
modifier = Modifier.padding(10.dp),
text = "Click on the + icon to add a note",
style = MaterialTheme.typography.h5
)
}
}
}
Screen:
enum class Screen {
NotesScreen, AddScreen
}
Util:
private var previousId = 0L
fun assignIdForNote() = previousId++
MainActivity:
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
NoteAppTheme {
// A surface container using the 'background' color from the theme
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colors.background
) {
Navigation()
}
}
}
}
}
@Preview(showBackground = true)
@Composable
fun DefaultPreview() {
NoteAppTheme {
Navigation()
}
}