In official Material Design 3 resources (e.g. the Figma design kit), there have been many references to colors called "Surface at +x". These colors are the surface color mixed with x% of the primary color.
Now my question:
How can you implement the "Surface at +x" colors in Jetpack Compose? There is no documentation and no property on the MaterialTheme.colorScheme object.
Figma Design Kit reference:
In case anyone need to get it in a non-compose code, use SurfaceColors enums:
int colorSurface1 = SurfaceColors.SURFACE_2.getColor(context);
Documentation can be found here
Update September 2022
With Material 3, if for some reason you need the elevate color surface but you can't use the Surface, now you can use directly:
MaterialTheme.colorScheme.surfaceColorAtElevation(4.dp)
Surface uses MaterialTheme.colorScheme.surface by default, they also have a new tonalElevation property which you can read about here.
The gist of it is that increasing the tonal elevation changes the color automatically, try it yourself:
Surface(tonalElevation = 5.dp) {
// content
}
Related
With Jetpack Compose, using Material 2, you can see if a theme is in light mode easily with the following
val light = MaterialTheme.colors.isLight
Using Material 3, I don't see this ability. Is there a way to do this with a Material 3 theme?
Found a solution. Color in Compose has a built in method luminance that returns the relative luminance as a float between 0 and 1. I wrote an extension function for ColorScheme that returns true if the luminance of the background is greater than 0.5.
#Composable
fun ColorScheme.isLight() = this.background.luminance() > 0.5
Using it as:
val isLight = MaterialTheme.colorScheme.isLight()
Now whether the system is in dark mode doesn't matter, only the theme.
In JetpackCompose you can use this method that returns if the light / dark mode is enabled or not
isSystemInDarkTheme()
And then in your code
if (isSystemInDarkTheme()){} \\Dark mode enabled
else {} //Light mode enabled
Is there a way to create OverscrollEffect in jetpack compose?
Something like this:
The overscroll effect can be controlled by the LocalOverscrollConfiguration, which currently has the following parameters:
glowColor - color for the glow effect, if the platform effect is a glow effect, otherwise ignored.
forceShowAlways - force show overscroll even if content doesn't scroll (is smaller than a scrollable container itself)
drawPadding - the amount of padding to apply from scrollable container bounds to effect before drawing it
CompositionLocalProvider(
LocalOverscrollConfiguration provides OverScrollConfiguration(
glowColor = Color.Gray,
forceShowAlways = false,
drawPadding = PaddingValues()
)
) {
// effected views
}
If you think there should be more parameters, you can let the maintainers know by creating a feature request.
p.s. in 1.2.0-rc01 LocalOverScrollConfiguration has being renamed to LocalOverscrollConfiguration
We have a View based Android app with some drawables in res/drawable folder, and their counterpart for night mode in res/drawable-night folder
When using legacy views, referencing a drawable R.drawable.foo from a XML layout file, the system would pick the drawable from either res/drawable or res/drawable-night folders depending on whether we are in day or night mode.
When using jetpack compose, we reference the drawable in an Image composable like this:
Image(painter = painterResource(R.drawable.foo))
However, this always pick the drawable from res/drawable folder, ignoring day / night mode.
We could do something like this to select the right drawable, but we would need to test the night mode (isSystemInDarkTheme()) within all composables that uses drawables depending on nigh mode:
Image(painter = painterResource(id = if (isSystemInDarkTheme()) R.drawable.foo_dark else R.drawable.foo_light))
Is there a way in compose to ensure that the drawable from day or night mode are picked correctly, and transpartently, as in legacy view system?
Maybe Compose was updated since the other answers were posted, but I can confirm that in a simple app using only Compose and two drawables with the same name in drawable and drawable-night folders, the app is picking up the dark one, if the phone is set to dark mode.
That's also without a composable theme defined, so this simple code does the job:
#Preview
#Preview(uiMode = UI_MODE_NIGHT_YES)
#Composable
fun ImagePreview() {
Image(
painter = painterResource(id = R.drawable.my_icon),
contentDescription = null
)
}
Note that you can also see this in a Preview - having two #Preview annotations produces two previews in Android Studio, and specifying that you want to see your composable in dark mode is also possible!
Seeing how the dark & light palette is currently implemented in the theming codelab I'd go with creating my own somewhat similar abstraction:
class LightDrawables: Drawables
class DarkDrawables: Drawables
fun getDrawable(darkTheme: Boolean = isSystemInDarkTheme(), #DrawableRes drawableRes: Int) = if(darkTheme) DarkDrawables.xy else LightDrawables.xy
As of now, "NO".
How to use /drawable-night?
Google provided support for some basic compose utils through Accompanist which does not come with standard Jetpack Compose. For example, PagerLayout, Swipe Refresh and many more.
One of those utils is Drawable Painter and that is something you can use.
After you add dependency, you can use this util using:
#Composable
fun DrawDrawable() {
val drawable = AppCompatResources.getDrawable(LocalContext.current, R.drawable.foo)
Image(
painter = rememberDrawablePainter(drawable = drawable),
contentDescription = "content description",
)
}
Document Source
Note:
Don't expect dark variant of the drawable to show up in #Preview. But it will be loaded at runtime.
I make Viewpager and there is only ImageView.
that images from server. So it can be bright or dark.
and there is Layout for notice current page / totalPage like this.
Now I want to make if Image is bright, notice layout make dark.
and if Image is dark, notice layout make bright.
So. My Question is
How can I know current image is bright or dark?
And How I can make complementary color from image?
The Android Support Library r21 and above includes the Palette class, which lets you extract prominent colors from an image. To extract these colors, pass a Bitmap object to the Palette.generate() static method in the background thread where you load your images. If you can't use that thread, call the Palette.generateAsync() method and provide a listener instead.
To use the Palette class in your project, add the following Gradle dependency to your app's module:
implementation 'androidx.palette:palette:$version'
To get the color from image:
Palette.generateAsync(bitmap, new Palette.PaletteAsyncListener() {
public void onGenerated(Palette palette) {
// Do something with colors...
}
});
The palette library attempts to extract the following six color profiles:
Light Vibrant,
Vibrant,
Dark Vibrant,
Light Muted,
Muted and
Dark Muted.
Finding complementary color is very simple in RGB model. For any given color, for example, red (#FF0000) you need to find the color, which, after being added to red, creates white (0xFFFFFF). Naturally, all you need to do, is subtract red from white and get cyan (0xFFFFFF - 0xFF0000 = 0x00FFFF).
v7.palette to extract colors from images. now my problem is i am limited to only one swatch, and my question is how to get all the swatches allowing the palette to extract all the colors from the image and using that color .Please help
N.B: Everything is working fine,Palette is working fine but with a small collection of colors
public void updateColor(){
final Bitmap bitmap = mImageFetcher.getArtwork(Utils.getAlbumName(),
Utils.getCurrentAlbumId(), Utils.getArtistName());
Palette palette = Palette.generate(bitmap);
// Getting the different types of colors from the Image
Palette.Swatch vibrantSwatch = palette.getVibrantSwatch();
// Adding the colors to the TextViews.
if(vibrantSwatch!=null) {
// Changing the background color of the toolbar to Vibrant Light Swatch
toolbar.setBackgroundDrawable(new ColorDrawable(vibrantSwatch.getRgb()));
if (Build.VERSION.SDK_INT >= 21) { // setStatusBarColor only works above API 21!
getWindow().setStatusBarColor(vibrantSwatch.getRgb());
}
}
}
Palettes intend is to extract the main colors not to give you a distribution of colors. You will have to look elsewhere for such a feature.
Check out Color Extractor (https://github.com/RacZo/ColorExtractor), it is a little app that I build as a proof of concept. It shows how to use the new Palette and Palette Builder classes to get colors and swatches from an image.
Palette has a method getSwatches() which will return a list of Swatches.
(maybe this method did not exist when this question was asked)