Reputation: 211
I'm building an Android app and I wanted to add an option in the settings for the user to choose either he wants to use The app custom font family or just use the dafault system font family and maybe also options for other fonts. Is there an option in compose to do this?
Upvotes: 2
Views: 3852
Reputation: 71
If you are using androidx.compose.material3.Typography, there would be 2 approaches: First one is to copy each style and change the font family.
fun createTypography(parent: Typography, fontFamily: FontFamily): Typography{
return Typography(
parent.displayLarge.copy(fontFamily = fontFamily),
parent.displayMedium.copy(fontFamily = fontFamily),
parent.displaySmall.copy(fontFamily = fontFamily),
parent.headlineLarge.copy(fontFamily = fontFamily),
parent.headlineMedium.copy(fontFamily = fontFamily),
parent.headlineSmall.copy(fontFamily = fontFamily),
parent.titleLarge.copy(fontFamily = fontFamily),
parent.titleMedium.copy(fontFamily = fontFamily),
parent.titleSmall.copy(fontFamily = fontFamily),
parent.bodyLarge.copy(fontFamily = fontFamily),
parent.bodyMedium.copy(fontFamily = fontFamily),
parent.bodySmall.copy(fontFamily = fontFamily),
parent.labelLarge.copy(fontFamily = fontFamily),
parent.labelMedium.copy(fontFamily = fontFamily),
parent.labelSmall.copy(fontFamily = fontFamily)
)
}
the other way is to use reflection:
fun createTypographyReflection(parent: Typography, fontFamily: FontFamily): Typography{
val result = Typography()
Typography::class.java.declaredFields.filter { it.type == TextStyle::class.java }.forEach { field ->
field.isAccessible = true
val textStyle = field.get(parent) as TextStyle
val modifiedTextStyle = textStyle.copy(fontFamily = fontFamily)
field.set(result, modifiedTextStyle)
}
return result
}
Upvotes: 0
Reputation: 3131
For Material3 (Material Design 3):
Note: Unlike the M2 Typography class, the M3 Typography class doesn’t currently include a
defaultFontFamily
parameter. You’ll need to use thefontFamily
parameter in each of the individual TextStyles instead. (Source)
So, here is an example of setting the default font-family in M3:
// Type.kt
import androidx.compose.material3.Typography
import androidx.compose.ui.text.font.Font
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontStyle
import androidx.compose.ui.text.font.FontWeight
import com.example.exampleapp.R
// Declare the font families
object AppFont {
val TitilliumWeb = FontFamily(
Font(R.font.titillium_web_regular),
Font(R.font.titillium_web_italic, style = FontStyle.Italic),
Font(R.font.titillium_web_medium, FontWeight.Medium),
Font(R.font.titillium_web_medium_italic, FontWeight.Medium, style = FontStyle.Italic),
Font(R.font.titillium_web_bold, FontWeight.Bold),
Font(R.font.titillium_web_bold_italic, FontWeight.Bold, style = FontStyle.Italic)
)
}
private val defaultTypography = Typography()
val Typography = Typography(
displayLarge = defaultTypography.displayLarge.copy(fontFamily = AppFont.TitilliumWeb),
displayMedium = defaultTypography.displayMedium.copy(fontFamily = AppFont.TitilliumWeb),
displaySmall = defaultTypography.displaySmall.copy(fontFamily = AppFont.TitilliumWeb),
headlineLarge = defaultTypography.headlineLarge.copy(fontFamily = AppFont.TitilliumWeb),
headlineMedium = defaultTypography.headlineMedium.copy(fontFamily = AppFont.TitilliumWeb),
headlineSmall = defaultTypography.headlineSmall.copy(fontFamily = AppFont.TitilliumWeb),
titleLarge = defaultTypography.titleLarge.copy(fontFamily = AppFont.TitilliumWeb),
titleMedium = defaultTypography.titleMedium.copy(fontFamily = AppFont.TitilliumWeb),
titleSmall = defaultTypography.titleSmall.copy(fontFamily = AppFont.TitilliumWeb),
bodyLarge = defaultTypography.bodyLarge.copy(fontFamily = AppFont.TitilliumWeb),
bodyMedium = defaultTypography.bodyMedium.copy(fontFamily = AppFont.TitilliumWeb),
bodySmall = defaultTypography.bodySmall.copy(fontFamily = AppFont.TitilliumWeb),
labelLarge = defaultTypography.labelLarge.copy(fontFamily = AppFont.TitilliumWeb),
labelMedium = defaultTypography.labelMedium.copy(fontFamily = AppFont.TitilliumWeb),
labelSmall = defaultTypography.labelSmall.copy(fontFamily = AppFont.TitilliumWeb)
)
// Theme.kt
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
@Composable
fun AppTheme(
content: @Composable () -> Unit
) {
MaterialTheme(
typography = Typography,
content = content
)
}
Example for an individual component:
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import com.example.exampleapp.theme.AppFont
@Composable
fun ExampleScreen() {
Text(
text = "Hello World!",
fontFamily = AppFont.TitilliumWeb
)
}
Upvotes: 7
Reputation: 211
I was able to do it by using the defaultFontFamily
parameter, adding an extra parameter to MyAppTheme
Composable and passing the typography object to the MaterialTheme()
constructor instead of the default one as you can see the code below :
fun getTypography(fontFamily: FontFamily) = Typography(
defaultFontFamily = fontFamily
)
In Theme.kt
:
@Composable
fun MyAppTheme(
darkTheme: Boolean = isSystemInDarkTheme(),
// Added fontFamily param
fontFamily: FontFamily = Rubik,
content: @Composable () -> Unit) {
val colors = if (darkTheme) {
DarkColorPalette
} else {
LightColorPalette
}
val typography = getTypography(fontFamily)
MaterialTheme(
colors = colors,
typography = typography,
shapes = Shapes,
content = content
)
}
Upvotes: 1