Search code examples
gridandroid-jetpack-compose

How to select items in Compose on long click?


I have LazyVerticalGrid with pictures and I want to select items in it on long click. How to do it?

I have Photo function for photo item:

@Composable
    fun Photo(
        photo: Photo,
        navController: NavController,
    ) {
        val painter = rememberAsyncImagePainter(model = photo.uri)
        Box(
            modifier = Modifier
                .width(150.dp)
                .height(150.dp)
                .clickable(
                    onClick = {
                        val args = URLEncoder.encode(photo.uri, StandardCharsets.UTF_8.toString())
                        navController.navigate(Destinations.DetailScreen.withArgs(args))
                    }
                )
        ) {
            Image(
                painter = painter,
                contentDescription = null,
                contentScale = ContentScale.Fit,
            )
        }
    }

And I have main screen. How to make items in LazyVerticalGrid selectable? I need to select several photos and delete them. And I need checkbox to be able to select all the items and delete them.

@Composable
    fun MainScreen(navController: NavController) {

        Box(
            modifier = Modifier
                .fillMaxSize()
                .background(Color(android.graphics.Color.parseColor("#50E1E6")))
        ) {
            LaunchedEffect(Unit) {
                lifecycleScope.launch {
                    lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) {
                        viewModel.allPhotos.collect {
                            photoList = it
                        }
                    }
                }
            }
            if (photoList.isEmpty()) {
                TextContent()
            } else {
                LazyVerticalGrid(
                    columns = GridCells.Fixed(3),
                    contentPadding = PaddingValues(5.dp)
                ) {
                    items(photoList) { photo ->
                        Column {
                            Photo(
                                photo = photo,
                                navController = navController,
                            )
                            Divider(color = Color.Transparent, thickness = 5.dp)
                        }
                    }
                }
            }

            Button(
                onClick = {
                    navController.navigate(Destinations.CameraScreen.routes)
                    startCamera()
                },
                modifier = Modifier.align(Alignment.BottomEnd)
            ) {
                Text(text = "Add a picture")
            }
            DeleteDialog()
        }
    }

Solution

  • Instead of the clickable modifier you need to use the combinedClickable:

    .combinedClickable (
          onLongClick = {},
          onClick = {},
    )
    

    The onLongClicked function should be passed down to your Photo composable from the LazyVerticalGrid:

    val selectedItems = remember { mutableListOf<Int>() }
    
    LazyVerticalGrid(columns = GridCells.Fixed(3)) {
        // you can either save the index or the object's ID if there's one
        itemsIndexed(photos) { index, item ->
            val isSelected = selectedItems.contains(index)
            Photo(photo = item, navController = navController, isSelected = isSelected, onSelected = { selectedItems.add(index) })
        }
    }