Basic question, sorry, is there a better way to do...
# compose
g
Basic question, sorry, is there a better way to do what I want to do here? This doesn't actually appear to work:
Copy code
var modifier = Modifier
	if (isSelected) {
		modifier.border(2.dp, Color.White)
	}
The selected item doesn't get a border
s
modifier = modifier.border(2.dp, Color.White)
g
If I do the cast then I get
Copy code
java.lang.ClassCastException: androidx.compose.ui.ComposedModifier cannot be cast to androidx.compose.ui.Modifier$Companion
Full code:
Copy code
@ExperimentalMaterialApi
@Composable
fun MessageRow(loaf: Loaf, editLoafDate: (Loaf) -> Unit, editLoafType: (Loaf) -> Unit, isSelected: Boolean) {
	var modifier = Modifier
	if (isSelected) {
		modifier = modifier.border(2.dp, Color.White) as Modifier.Companion
	}
	ListItem(
		text = {
			Text(
				text = loaf.updateDate.toString(),
				fontWeight = FontWeight.Medium,
				fontSize = 20.sp
			)
		},
		trailing = {
			IconButton(onClick = { editLoafDate(loaf) }) {
				Image(
					imageVector = Icons.Outlined.Edit,
					contentDescription = "Edit Bread Date",
					contentScale = ContentScale.FillBounds,
					colorFilter = ColorFilter.tint(Color.White),
					modifier = Modifier.fillMaxSize(0.8f)
				)
			}
		},
		icon = {
			IconButton(onClick = { editLoafType(loaf) }) {
				Image(
					painter = painterResource(
						if (loaf.icon != 0) loaf.icon else R.drawable.bread_slice
					),
					contentDescription = "Loaf Icon",
					contentScale = ContentScale.FillBounds,
				)
			}
		},
		modifier = modifier
	)
}
s
I see, don't cast... I've created a simple extension
Copy code
inline fun Modifier.applyIf(
    condition: Boolean,
    modifier: Modifier.() -> Modifier
) = if (condition) this.then(modifier()) else this
You can use it like
Copy code
ListItem(...
    modifier = Modifier.applyIf(isSelected) { border(2.dp, Color.White) }
}
g
That works thanks 👍
Is there no way to do it without extending Modifier?
s
@Gabriel I don't know how to get an instance of the Modifier and not use the modifier itself. I wish we had something like Modifier.identity or Modifier.empty. Or it will be a mistake. Personally, I don't mind the extension. Maybe @Sean McQuillan [G] has some advice.
s
That's a weird one, it's type resolving to
Modifier.Companion
which is-a
Modifier
but is also a distinct class, then later when you try to do re-assignment to
Modifier
it fails. Here's a worky solution given the initial code:
Copy code
@Composable
fun ModifierTest() {
    val (isSelected, setSelected) = remember { mutableStateOf(false)}
    var modifier: Modifier = Modifier
    if (isSelected) {
        modifier = modifier.padding(10.dp).border(2.dp, Color.Cyan)
    }
    Column(modifier) {
        Button(onClick = { setSelected(!isSelected) }) {
            Text("Toggle")
        }
    }
}
And how I'd code it slightly differently to turn the
var
into a
val
for kotlin hygene
Copy code
@Composable
fun ModifierTest() {
    val (isSelected, setSelected) = remember { mutableStateOf(false)}
    val modifier = if (isSelected) {
        Modifier.padding(10.dp).border(2.dp, Color.Cyan)
    } else {
        Modifier
    }
    Column(modifier) {
        Button(onClick = { setSelected(!isSelected) }) {
            Text("Toggle")
        }
    }
}
The reason this fails due to type inference on a local but not on a default parameter is that the type is always explicitly specified on a default parameter
Copy code
fun ThingWithModifier(modifier: Modifier = Modifier // actually reads Modifier.Companion and upcasts to Modifier)
cc @Adam Powell ^
👀 1
Also, please don't shy away from defining extensions on Modifier. That is its intended API usage 🙂.
1
👍 1
g
Wow that's great, thanks Sean, it's always good to know why something behaves the way it does 🙂