Reputation: 23
I'm learning programming for the first time in my life. I've spent around 2 weeks learning Kotlin with a free course, and a week learning Jetpack Compose in Android Studio specifically. I've been stuck two days with a practice question, but every answer I encounter on the internet assumes I know more than I know. The practice consists in making a Quadrant like this CorrectQuadrant but unless I make a change that doesn't make sense to me I'm only able to get it like this IncorrectQuadrant.
So the thing is I don't quite understand the modifier parameter, so trying and trying I finally downloaded the solution code and found the mistake, but I cannot understand why it is a mistake. In the code below, in the private function "ComposeInfoCard", you can see a modifier Column argument surrounded by (=====). If I write that argument in lowercase (modifier = modifier) I get the correct Quadrant. If I write it like it is (modifier = Modifier), and that's how I supossed it was correct, the modifier parameter in the private function says "Parameter modifier is never used", and that's not true because I'm using it four times for the weight modifier in the ComposeQuadrant function.
Can someone explain why it needs to be in lowercase, and, if you don't mind, explain the object modifier like I'm a completely new to this?
@Composable
fun ComposeQuadrant(){
Column (modifier = Modifier.fillMaxWidth()){
Row (modifier = Modifier.weight(1f)){
ComposeInfoCard(
title = stringResource(R.string.title1),
description = stringResource(R.string.description1),
backgroundColor = Color(0xFFEADDFF),
modifier = Modifier.weight(1f)
)
ComposeInfoCard(
title = stringResource(R.string.title2),
description = stringResource(R.string.description2),
backgroundColor = Color(0xFFD0BCFF),
modifier = Modifier.weight(1f)
)
}
Row (Modifier.weight(1f)){
ComposeInfoCard(
title = stringResource(R.string.title3),
description = stringResource(R.string.description3),
backgroundColor = Color(0xFFB69DF8),
modifier = Modifier.weight(1f)
)
ComposeInfoCard(
title = stringResource(R.string.title4),
description = stringResource(R.string.description4),
backgroundColor = Color(0xFFF6EDFF),
modifier = Modifier.weight(1f)
)
}
}
}
@Composable
private fun ComposeInfoCard(
title: String,
description: String,
backgroundColor: Color,
modifier: Modifier = Modifier) {
=========================================================
Column (modifier = Modifier
=========================================================
.padding(16.dp)
.background(backgroundColor)
.fillMaxSize(),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
){
Text(
text = title,
fontWeight = FontWeight.Bold,
modifier = Modifier.padding(bottom = 16.dp)
)
Text(
text = description,
textAlign = TextAlign.Justify
)
}
}
Upvotes: 2
Views: 671
Reputation: 1404
Short-Explaination : modifier
small-case is the existing modifier that was created in ComposeQuadrant
with property weight of 1f. When you use Modifier
upper case, you create a new modifier object, so it doesn't have this weight property from before.
Long-Explaination :
Arguments - These are the inputs that you provide when you call the function, the function can then use the input variables. However we need to define the data type parameter of these variable, i.e. whether its a String or an Int, etc.
fun greetMe(greeting : String, name : String) {
print("$greeting to $name")
// the name used here is the one that I get from the code that calls this function
}
Now we, call the function
greetMe("Hi", "Pawan")
The output is
Hi to Pawan
Now, suppose the same greetMe
function is called in this way
greetMe("Pawan", "Hi")
The output is
Pawan to Hi
Is there anything wrong with the code implementation? No! Because both "Pawan" and "Hi" are Strings and that's what the function requires. But is this logically correct? No! because we have provided input in wrong order. To handle this we use named arguments, and we call the function in this way
greetMe(name = "Pawan", greeting = "Hi")
Although the sequence is which we provided the input is wrong, but the output is correct because we have used named arguments, so now they will be mapped to correct variables.
Hi to Pawan
Now coming to question...
ComposeInfoCard(modifier = Modifier.weight(1f))
Here you are calling the ComposeInfoCard
and using named arguments. You create a new Modifier object change its property i.e. set weigh to 1f.
private fun ComposeInfoCard(modifier: Modifier = Modifier) {
}
Okay, so I hope that now you understand the first modifier
, it is a named argument and not a variable. The above line says that you will get a modifier as an arugment
and the data type of it will be Modifier
. The part after =
sign is what we call a default value, i.e. if a modifier is not provided by the calling function, you use this, which in this case is a new Modifier.
So now inside your ComposeInfoCard
method, you have a modifier variable, which is provided by the calling function.
private fun ComposeInfoCard(
// modifer that you get here is not used anywhere
modifier: Modifier = Modifier) {
Column (modifier = Modifier // because here you are creating a new modifier
.background(backgroundColor)
.fillMaxSize()
)
Now here you call another function, which is Column
it also needs a modifier, you have created a new Modifier
object and changed is background color. What you don't want is to create a new Modifier
object but to use the same modifier which is small-case modifier
that you already have.
private fun ComposeInfoCard(
// modifier that you get here
modifier: Modifier = Modifier) {
Column (modifier = modifier // same modifier is passed here with previous properties
.background(backgroundColor)
.fillMaxSize()
)
NOTE : Spend some more time with basics of Kotlin like functions, named arguments, defaults, scope of a variable, lambda functions, etc before moving to complex Library like Jetpack Compose. Maybe try creating some basic projects in Kotlin before moving to Android.
Upvotes: 6
Reputation: 3869
In your ComposeInfoCard
function you have a modifier
parameter of type Modifier
.
Then when you do Column (modifier = modifier
Here you want to use this modifier
parameter. If you do Column (modifier = Modifier
then, instead of using the Modifier you passed as parameter to the function, you create a new Modifier.
That's why you get the message saying that the modifier
parameter is not used, and that your ComposeInfoCard
doesn't behave as espected.
Upvotes: 1
Reputation: 1767
It works with the lowercase modifier because you need to use the one passed from the ComposeQuadrant()
to the ComposeInfoCard
.
If you use the uppercase modifier, Modifier
, then you are constructing a new modifier to use but what you need in your example is the modifier passed as an argument to the ComposeInfoCard
as that has some important decoration such as the weight(1f)
.
What happens in your example is that you have the ComposeQuadrant
function which determines through the weight(1f)
where to place the ComposeInfoCard
. Then the ComposeInfoCard
only cares about its decorations/configurations that it needs such as padding, background and size. In summary, ComposeInfoCard
only cares about it's appearance but not where it's placed in the container. The container will instruct where it's placed and that happens through the modifier: Modifier
argument passed to the ComposeInfoCard
function.
Upvotes: 0