Is there a way to consistently override the shape ...
# compose
e
Is there a way to consistently override the shape for a M3
OutlinedTextField
without wrapping it in another composable (too many parameters) or overriding
MaterialTheme.shapes.extraSmall
?
s
Wrap your entire composable, basically where you add your theme maybe?
e
I don't want to override the shape at the theme level though, because other components might use that shape. I could make a wrapper composable just for
TextField
but that's heavyweight because I essentially have to do the following any time I want to use one:
Copy code
MyTextFieldTheme {
  TextField(...)
}
s
Yeah, I think you do in fact want a CustomOutlinedTextField, since if you change it globally it affects other components too, but this is the only thing that alters the shape it seems. What other options might you have?
e
I'm hoping to avoid that because there are so many parameters. I don't think I have any other choices, so this was more of a desperation post to see if anyone had any tricks that might help 😅
s
Yeah I get you. If you don’t want to copy all the different versions with all the different parameters you’d probably have to go with the wrapper solution, which changes the local shapes provided through the MaterialTheme composition locals and inside the content lambda of that simply call the normal OutlinedTextField. Can’t think of some better idea atm, sorry 😢
c
I essentially have to do the following any time I want to use one
Hmm you should be able to include the overridden shape theme in the Composable wrapper. Then you just use that one wrapper all over your project, e.g.
TextFieldWithCustomShape
Making that change within that wrapper should work since it would only affect the children of that overridden theme, i.e. your customized TextField, and not affect its ascendants
e
Yeah that's what I got, but I don't like having to make two function calls to get the
TextField
c
I see. Though that is implied duplicated work if you want to override the theme / the Material designed TextField in only specific cases. But it can be minimized by having your own Composable wrapper
e
Right, but there's a lot of arguments to wrap. Not the end of the world, and I'll probably go with that approach.
c
Yeah TextField does have a lot of parameters. But if you are using it special cases, maybe there’s an opportunity to reduce the amount of parameters you need to wrap and pass.
s
I wonder how you can ensure that you don't use the wrong API then if you provide your own implementation of it with the same name but different parameters. Especially if the team is big and it's hard to let everyone know. Do you do the thing suggested here to have it not come up in the IDE? https://www.jetpackcompose.app/articles/productivity-hack-to-save-tens-of-engineering-hours-when-working-with-Jetpack-Compose Do you provide a lint rule somehow which explains what to use instead? Do you just hope you don't misuse the API which doesn't have this corner change? What do you Optimally do? 🤔
e
Currently my team is small enough that I'm not worried. If/when we grow we'll probably use detekt to enforce it (I'm assuming we can use ForbiddenMethodCall rule for this)
a
For reference, Now in Android has a lint module that will cause an android lint failure if using an underlying component instead of a specifically designed one: https://github.com/android/nowinandroid/tree/main/lint
So that’s one approach if you want to go the tooling route. Or you can trust in agreeing not to use it and code reviews too 😄
s
Ah of course, this is exactly what I wanted to see when I said "somehow" above. NowInAndroid seems to be the gift that keeps on giving 😅 the amount of things I've learned and applied on my work app has been way too high. Thanks so much for that resource, it's invaluable!