'Jetpack Compose - Issues by passing down States
I am new to Kotlin and jetpack compose. So while I get startig, I got my first problem and I can't solve it on my own. The Problem appears, when I started to put the States up in the MainContent-function and pass the States as Arguments to TipCalcSurface. Now I got the following problems:
Type mismatch: inferred type is Int but MutableState<Int> was expected
The other problems are consequential problems of the wrong Type, but why? If I change the type to an Int, the whole function doesn't work. Below my practiceing code.
package com.example.customtippcalc
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.*
import androidx.compose.material.*
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.sharp.KeyboardArrowDown
import androidx.compose.material.icons.sharp.KeyboardArrowUp
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.example.customtippcalc.ui.theme.CustomTippCalcTheme
import com.example.customtippcalc.util.calculateTipPrice
import com.example.customtippcalc.util.calculateTotalPricePerPerson
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
CustomTippCalcTheme {
// A surface container using the 'background' color from the theme
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colors.background
) {
MainContent()
}
}
}
}
}
@Composable
fun MainContent() {
var totalPricePerPerson by remember { mutableStateOf(0.0)}
var personCount by remember { mutableStateOf(1)} // Problem starts here
Column() {
TipCalcHeader(totalPrice = totalPricePerPerson)
TipCalcSurface(
personCount = personCount,
onPriceCalculate = { totalPricePerPerson = it }
)
}
}
@Composable
fun TipCalcHeader(totalPrice: Double = 0.0) {
Column {
Text(text = "Price per person:")
Text(
modifier = Modifier.fillMaxWidth().padding(top = 28.dp, bottom = 28.dp),
textAlign = TextAlign.Center,
fontSize = 24.sp,
fontWeight = FontWeight.Bold,
text = "$totalPrice €"
)
}
}
@Preview(showBackground = true)
@Composable
fun TipCalcSurface(
personCount: MutableState<Int>, // And problem here
onPriceCalculate: (Double) -> Unit = {}
) {
var totalPrice by remember { mutableStateOf(0.0) }
var invoiceAmount by remember { mutableStateOf("")}
var totalTip by remember { mutableStateOf(0.0)}
var sliderAmount by remember { mutableStateOf(0f) }
var sliderAmountAtPercent by remember { mutableStateOf(0)}
Column(modifier = Modifier
.fillMaxWidth()
.padding(13.dp)) {
TextField(
modifier = Modifier.fillMaxWidth(),
value = invoiceAmount,
onValueChange = {invoiceAmount = it},
label = { Text( text = "Totalprice") }
)
Spacer(modifier = Modifier.height(20.dp))
// Person Count Row
Row(modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
Text( text = "Person:")
Row(verticalAlignment = Alignment.CenterVertically) {
Button(onClick = {
personCount ++
totalPrice = calculateTotalPricePerPerson(
personAmount = personCount,
invoiceAmount = invoiceAmount.toDouble(),
tipAmount = totalTip
)
onPriceCalculate(totalPrice)
} ) {
Icon(imageVector = Icons.Sharp.KeyboardArrowUp, contentDescription = "+")
}
Text( modifier = Modifier
.padding(start = 13.dp, end = 13.dp),
text = "$personCount")
Button(
onClick = {
if (personCount > 1) personCount --
totalPrice = calculateTotalPricePerPerson(
personAmount = personCount,
invoiceAmount = invoiceAmount.toDouble(),
tipAmount = totalTip
)
onPriceCalculate(totalPrice)
}) {
Icon(imageVector = Icons.Sharp.KeyboardArrowDown, contentDescription = "-")
}
}
}
Spacer(modifier = Modifier.height(20.dp))
// Tip Amount Row
Row(modifier = Modifier
.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween) {
Text( text = "Tip in €:")
Text( text = "$totalTip €")
}
Spacer(modifier= Modifier.height(20.dp))
// Tip Percentage Slider
Row(modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween
) {
Text( text = "Tip in %:")
Text( text = "$sliderAmountAtPercent")
}
Slider(
value = sliderAmount,
onValueChange = {
sliderAmount = it //(it * 100).toInt()
sliderAmountAtPercent = (sliderAmount*100).toInt()
totalTip = calculateTipPrice(
totalPrice = invoiceAmount.toDouble(), // Fehler bei kovertierung zu Double wenn Wert leer
tipAtPercent = sliderAmountAtPercent)
totalPrice = calculateTotalPricePerPerson(
personAmount = personCount,
invoiceAmount = invoiceAmount.toDouble(),
tipAmount = totalTip
)
onPriceCalculate(totalPrice)
})
}
}
Thanks for help!
Solution 1:[1]
When you do var personCount by remember { mutableStateOf(1)}, then the type of personCount is Int. You are not assigning the MutableState<Int> to personCount, but delegating to it.
In order to make it work, you should pass the personCount as an Int to TipCalcSurface, as well as adding a updatePersonCount: (Int) -> Unit function to it. You can then call that function when you want to update personCount.
Like this:
fun TipCalcSurface(
personCount: Int,
updatePersonCount: (Int) -> Unit = {},
onPriceCalculate: (Double) -> Unit = {}
) {
// Fix the code mutating personCount to instead call updatePersonCount.
}
@Composable
fun MainContent() {
var totalPricePerPerson by remember { mutableStateOf(0.0) }
var personCount by remember { mutableStateOf(1) }
Column() {
TipCalcHeader(totalPrice = totalPricePerPerson)
TipCalcSurface(
personCount = personCount,
updatePersonCount = { personCount = it }
onPriceCalculate = { totalPricePerPerson = it }
)
}
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | marstran |
