My app uses Material 3; however, I'm also using some libraries that use Material 2. The problem is: to get colors with Material 3 you have to use MaterialTheme.colorScheme, but to get them with Material 2 you have to use MaterialTheme.colors. So, the libraries that use Material 2 use MaterialTheme.colors, but when I create my theme I use MaterialTheme.colorScheme:
val DarkColorScheme = darkColorScheme(
primary = Green,
secondary = Blue,
tertiary = Red,
onSurface = Color.White,
error = Red,
)
#Composable
fun StarDictTheme(
darkTheme: Boolean = true,
// Dynamic color is available on Android 12+
dynamicColor: Boolean = true,
content: #Composable () -> Unit
) {
MaterialTheme(
colorScheme = DarkColorScheme,
typography = Typography,
content = content
)
}
So, in the end the libraries don't use my theme colors, and I get dark elements on a dark background.
Is it possible to fix this? Thanks!
Related
I'm sure this is a newbie question, but I'm trying to implement a Material 3 theme. I have added the themes.kt & colors.kt to my com.my.project.ui.theme package. But I don't understand what I can do next to implement these colors as my app is not using these colors and is still using the default material 3 colors that came when I started the app. I'm not finding the disconnect.
I have added the dependencies and removed the old Material dependency
//implementation 'androidx.compose.material:material:1.3.1'
implementation 'androidx.compose.material3:material3:1.1.0-alpha03'
implementation "androidx.compose.material3:material3-window-size-class:1.1.0-alpha03"
implementation "com.google.accompanist:accompanist-flowlayout:0.24.8-beta"
One thing I notice is the function in themes.kt is saying it is never used (grayed out).
#Composable
fun DzoicTheme(darkTheme: Boolean = isSystemInDarkTheme(), content: #Composable () -> Unit) {
val useDynamicColors = Build.VERSION.SDK_INT >= Build.VERSION_CODES.S
val colors = when {
useDynamicColors && darkTheme -> dynamicDarkColorScheme(LocalContext.current)
useDynamicColors && !darkTheme -> dynamicLightColorScheme(LocalContext.current)
darkTheme -> DarkColors
else -> LightColors
}
MaterialTheme(
colorScheme = colors,
typography = Typography,
shapes = Shapes,
content = content
)
}
Where does this function get called (DzoicTheme)? Default was AppTheme but instructions said to change it. Is the name important here? Most tutorials show utilizing material 3 colors from the activity compose functions but I do all my design in xml layout files, does this matter? Any help here would be appreciated!
I am learning Jetpack compose of Android Development.
Sometimes, I use
MaterialTheme.colors
MaterialTheme.coloScheme
because one of them shows red.
For example,
Surface(
color = MaterialTheme.colorScheme.primary,
modifier = Modifier.padding(vertical = 4.dp, horizontal = 8.dp)
) {
Row(modifier = Modifier.padding(24.dp)) {
Column(modifier = Modifier
.weight(1f)
.padding(bottom = extraPadding)
) {
Text(text = "Hello, ")
Text(text = name)
}
ElevatedButton(
onClick = { expanded.value = !expanded.value }
) {
Text(if (expanded.value) "Show less" else "Show more")
}
}
}
So, what's the difference and which one is better or how to use them properly?
These are 2 different color selection systems. In material design 2 Color swatches with color between 100, and 900 is used. You can check out swatches in material color picker. M3 uses shades between 0-100 from their new color system HCT.
TL;DR
When you pick Composables suc as Button from Material Design2 colors from M2 are used. When you pick Composables from Material Design3 tokens from M3 are used.
Material Design2
When you select primary 500 and 700, for selecting secondary 200 and 700 variants are used.
When you call androidx.compose.material.MaterialTheme.colors.x
you are getting these colors.
Material Design3
For Material Design 3 they invented a new color system(RGB, HSV, HSL) called HCT(hue-colorfulness-tone). If you are interested in details you can check out this blog. Now, instead of colors with 200 and 900 colors are selected as tones between 0 and 100.
There is util library from google that creates these tones from the color you picked. But there was a bug creating colors last time i checked.
I also built a M2, and M3 color selection library that depends google's library for M3 creation.
Google's theme builder to create M3 colors for Compose
When you pick primary, secondary, teriatry in material builder or any tool, or using default colors by creating M3 project variants of 40-20, etc are created for primary, secondary color roles. You might pick Red but its tone(40) is used for Primary color.
#FF00000 -> #c001000
Color Roles
The primary key color is used to derive roles for key components
across the UI, such as the FAB, prominent buttons, active states, as
well as the tint of elevated surfaces.
The secondary key color is used for less prominent components in the
UI such as filter chips, while expanding the opportunity for color
expression.
The tertiary key color is used to derive the roles of contrasting
accents that can be used to balance primary and secondary colors or
bring heightened attention to an element. The tertiary color role is
left for teams to use at their discretion and is intended to support
broader color expression in products.
You can check out official m3 page when to use primary, secondary and teriatry colors
Primary
Primary roles are used for key components across the UI, such as the FAB, prominent buttons, active states, as well as the tint of elevated surfaces.
Secondary
Secondary roles are used for less prominent components in the UI, such as filter chips, while expanding the opportunity for color expression.
Tertiary
Tertiary roles are used for contrasting accents that can be used to balance primary and secondary colors or bring heightened attention to an element, such as an input field.
The tertiary color role is left for makers to use at their discretion and is intended to support broader color expression in products.
How are these in code are like this? As in mentioned above Composables pick respective color tokens, Buttons primary to match with your theme's set colors.
internal object FilledButtonTokens {
val ContainerColor = ColorSchemeKeyTokens.Primary
val ContainerElevation = ElevationTokens.Level0
val ContainerHeight = 40.0.dp
val ContainerShape = ShapeKeyTokens.CornerFull
val DisabledContainerColor = ColorSchemeKeyTokens.OnSurface
val DisabledContainerElevation = ElevationTokens.Level0
const val DisabledContainerOpacity = 0.12f
val DisabledLabelTextColor = ColorSchemeKeyTokens.OnSurface
const val DisabledLabelTextOpacity = 0.38f
val FocusContainerElevation = ElevationTokens.Level0
val FocusLabelTextColor = ColorSchemeKeyTokens.OnPrimary
val HoverContainerElevation = ElevationTokens.Level1
val HoverLabelTextColor = ColorSchemeKeyTokens.OnPrimary
val LabelTextColor = ColorSchemeKeyTokens.OnPrimary
val LabelTextFont = TypographyKeyTokens.LabelLarge
val PressedContainerElevation = ElevationTokens.Level0
val PressedLabelTextColor = ColorSchemeKeyTokens.OnPrimary
val DisabledIconColor = ColorSchemeKeyTokens.OnSurface
const val DisabledIconOpacity = 0.38f
val FocusIconColor = ColorSchemeKeyTokens.OnPrimary
val HoverIconColor = ColorSchemeKeyTokens.OnPrimary
val IconColor = ColorSchemeKeyTokens.OnPrimary
val IconSize = 18.0.dp
val PressedIconColor = ColorSchemeKeyTokens.OnPrimary
}
In Material 2 you would use one and in Material 3 the other. For instance:
Material 2:
Surface(
color = MaterialTheme.colors.surface,
contentColor = contentColorFor(color),
// ...
TopAppBar(
backgroundColor = MaterialTheme.colors.primarySurface,
contentColor = contentColorFor(backgroundColor),
// ...
Material 3:
Card(
colors = CardDefaults.cardColors(
containerColor =
if (isSelected) MaterialTheme.colorScheme.primaryContainer
else
MaterialTheme.colorScheme.surfaceVariant)
) {
Text(
text = “Dinner club”,
style = MaterialTheme.typography.bodyLarge,
color =
if (isSelected) MaterialTheme.colorScheme.onPrimaryContainer
else MaterialTheme.colorScheme.onSurface, ),
….
….
}
They are the same.
colors is available only on material 2 so when you use MaterialTheme.colors you will notice that MaterialTheme is imported from material with import androidx.compose.material.MaterialTheme
colorScheme is available only on material 3 so when you use MaterialTheme.colorScheme you will notice that MaterialTheme is imported from material3 with import androidx.compose.material3.MaterialTheme
So if you are using material 3 in your project make sure that you are working with colorScheme and if you are using material 2 make sure that you are using color.
Basically ,
MaterialTheme.colorScheme.primary is part of Material 3 Design library.
MaterialTheme.colors.background is part of Legacy Material 2 Design Library.
Material 3 library for compose has additional features compared to Material 2.
Currently, I am migrating one of my apps to Material Design 3 which is entirely written in Kotlin using Jetpack Compose.
While using Material Design 2, I was able to change the emphasis of the text using the code below.
CompositionLocalProvider(LocalContentAlpha provides ContentAlpha.medium) {
Text(
text = "Hello, world",
style = MaterialTheme.typography.h6,
fontWeight = FontWeight.SemiBold,
)
}
However, the same code doesn't work for Material Design 3 and the text has the default emphasis. Also, I can't find the relevant function anywhere for Material Design 3. I would like to know if there is any official way to achieve the same effect.
MaterialTheme.typography.h6 is from Material 2, which means you're using Text composable from Material 2 too.
Material 3 analog of h6 is MaterialTheme.typography.headlineSmall.
Make sure you have correct imports of both Text and MaterialTheme - these should be imported from androidx.compose.material3 package. Also make sure you provide a correctly imported theme, e.g. here.
Wrong imports is the most common mistake when migrating to M3, so be patient with it.
Also note that LocalContentAlpha doesn't exists in M3, providing M2 version will have no effect on M3 views. You can compare how Text composable determines its color in M2 and in M3.
I'm not sure wether it's gonna be added later (it's alpha after all), or it's handled in some other way in M3, here's a workaround(which is not perfect for sure):
CompositionLocalProvider(LocalContentColor provides LocalContentColor.current.copy(alpha = 0.4f)) {
p.s. LocalContentColor needs to be imported from M3 too
The "Emphasis and content alpha" section in the Migrate from Material 2 to Material 3 in Compose details the API changes.
Material2:
import androidx.compose.material.ContentAlpha
import androidx.compose.material.LocalContentAlpha
// High emphasis
CompositionLocalProvider(LocalContentAlpha provides ContentAlpha.high) {
Icon(…)
}
// Medium emphasis
CompositionLocalProvider(LocalContentAlpha provides ContentAlpha.medium) {
Icon(…)
}
// Disabled emphasis
CompositionLocalProvider(LocalContentAlpha provides ContentAlpha.disabled) {
Icon(…)
}
Material3:
import androidx.compose.material3.LocalContentColor
// High emphasis
CompositionLocalProvider(LocalContentColor provides MaterialTheme.colorScheme.onSurface) {
Icon(…)
}
// Medium emphasis
CompositionLocalProvider(LocalContentColor provides MaterialTheme.colorScheme.onSurfaceVariant) {
Icon(…)
}
// Disabled emphasis
CompositionLocalProvider(LocalContentColor provides MaterialTheme.colorScheme.onSurface.copy(alpha = 0.38f)) {
Icon(…)
}
I am having the following issue. I am adding some vector drawable images in my project which is built using Jetpack compose. I am overriding the colors of the drawable by setting
android:fillColor="?colorPrimary"
But, the previous solution, even though it works on a usual Android project, when working on Jetpack compose it is not.
Of course, I have initialized a Material Theme with my colors/typo/shapes.
Any suggetions?
Best regards!
I've run into similar issues where compose doesn't play well with attributes. It prefers to access via colorResource(R.color.colorName).
What you might be looking for is either of the below implementations:
Icon(
Icons.Filled,
"contentDescription",
tint = MaterialTheme.colors.secondary
)
Image(
painter = painterResource(R.drawable.resourceName),
contentDescription = "contentDescription",
colorFilter = ColorFilter.tint(Color.myColor)
)
UPDATE:
I actually found something similar with font attributes. You might want to try something like this:
fun getFontFromAttribute(resId: Int, context: Context): Typeface? =
context.obtainStyledAttributes(R.style.MYSTYLE, intArrayOf(resId))
.use { array ->
val resource = array.getResourceId(array.getIndex(0), 0)
if (resource == 0) {
null
} else {
ResourcesCompat.getFont(context, resource) ?: Typeface.SANS_SERIF
}
}
On any Android Studio version up to Bumblebee 2011.1.1 Canary 11, the following View does not render and in fact breaks the Previewer in unexpected ways.
#Preview
#Composable
fun ColoredText(color: Color = Color.Red) = Text("text")
Stable version of Arctic Fox throws a MethodNotFoundError while the canary throws a warning saying it can't find the View. How can I get the preview to work again?
With #Preview Composables the main restriction is that the Preview Composable functions must not take any parameters.
Your ColoredText composable takes color: Color = Color.Red as a parameter hence doesn't render. You will also see the #Preview Annotation on your code highlighted in red.
To preview your code you can make a preview composable named ColoredTextPreview() which doesn't accept any parameter. Use this to preview the ColoredText() and pass in the Color Parameter
#Preview
#Composable
//preview doesn't accept parameters
fun ColoredTextPreview() = ColoredText(Color.Red)
#Composable
//create a 2nd non-preview composable that accepts parameters
fun ColoredText(color1: Color = Color.Red) {
Text(
text = "text",
color = color1,
modifier = Modifier.fillMaxWidth()
)
}
Be sure to include this line of code on your import statements to help with the Colors.
import androidx.compose.ui.graphics.Color
Thanks,