deleting item from a mutableStateListOf
it keeps the value of the deleted TextField
passing this value to the other TextField
below. I don't know if this is a error from Jetpack Compose.
This is a bit confusing since I deleted the first line right.
My code:
private var ids = mutableStateListOf<ShoppingCart>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent{
i = intent.getParcelableArrayListExtra("produtos")!!
ids=i.toMutableSet().toMutableStateList()
ids = remember { ids }
MainContent()
}
}
LazyColumn(
modifier = Modifier
.padding(top = 50.dp)
.weight(1f)
.border(4.dp, colorResource(id = R.color.pastel_green))
) {
itemsIndexed(ids) { index, item ->
var quantidades by rememberSaveable(stateSaver = TextFieldValue.Saver) {
mutableStateOf(TextFieldValue(item.product_quant.toString()))
}
TextField(
value = quantidades,
onValueChange = {
quantidades = it
if (it.text.isNotEmpty()) {
item.product_quant = it.text.toInt()
calcular()
}
},
shape = RoundedCornerShape(8.dp),
colors = TextFieldDefaults.textFieldColors(
focusedIndicatorColor = Color.Transparent,
unfocusedIndicatorColor = Color.Transparent,
disabledIndicatorColor = Color.Transparent
),
keyboardOptions = KeyboardOptions(
keyboardType = KeyboardType.Number
),
modifier = Modifier
.width(70.dp)
.height(70.dp)
.padding(top = 20.dp)
)
Button(
onClick = {
ids.removeAt(index)
},
modifier = Modifier
.padding(top = 20.dp, end = 20.dp)
) {
Icon(
Icons.Default.Delete,
stringResource(id = R.string.deletar)
)
}
}
When you're using items
of lazy view, it creates a scope depending on the key
.
And when you pass no key, the default value is item index.
All remember
values inside are bound to that key, so when you remove first cell, second one reuses it remember value, that's what happening in your case. You can pass some item id
to prevent that.
But if you would have many items and would like to scroll your list, you'll see that these items are not gettings saved. You could've create a mutable state list, but it'll be cleaned during screen rotation.
I strongly recommend you out of storing state variables as global variables.
Instead of that, all data that should be shared and which you don't wanna loose should be inside a view model. It's gonna be shared in the whole composable tree, unless you're using compose navigation. For this case check out this answer how you can share it.
As you need to modify product_quant
, I suggest you making it a mutable state, so changes will trigger recomposition.
If you can't update ShoppingCart
, you can create a ShoppingCartState
wrapper, which will have a mutable state and update ShoppingCart
value(if you need this):
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val produtos = intent.getParcelableArrayListExtra("produtos")!!
setContent{
// initializing view model with produtos
viewModel<ScreenViewModel>(
factory = object : ViewModelProvider.Factory {
override fun <T : ViewModel?> create(modelClass: Class<T>) =
ScreenViewModel(produtos) as T
}
)
TestView()
}
}
class ShoppingCartState(val shoppingCart: ShoppingCart) {
private val _product_quant = mutableStateOf(shoppingCart.product_quant)
var product_quant: Int
get() = _product_quant.value
set(value) {
_product_quant.value = value
shoppingCart.product_quant = value
}
}
class ScreenViewModel(ids: List<ShoppingCart>) : ViewModel() {
val shoppingCartStates = ids.map(::ShoppingCartState).toMutableStateList()
fun calcular() {
// do your calculations
}
}
@Composable
fun TestView() {
// you can pass view model as a parameter, but this also
// will return same view model across whole composable tree
val viewModel = viewModel<ScreenViewModel>()
LazyColumn(
modifier = Modifier
.padding(top = 50.dp)
.border(4.dp, Color.Green)//colorResource(id = R.color.pastel_green))
) {
itemsIndexed(viewModel.shoppingCartStates) { index, item ->
Row {
TextField(
value = item.product_quant.toString(),
onValueChange = {
if (it.isNotEmpty()) {
item.product_quant = it.toInt()
viewModel.calcular()
}
},
shape = RoundedCornerShape(8.dp),
colors = TextFieldDefaults.textFieldColors(
focusedIndicatorColor = Color.Transparent,
unfocusedIndicatorColor = Color.Transparent,
disabledIndicatorColor = Color.Transparent
),
keyboardOptions = KeyboardOptions(
keyboardType = KeyboardType.Number
),
modifier = Modifier
.width(70.dp)
.height(70.dp)
.padding(top = 20.dp)
)
Button(
onClick = {
viewModel.shoppingCartStates.removeAt(index)
},
modifier = Modifier
.padding(top = 20.dp, end = 20.dp)
) {
Icon(
Icons.Default.Delete,
"delete"
//stringResource(id = R.string.deletar)
)
}
}
}
}
}