In Type.kt Typography I defined h1 TextStyle like this:
h1 = TextStyle(
fontFamily = FontFamily.SansSerif,
fontWeight = FontWeight.W500,
fontSize = 70.sp,
color = Color(0xFFF8F9FC)
),
Now how can I define the Text widget to be an h1 so these TextStyles applies automatically?
You can get the current theme h1 from any #Composable with MaterialTheme.typography.h1, so your widget might look like this:
#Composable
fun TextH1(
text: String,
modifier: Modifier = Modifier,
) {
Text(
text = text,
modifier = modifier,
style = MaterialTheme.typography.h1,
)
}
If you plan on using your style globally for all text that you want identified as h1, you should create a custom composable for that and apply your style there:
#Composable
fun TextH1(
text: String,
modifier: Modifier = Modifier
) {
Text(text = text, modifier = modifier, textStyle = h1)
}
Alternatively, you could use CompositionLocal, but that tends to become cumbersome if used extensively.
Related
I faced with a problem related to Text element in Jetpack Compose. I wanted to place two separated Text elements under each other but I can't remove their inner paddings to make them look like not so separated.
As you can see on pic below Text with "02" has these paddings. Is there any way to crop them?
I tried to use .offset() and .height() modifiers to change the Text box size, but it looks like a really awful solution.
Code example to reproduce:
Box(
modifier = Modifier
.height(65.dp)
.width(65.dp)
.background(Color.White)
) {
Column(
modifier = Modifier
.align(Alignment.Center)
) {
Text(
text = "00",
maxLines = 1,
overflow = TextOverflow.Clip,
style = MaterialTheme.typography.h5.copy(
fontWeight = FontWeight.SemiBold
),
color = Color.Black,
modifier = Modifier
.align(Alignment.CenterHorizontally)
)
Text(
text = "Text",
style = MaterialTheme.typography.body2,
color = Color.Gray,
modifier = Modifier.align(Alignment.CenterHorizontally)
)
}
}
Thanks in advance!
I have a sample which I use Jetpack compose in it : https://github.com/alirezaeiii/SampleCompose
Here is my Theme for the application which is the default by Android Studio :
#Composable
fun ComposeTheme(darkTheme: Boolean = isSystemInDarkTheme(), content: #Composable() () -> Unit) {
val colors = if (darkTheme) {
DarkColorPalette
} else {
LightColorPalette
}
MaterialTheme(
colors = colors,
typography = Typography,
shapes = Shapes,
content = content
)
}
Base on this when I am in dark mode, Text's color are light. as an example Texts in my List items:
#Composable
fun VerticalListItem(item: Poster, callback: OnClickListener) {
val typography = MaterialTheme.typography
Column(
modifier = Modifier
.fillMaxWidth()
.padding(16.dp)
.clickable(onClick = { callback.onClick(item) })
) {
ImageView(url = item.poster, height = 150.dp)
Spacer(Modifier.height(16.dp))
Text(
text = item.name,
style = typography.h6
)
Text(
text = item.release,
style = typography.body2
)
Text(
text = item.playtime,
style = typography.subtitle2
)
}
}
I have a DetailView as follow :
#Composable
fun DetailView(item: Poster, pressOnBack: () -> Unit, sendNotification: () -> Unit) {
val typography = MaterialTheme.typography
Column(
modifier = Modifier
.verticalScroll(rememberScrollState())
.fillMaxHeight()
) {
Box {
ImageView(url = item.poster, height = 420.dp)
Icon(
imageVector = Icons.Filled.ArrowBack,
tint = Color.White,
contentDescription = null,
modifier = Modifier
.padding(12.dp)
.clickable(onClick = pressOnBack)
)
}
Spacer(Modifier.height(8.dp))
Button(
onClick = sendNotification,
modifier = Modifier.align(Alignment.CenterHorizontally)
) {
Text(text = "DeepLink")
}
Spacer(Modifier.height(8.dp))
Surface {
Text(
modifier = Modifier.padding(8.dp),
text = item.description,
style = typography.body2
)
}
}
}
As you see Text here is surrounded by Surface, otherwise it will be Dark in Dark mode. Why is that? Why my other Texts for instance in VerticalListItem do not need Surface? I also have a Button in DetailView which is showing Light in Dark mode. I can not understand why this specific Text need Surface.
The tint is derived from the parent content color. The box is not a surface, has no background so the content color is indifferent. Anyway you don't have to wrap it in a surface, just set the color for the text:
MaterialTheme.colors.onSurface
or
color = contentColorFor(background)
I am trying to remove padding from TextButton but it wont work.
TextButton(
onClick = {},
modifier = Modifier.padding(0.dp)
) {
Text(
" ${getString(R.string.terms_and_conditions)}",
color = MaterialTheme.colors.primary,
fontFamily = FontFamily(Font(R.font.poppins_regular)),
fontSize = 10.sp,
)
}
I have tried setting the height and size in Modifier property as well but the padding is still present
Wrap the TextButton with CompositionLocalProvider to override the value of LocalMinimumTouchTargetEnforcement. This will only remove the extra margin but will not modify the defaultMinSize which is hardcoded.
CompositionLocalProvider(
LocalMinimumTouchTargetEnforcement provides false,
) {
TextButton(
onClick = {},
contentPadding = PaddingValues(),
) {
Text(
"Button",
color = MaterialTheme.colors.primary,
fontSize = 10.sp,
)
}
}
You cannot reduce padding with the padding modifier: it always adds an extra padding on top of the existing padding. See this reply for more details about the order of modifiers.
You can reduce TextButton padding with contentPadding argument, by specifying PaddingValues(0.dp), but this will not fully remove the padding.
If you need fully remove the padding, you can use the clickable modifier instead:
Text(
"getString(R.string.terms_and_conditions",
color = MaterialTheme.colors.primary,
fontFamily = FontFamily(Font(R.font.neris_semi_bold)),
fontSize = 10.sp,
modifier = Modifier
.clickable {
// onClick()
}
)
If you want to change the color of the ripple, as is done in TextButton, you can do it as follows:
.clickable(
interactionSource = remember { MutableInteractionSource() },
indication = rememberRipple(color = MaterialTheme.colors.primary),
) {
}
You can achieve it changing the contentPadding and applying a fixed size:
TextButton(
onClick = {},
contentPadding = PaddingValues(0.dp),
modifier = Modifier.height(20.dp).width(40.dp)
) {
Text(
"Button",
color = MaterialTheme.colors.primary,
fontSize = 10.sp,
)
}
If you come across unwanted margins. When you use onclick in any Button function, it sets propagateMinConstraints = true inside the view's surface - this will apply to unwanted margins. Example how solve this problem:
#Composable
fun ButtonWithoutOuterPadding(
onClick: () -> Unit,
modifier: Modifier = Modifier,
shape: Shape = RectangleShape,
elevation: Dp = 0.dp,
color: Color = Color.Transparent,
border: BorderStroke? = null,
contentAlignment: Alignment = Alignment.Center,
content: #Composable () -> Unit
) {
Box(
modifier
.shadow(elevation, shape, clip = false)
.then(if (border != null) Modifier.border(border, shape) else Modifier)
.background(
color = color,
shape = shape
)
.clip(shape)
.then(
Modifier.clickable(
interactionSource = remember { MutableInteractionSource() },
indication = LocalIndication.current,
enabled = true,
onClickLabel = null,
role = null,
onClick = onClick
)
),
contentAlignment = contentAlignment,
propagateMinConstraints = false
) {
content()
}
}
How do I reference a resource style from Compose widget?
styles.xml
<style name="Style.Monet.TextView.HeaderSubtext" parent="Widget.AppCompat.TextView">
<item name="android:textColor">#737373</item>
<item name="android:textSize">12sp</item>
<item name="android:layout_marginStart">16dp</item>
<item name="android:layout_marginBottom">16dp</item>
<item name="android:layout_marginEnd">24dp</item>
</style>
MyComponent.kt
Text(text = "June 2021", style = TextStyle(R.style.Style_TextView_HeaderSubtext))
But this doesn't work. Is there a way to make this work?
You can't do that, because Compose Text is styled differently, and TextStyle it not responsible so all xml style is responsible. As an example, you cannot add margins.
You can create compose TextStyle:
val textStyle = TextStyle(
color = Color(0xFF737373),
fontSize = 12.sp,
)
And use it globally in your project or pass to your theme. This is a preferred way to use styles in compose, check out more about it in the theming documentation. Customize one of material available styles:
val typography = Typography(
body1 = TextStyle(
color = Color(0xFF737373),
fontSize = 12.sp,
)
)
Pass it to your theme:
#Composable
fun ComposePlaygroundTheme(
darkTheme: Boolean = isSystemInDarkTheme(),
content: #Composable () -> Unit
) {
val colors = if (darkTheme) {
DarkThemeColors
} else {
LightThemeColors
}
MaterialTheme(
colors = colors,
typography = typography,
shapes = shapes,
content = content,
)
}
Apply Theme at the composable root:
setContent {
ComposePlaygroundTheme {
// your composables
}
}
After that you can use it like this:
Text("",
style = MaterialTheme.typography.body1,
)
To apply margins in compose you need to use padding modifier. Check out more about layout in compose in the layout documentation:
If you wanna reuse same styled text in compose, you can create your own composable with predefined style and padding:
#Composable
fun ProjectText(text: String, modifier: Modifier) {
// without material theme you can just define text style here and pass to text
// val textStyle = TextStyle(
// color = Color(0xFF737373),
// fontSize = 12.sp,
)
Text("",
style = MaterialTheme.typography.body1,
modifier = modifier
.padding(start = 16.dp, end = 24.dp, bottom = 16.dp)
)
}
Usage:
ProjectText("June 2021")
I want to use material icons as argument passing it to the textField.
#Composable
fun NormalTextField(
icon: () -> Unit, // how to pass material icon to textField
label: String
) {
val (text, setText) = mutableStateOf("")
TextField(
leadingIcon = icon,
value = text,
onValueChange = setText,
label = label
)
}
The leadingIcon argument of texfield is a composable function (the label too), so one way to do it is:
#Composable
fun Example() {
NormalTextField(label = "Email") {
Icon(
imageVector = Icons.Outlined.Email,
contentDescription = null
)
}
}
#Composable
fun NormalTextField(
label: String,
Icon: #Composable (() -> Unit)
) {
val (text, setText) = mutableStateOf("")
TextField(
leadingIcon = Icon,
value = text,
onValueChange = setText,
label = { Text(text = label) }
)
}
This can be done using InlineTextContent. Here is an example how to insert the icon at the start of the text. You can wrap this into another composable if you just want to pass the icon as a parameter.
Text(text = buildAnnotatedString {
appendInlineContent("photoIcon", "photoIcon")
append("very long breaking text very long breaking text very long breaking text very long breaking text very long breaking text")
}, inlineContent = mapOf(
Pair("photoIcon", InlineTextContent(
Placeholder(width = 1.7.em, height = 23.sp, placeholderVerticalAlign = PlaceholderVerticalAlign.TextTop)
) {
Image(
painterResource(R.drawable.ic_cameraicon),"play",
modifier = Modifier.fillMaxWidth().padding(end = 10.dp),
alignment = Alignment.Center,
contentScale = ContentScale.FillWidth)
}
)), lineHeight = 23.sp, color = Color.White, fontFamily = HelveticaNeue, fontSize = 18.sp, fontWeight = FontWeight.Medium)
The result would look like this: