0

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()
    }
}
AzureStar123
  • 196
  • 7
  • 2
    Check out the concept of [minimum reproducible example](https://stackoverflow.com/help/minimal-reproducible-example). Reduce your code as much as possible - often you will be able to localize the problem and solve it yourself, otherwise it will be easy for others to help you. – Phil Dukhov May 19 '22 at 09:09

1 Answers1

0

The reason your add functionality is not working is you were operating on a independent NoteViewModel on AddScreen, which is different with NotesScreen's NoteViewModel. You can check both noteViewModel's hashCode to verify.

聂超群
  • 1,659
  • 6
  • 14