MediumTopAppBar Material3 change only big Title - android

I am working with MediumTopAppBar, and i am trying to change the textStyle of the big Title without ruining the small title.
So what i am doing is:
MediumTopAppBar(
title = { HeadlineLargeBlackText(text = "pageTitle") },
navigationIcon = {
IconButton(onClick = { onBackPressed.invoke() }) {
Icon(
imageVector = Icons.Filled.ArrowBack,
contentDescription = stringResource(id = R.string.action_back)
)
}
},
scrollBehavior = scrollBehavior
)
My problem is that when i set it to "HeadlineLargeBlackText" it automatically change the textstyle of both the big and the small text so it looks like this (image taken with both big and small text visible):
What i want is for the bottom to be big, and the top to be small.
When i go into the MediumTopAppBar i do see that the textStyle of the big and the small is set in the TwoRowsTopAppBar as:
titleTextStyle = MaterialTheme.typography.fromToken(TopAppBarMediumTokens.HeadlineFont),
smallTitleTextStyle = MaterialTheme.typography.fromToken(TopAppBarSmallTokens.HeadlineFont),
But ofc that method is private :// So i wonder, is it possible to get access to these big/small texts separately somehow?

Currently the MediumTopAppBar uses the titleLarge and headlineSmall textstyles defined with the typography attribute in your theme.
You can define them in the theme with:
val customTypography = androidx.compose.material3.Typography(
titleLarge = TextStyle(
fontWeight = FontWeight.SemiBold,
fontSize = 22. sp,
lineHeight = 28. sp,
letterSpacing = 0. sp
),
headlineSmall = TextStyle(
fontWeight = FontWeight.SemiBold,
fontSize = 16. sp,
lineHeight = 24. sp,
letterSpacing = 0.15.sp
),
)
If you don't wont to apply them to the whole app, you can apply a custom theme only to the MediumTopAppBar with something like:
Scaffold(
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
topBar = {
AppTheme {
MediumTopAppBar(
title = {
androidx.compose.material3.Text(
"Medium TopAppBar",
maxLines = 1,
overflow = TextOverflow.Ellipsis
)
},
//....
)
},
//....
}
where
fun AppTheme(
useDarkTheme: Boolean = isSystemInDarkTheme(),
content: #Composable() () -> Unit
) {
//...
aMaterialTheme(
colorScheme = colors,
typography = customTypography,
content = content
)
}

Related

Incorrect rendering of text due to letterSpacing in Compose

I have a problem with letterSpacing in Compose.
When I set TextAlign.End, TextOverflow.Ellipsis and style with letterSpacing text gets cut off.
How can I fix this?
code:
val textStyleWithoutLetterSpacing = TextStyle()
val textStyleWithLetterSpacing = TextStyle(letterSpacing = 1.sp)
#Composable
fun Sample() {
Column {
Text(
text = "1234567890 1234567890 1234567890",
textAlign = TextAlign.End,
overflow = TextOverflow.Ellipsis,
maxLines = 1,
style = textStyleWithoutLetterSpacing
)
Text(
text = "1234567890 1234567890 1234567890",
textAlign = TextAlign.End,
overflow = TextOverflow.Ellipsis,
maxLines = 1,
style = textStyleWithLetterSpacing
)
}
}
result:
I faced a similar issue which I believe has to do with combining textAlign = TextAlign.End with overflow = TextOverflow.Ellipsis. I have just had a play with you sample and came up with this (which is similar to how I solved my problem):
val textStyleWithoutLetterSpacing = TextStyle()
val textStyleWithLetterSpacing = TextStyle(letterSpacing = 1.sp)
#Composable
fun Sample() {
Column {
Text(
text = "1234567890 1234567890 1234567890",
textAlign = TextAlign.End,
overflow = TextOverflow.Ellipsis,
maxLines = 1,
style = textStyleWithoutLetterSpacing
)
Box(contentAlignment = Alignment.CenterEnd) {
Text(
text = "1234567890 1234567890 1234567890",
overflow = TextOverflow.Ellipsis,
maxLines = 1,
style = textStyleWithLetterSpacing
)
}
}
}
In essence, I delegated the alignment of the text to the Box component and that seems to bypass the bug in the compose library (v1.2.1 at the time of writing this answer).

Set all text style changes in one place in Compose UI similar to styles.xml

Previously you could define all of your style changes as a single style in XML which was really convenient especially if you had a lot of different styles. The project I'm currently working on has 50+ of these styles defined.
<!-- styles.xml -->
<style name="title_1">
<item name="android:textColor">#color/purple_500</item>
<item name="android:fontFamily">#font</item>
<item name="android:textSize">18sp</item>
<item name="android:maxLines">1</item>
<item name="android:firstBaselineToTopHeight">12sp</item>
<item name="android:lastBaselineToBottomHeight">9sp</item>
</style>
<!-- hello_world.xml -->
<TextView
android:id="#+id/hello_world"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello, World!"
style="#style/title_1" />
While looking to transition to Compose UI, I noticed that certain attributes are separated out. For example baseline can be changed as a modifier while other values can be changed as a text style or a separate parameter in the case of max lines.
// Styles.kt
#Composable
fun Title1(text: String) {
Text(
text = text,
modifier = Modifier.paddingFromBaseline(top = 12.sp, bottom = 9.sp),
maxLines = 1,
style = TextStyle(
color = colorResource(id = R.color.purple_500),
fontFamily = FontFamily(Font(R.font.podkova_semibold)),
fontSize = 18.sp
)
)
}
// MainActivity.kt
setContent {
Title1("Hello, World")
}
This makes it more error prone since they're separated into different parameters and it's easy to forget to apply one of them. I know you could lump all the text styles together, which helps, but was wondering if there was a way to replicate what we had in XML and specify all the modifications in one place.
In my initial approach above I tried creating wrappers around the Text composable with all the predefined changes, but wanted a flexible solution that can take all the Text parameters without having 50+ composables with all the same parameters as the Text composable. Wondering if there's something in the Kotlin language that can help simplify this or if this is just the wrong approach to the problem.
// Would like to avoid having to do this 50+ times
#Composable
fun Title1(
text: String,
modifier: Modifier = Modifier,
color: Color = Color.Unspecified,
fontSize: TextUnit = TextUnit.Unspecified,
fontStyle: FontStyle? = null,
fontWeight: FontWeight? = null,
fontFamily: FontFamily? = null,
letterSpacing: TextUnit = TextUnit.Unspecified,
textDecoration: TextDecoration? = null,
textAlign: TextAlign? = null,
lineHeight: TextUnit = TextUnit.Unspecified,
overflow: TextOverflow = TextOverflow.Clip,
softWrap: Boolean = true,
maxLines: Int = 1,
onTextLayout: (TextLayoutResult) -> Unit = {},
style: TextStyle = LocalTextStyle.current
) {
Text(
text = text,
modifier = modifier
.paddingFromBaseline(top = 12.sp, bottom = 9.sp),
color = color,
fontSize = fontSize,
fontStyle = fontStyle,
fontWeight = fontWeight,
fontFamily = fontFamily,
letterSpacing = letterSpacing,
textDecoration = textDecoration,
textAlign = textAlign,
lineHeight = lineHeight,
overflow = overflow,
softWrap = softWrap,
maxLines = maxLines,
onTextLayout = onTextLayout,
style = style.merge(
TextStyle(
color = colorResource(id = R.color.purple_500),
fontFamily = FontFamily(Font(R.font.podkova_semibold)),
fontSize = 18.sp
)
)
)
}
I think your initial approach is correct in the current version of Jetpack Compose (1.1.1), but they're currently working on APIs to enable setting this within a Text's TextStyle, so you can keep it all in one place, similar to XML.
See Compose UI 1.2.0-beta01: https://developer.android.com/jetpack/androidx/releases/compose-ui#version_12_2
It looks like they'll be adding a lineHeightStyle property to TextStyle, in addition to platformStyle (which allows setting includeFontPadding to false).
You Can create it by making Typography.
object MyStyle{
val myFontFamily = FontFamily(
Font(R.font.custom_font, FontWeight.Bold)
)
val myTypepo = Typography(
bodyLarge = TextStyle(
fontFamily = myFontFamily,
fontWeight = FontWeight.Bold,
fontSize = 16.sp,
lineHeight = 24.sp,
letterSpacing = 0.5.sp
),)
}
Now OnTextView you Can use it like :
Text(text = title, style = MyStyle.myTypepo.bodyLarge)
You can use this code, when you apply your theme and it will be implemented all across the application
MaterialTheme(
colorScheme = MyColorScheme,
typography = MyTypo,
content = {
ProvideTextStyle(value = defaultTextStyle, content)
}
)

How to change Jectpack Compose BasicTextField's text color?

I'm trying to make a search bar using BasicTextField.
The default text color is black and I couldn't find any option to change the text color.
Also I need to change the text size, font and other attributes.
#Composable
fun MyBasicTextField(){
var text by remember { mutableStateOf("Hello") }
BasicTextField(
value = text,
onValueChange = {
text = it
},
decorationBox = { ... },
modifier = Modifier
.fillMaxWidth()
.background(Color.DarkGray, CircleShape)
.padding(10.dp)
)
}
If this is not possible through BasicTextField, is there any other approach to create similar view?
I have tried TextField but there was several problems like removing label, height, background...
You need textStyle parameter. If you prefer using default text style, use LocalTextStyle:
BasicTextField(
// ...
textStyle = LocalTextStyle.current.copy(color = Color.White)
)
Or you can use one of material styles:
BasicTextField(
// ...
textStyle = MaterialTheme.typography.body1.copy(color = Color.White)
)
In addition to other answer, this worked for me in adding textStyle property:
textStyle = TextStyle(
color = Color.White,
fontFamily = FontFamily.SansSerif,
fontSize = 14.sp,
textAlign = TextAlign.Center,
)
here is all the TextStyle attributes that you can set :
https://developer.android.com/reference/kotlin/androidx/compose/ui/text/TextStyle
public constructor TextStyle(
color: Color,
fontSize: TextUnit,
fontWeight: FontWeight?,
fontStyle: FontStyle?,
fontSynthesis: FontSynthesis?,
fontFamily: FontFamily?,
fontFeatureSettings: String?,
letterSpacing: TextUnit,
baselineShift: BaselineShift?,
textGeometricTransform: TextGeometricTransform?,
localeList: LocaleList?,
background: Color,
textDecoration: TextDecoration?,
shadow: Shadow?,
textAlign: TextAlign?,
textDirection: TextDirection?,
lineHeight: TextUnit,
textIndent: TextIndent?
)
If you want to use your current Material theme's colors so that it adapts to light and dark themes, you need to use LocalContentColor.current as well.
val localStyle = LocalTextStyle.current
val mergedStyle = localStyle.merge(TextStyle(color = LocalContentColor.current))
BasicTextField(
textStyle = mergedStyle,
cursorBrush = SolidColor(MaterialTheme.colorScheme.primary),
)
You probably also want to change the color of your cursor brush from the default black one. After some digging, I found that TextField uses the primary color (at least for Material 3).

How can I change TopAppBar position in the jetpack compose

I want to set the "Account" text to the center of TopAppBar and add an icon to the right of TopAppBar, how can I do it?
Scaffold(
scaffoldState = scaffoldState,
topBar = {
TopAppBar(
title = {
Text(
text = stringResource(R.string.account),
style = AppFont.PoppinsTypography.subtitle1
)
},
navigationIcon = {
Icon(
painter = painterResource(id = R.drawable.ic_left),
contentDescription = "back", tint = AppColor.brandColor.BLUE_DE_FRANCE
)
}, actions = {
viewModel.navigateUp()
}, backgroundColor = AppColor.neutralColor.DOCTOR
)
},
)
To align the title text to the center of TopAppbar,
Update
Using Material 3
CenterAlignedTopAppBar(
title = {
Text(
text = stringResource(R.string.account),
style = AppFont.PoppinsTypography.subtitle1
)
},
)
And actions attribute should have the compoosables to add at the end. Use that to add an icon to the right of TopAppBar.
Example,
actions = {
IconButton(onClick = { /*TODO*/ }) {
Icon(
imageVector = Icons.Rounded.ShoppingCart,
contentDescription = "cart",
)
}
},
The old answer, using Material 2
Change title to this,
title = {
Text(
text = stringResource(R.string.account),
textAlign = TextAlign.Center,
modifier = Modifier.fillMaxWidth(),
style = AppFont.PoppinsTypography.subtitle1
)
},
You could just implement a custom layout
#Composable
fun TopBar() {
Scaffold(
topBar = {
Layout(
modifier = Modifier.fillMaxHeight(0.1f), //Fills one-tenth of the screen
content = {
Text("Account")
Icon(
imageVector = Icons.Default.ArrowBack,
contentDescription = "back",
tint = Color.Blue,
)
}
) { measurables, constraints ->
val title = measurables[0].measure(constraints)
val navigationIcon = measurables[1].measure(constraints)
layout(constraints.maxWidth, constraints.maxHeight) {
title.place(
(constraints.maxWidth - title.width) / 2, //Midway
constraints.maxHeight / 2 // Usually Texts acquire maxHeight so we did not need t subtract
)
navigationIcon.place(
(constraints.maxWidth - 1.5 * navigationIcon.width).roundToInt(), //1.5 to add a bit of extra padding from the edge
(constraints.maxHeight - navigationIcon.height) / 2
)
}
}
},
) {
}
}

ClickableText styling in jetpack compose

I am trying to change the style of a clickable text, mostly the font and color of it.
I am using for now:
text = AnnotatedString(stringResource(R.string.forgot_password)),
onClick = { offset ->
Log.d("ClickableText", "$offset -th character is clicked.")
} ```
This just using the default theme.
How can I apply a different color or font or fontsize ?
Thanks
It offers the style parameter. You could just do something like
ClickableText(
text = AnnotatedString(""),
onClick = {},
style = TextStyle(
color = Blue,
fontSize = 26.sp,
fontFamily = FontFamily.Cursive
)
)
If you are using Android Studio, you can just press Ctrl + P on Windows and Cmd + P on Mac to check the available parameters. The optional parameters are not inserted by code completion since they can be many.
To use fonts, define a fontFamily property, like this
private val Montserrat = FontFamily(
Font(R.font.montserrat_regular, FontWeight.Normal),
Font(R.font.montserrat_medium, FontWeight.Medium),
Font(R.font.montserrat_bold, FontWeight.Bold),
)
then add it to your Typography
val Typography = Typography(
h1 = TextStyle(
fontFamily = Montserrat,
fontSize = 96.sp,
fontWeight = FontWeight.Normal,
lineHeight = 117.sp,
letterSpacing = (-1.5).sp
),
which is added to your theme
MaterialTheme(
colors = colors,
typography = Typography,
shapes = Shapes,
content = content
)
If you then use these styles in your text it will pick the family you specified, or you can override, like this
Text(
text = "Sample text",
style = MaterialTheme.typography.body1.copy(
color = Color.Blue,
fontFamily = Montserrat,
),
)
You can use style keyword to add font, for example:
ClickableText(
text = AnnotatedString(text = "Clickable Text Font Example"),
style = TextStyle(
fontFamily = FontFamily(Font(R.font.your_font)),
),
onClick = {}
)

Categories

Resources