I am making a LibGdx application to be embedded as a Android Fragment.
I am having an issue with passing a Android colour resource to be used in LibGdx
This is my colour
<resources>
<color name="red">#FF0000</color>
</resources>
I pass this colour as follows
ContextCompat.getColor(getContext(),R.color.red)
This returns an int which I convert to float
I have a texture which is a white circle that I colour as so
spriteCircle.setColor(myColor)
This calls upon the Sprite class public void setColor (float color)
The output is not red but a different color
Using one of the Color constants from LibGdx com.badlogic.gdx.graphics.Color yields the correct result so my texture can be coloured correctly so I can rule that out.
My theory is that Android colour has a different format from LibGdx
I wrote this method to help convert that
private com.badlogic.gdx.graphics.Color convertColorToLibGdxColor(int color) {
float alpha = Color.alpha(color);
float red = Color.red(color);
float green = Color.green(color);
float blue = Color.blue(color);
return new com.badlogic.gdx.graphics.Color(red, green, blue, alpha);
}
Note that the Color.red method comes from the android.graphics.Color class
/**
* Return the red component of a color int. This is the same as saying
* (color >> 16) & 0xFF
*/
public static int red(int color) {
return (color >> 16) & 0xFF;
}
There is a method for blue, green and alpha is well.
Then I call the public void setColor (Color tint) from the Sprite class
What is interesting, If I use a Color constant from Android android.graphics.Color such as
#ColorInt public static final int RED = 0xFFFF0000;
It works fine but not my colour resource I posted above
When I compared the two, I can see that my colour resource has the alpha channel omitted so I decided the fill that portion in so now it is
<resources>
<color name="red">#FFFF0000</color>
</resources>
However, I still experience the same issue
Debugging the ContextCompat.getColor(getContext(),R.color.red)
yields a value 0xFFD4172A. I imagine the problem lies here
tl;dr Is it possible to translate a Android colour resource for use in LibGdx?
Thanks
There is actually a method for this in libgdx color class.
https://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/graphics/Color.html#argb8888ToColor-com.badlogic.gdx.graphics.Color-int-
It's also static method but instead of returning a new color, changing existing color.
Thanks to #deniz-yılmaz
LibGdx already has a method for parsing ARGB colours
private com.badlogic.gdx.graphics.Color convertArgbToLibGdxColor(#ColorInt int argbColor) {
com.badlogic.gdx.graphics.Color color = new com.badlogic.gdx.graphics.Color();
com.badlogic.gdx.graphics.Color.argb8888ToColor(color, argbColor);
return color;
}
I found a Gist which actually resolved my issue here
https://gist.github.com/steen919/8a079f4dadf88d4197bb/d732449eb74321207b4b189a3bcbf47a83c5db65
public final class ArgbHexToLibGdxColor {
private ArgbHexToLibGdxColor() {
}
/**
* Taken from https://gist.github.com/steen919/8a079f4dadf88d4197bb/d732449eb74321207b4b189a3bcbf47a83c5db65
* Converts the given hex color in 0xAARRGGBB format to a {#link Color} that can be used in a LibGdx application
*/
public static Color convert(long hex) {
float a = (hex & 0xFF000000L) >> 24;
float r = (hex & 0xFF0000L) >> 16;
float g = (hex & 0xFF00L) >> 8;
float b = (hex & 0xFFL);
return new Color(r / 255f, g / 255f, b / 255f, a / 255f);
}
/**
* Converts a Android color resource into a {#link Color} that can be used in a LibGdx application
*
* #see #convert(long)
*/
public static Color convert(#NonNull Context context, #ColorRes int colorRes) {
return convert(ContextCompat.getColor(context, colorRes));
}
}
This seems to work with colours obtained from the colors.xml file and the constants from the Android Color class
Related
My Web API will send the background color for my views, Background color range is from white #ffffff to black #000000. So I can not set any fix text color for my information text.
What is the best way to set my text color?
I'm thinking to invert the background color and set it as my text color. But I don't know How can I invert Any color or Hex color code.
e.g if my web(background) color is #00ff11 then my text color will be #ff00ee.
For this, I search over stack but did not find any method for color conversion.
Thanks
Try this.
This will give rgb of your hex color. Now you can invert your colors as below.
int invertColor(String myColorString) {
int color = (int)Long.parseLong(myColorString, 16);
int r = (color >> 16) & 0xFF;
int g = (color >> 8) & 0xFF;
int b = (color >> 0) & 0xFF;
int invertedRed = 255 - r;
int invertedGreen = 255 - g;
int invertedBlue = 255 - b;
int invertedColor = Color.rgb(invertedRed, invertedGreen, invertedBlue);
return invertedColor.toString();
}
private PaintType getNegativePaintType(String hexa) {
int color = Color.parseColor(hexa);
return new SolidColor((color & 0xFF000000) | (~color & 0x00FFFFFF));
}
getNegativePaintType("#00ff11") will return "#ff00ee"
Independently of the platform your using, you can achieve that using RGB values simply by subtracting the used color from it's base (255).
So for example:
color = (r,g,b)
invertedColor = (255-r,255-g,255-b)
Then you could transform it to hexadecimal value or whatever you need.
Is there an easy way on Android to set the alpha component of a color retrieved from getResources().getColor(id)?
For example, this is what I'm currently doing to change an existing color to 70% opacity:
DrawerLayout drawerLayout = ...;
int color = getResources().getColor(R.color.bgColor);
color &= 0x00FFFFFF;
color |= (((int) (0.7 * 0xFF)) << 24);
drawerLayout.setScrimColor(color);
using the helper class Color. You can easily retrieve the four components, alpha, red, green, and blue, and set it back with Color.argb, for instance. The class has only static methods, and you don't need to instantiate it. E.g.
int alpha = Color.alpha(color);
int red = Color.red(color);
int green = Color.green(color);
int blue = Color.blue(color);
int newColor = Color.argb((int)(alpha * 0.7f), red, green, blue);
Here you can find the documentation
I'm using the Palette class to programmatically get the most dominant color from an image which I then want to use for my status bar and toolbar. According to the material design guidelines, the status bar color should be two shades darker than the toolbar color.
Bitmap bitmap = ((BitmapDrawable) ((ImageView)mImageView).getDrawable()).getBitmap();
if (bitmap != null) {
palette = Palette.generate(bitmap);
vibrantSwatch = palette.getVibrantSwatch();
darkVibrantSwatch = palette.getDarkVibrantSwatch();
}
For the darker color I'm using the darkVibrantSwatch and for the lighter color, I'm using the vibrantSwatch. But in most of the cases, these turn out to be very different from each other and hence essentially becoming unusable. Is there any workaround for this?
Maybe if its possible to get just one color, say darkVibrantSwatch, and then programmatically generate a color which is two shades lighter?
I'm not sure about getting exactly 2 shades lighter but you can play around with the SHADE_FACTOR and see if you can achieve what you want.
private int getDarkerShade(int color) {
return Color.rgb((int)(SHADE_FACTOR * Color.red(color)),
(int)(SHADE_FACTOR * Color.green(color)),
(int)(SHADE_FACTOR * Color.blue(color)));
}
Code snippet taken from here
An approach that works well is to modify the brightness value in the color's HSV representation:
import android.graphics.Color;
public static int modifyBrightness(int color, float factor) {
float[] hsv = new float[3];
Color.colorToHSV(color, hsv);
hsv[2] *= factor;
return Color.HSVToColor(hsv);
}
To get a suitably darker color for the status bar, use a factor of 0.8:
int darkerColor = modifyBrightness(color, 0.8);
as per title, my question is: Does Android provide any way to analyze/determine if a color (that will be obviously dynamic for the purpose) is light or dark?
Android doesn't provide it, you can implement a method to determine this. Here a method to do that:
public boolean isColorDark(int color){
double darkness = 1-(0.299*Color.red(color) + 0.587*Color.green(color) + 0.114*Color.blue(color))/255;
if(darkness<0.5){
return false; // It's a light color
}else{
return true; // It's a dark color
}
}
If you use support library v4 (or AndroidX), you can use ColorUtils.calculateLuminance(color), which returns luminance of color as float between 0.0 and 1.0.
So you can do something like:
boolean isDark(int color) {
return ColorUtils.calculateLuminance(color) < 0.5;
}
See:
Support library v4: https://developer.android.com/reference/android/support/v4/graphics/ColorUtils.html#calculateLuminance(int)
AndroidX: https://developer.android.com/reference/androidx/core/graphics/ColorUtils#calculateLuminance(int)
Note since Android API 24 there is also method: Color.luminance(color).
In case one would like to find out whether background color is light or dark to determine what color to use for text drawn on top of it (white or black) – calculating luminance won't provide you correct value in all the cases.
Consider you have background color: #7f6fad.
If you check its luminance (via ColorUtils#calculateLuminance) you'll get: 0.1889803503770053, which is below 0.5 and therefore should be considered as dark following that logic.
But if you follow WCAG you'll see that for general text contrast should be at least 4.5:1.
ColorUtils has method calculateContrast which will give the following results:
For white text color: 4.393666669010922
For black text color: 4.779607007540106
One can see that contrast which white text gives is not enough, while black is good.
Therefore if you'd like to check what color to draw on top of some generic background color it is better to check contrasts instead:
#ColorInt
fun getContrastColor(#ColorInt color: Int): Int {
val whiteContrast = ColorUtils.calculateContrast(Color.WHITE, color)
val blackContrast = ColorUtils.calculateContrast(Color.BLACK, color)
return if (whiteContrast > blackContrast) Color.WHITE else Color.BLACK
}
public float getLightness(int color) {
int red = Color.red(color);
int green = Color.green(color);
int blue = Color.blue(color);
float hsl[] = new float[3];
ColorUtils.RGBToHSL(red, green, blue, hsl);
return hsl[2];
}
One could easily use the ColorUtils to check the lightness of a color.
if (getLightness(color) < 0.5f ){
// This color is too dark!
}
Another solution:
private static final int BRIGHTNESS_THRESHOLD = 130;
/**
* Calculate whether a color is light or dark, based on a commonly known
* brightness formula.
*
* #see {#literal http://en.wikipedia.org/wiki/HSV_color_space%23Lightness}
*/
public static boolean isColorDark(int color) {
return ((30 * Color.red(color) +
59 * Color.green(color) +
11 * Color.blue(color)) / 100) <= BRIGHTNESS_THRESHOLD;
}
Simplifying the accepted answer a little
public boolean isColorDark(int color){
final double darkness = 1-(0.299*Color.red(color) + 0.587*Color.green(color) + 0.114*Color.blue(color))/255;
return !(darkness<0.5);
}
If you want to include alpha channel in calculations:
fun isColorDark(color: Int): Boolean {
val darkness = (1 - (0.299 * Color.red(color) + 0.587 * Color.green(color) + 0.114 * Color.blue(color)) / 255) * (Color.alpha(color) / 255)
return darkness >= 0.5
}
In Kotlin using extension function on Int type and with a darkness threshold parameter it can look like the following:
/**
* Determines if this color is dark.
* #param threshold - min darkness value; the higher the value, the darker the color;
* float value between 0.0 and 1.0.
*/
fun Int.isColorDark(#FloatRange(from = 0.0, to = 1.0) threshold: Float = 0.9f): Boolean {
val darkness = 1 - (Color.red(this) * 0.299 + Color.green(this) * 0.587 + Color.blue(this) * 0.114) / 255
return darkness >= threshold
}
I'm working on a simple bar graph application that uses a static array of colors for divvying out bar colors. I would like the functionality to either draw bars normally, or slightly transparent.
Is there a way to programmatically adjust a color integer so that it's slightly transparent? Or will I have to statically define a transparent version of each color and then switch to using these versions whenever I want transparency?
If you are using support library, you can use:
ColorUtils.setAlphaComponent(int color, int alpha);
If you are not using support library, one-line solution taken from it's source code is:
int res = (color & 0x00ffffff) | (alpha << 24);
Sure...Look at Color and there's a function:
static int argb(int alpha, int red, int green, int blue)
Return a color-int from alpha, red, green, blue components.
So your RGB values could be static and you just bump the alpha value to get a new transparent version of the color.
Hi there you could use the:
android.support.v4.graphics.ColorUtils#setAlphaComponent
note: the alpha here is from 0 to 255 and not % based.
There are also other util methods such contract and luminosity calculations in there.
Regards
Try following code
int color = (int)Long.parseLong(your_color, 16);
int r = (color >> 16) & 0xFF;
int g = (color >> 8) & 0xFF;
int b = (color >> 0) & 0xFF;
if color code has alpha then
int alpha= (color >> 24) & 0xFF;
From the top answer I created a method to do this:
private Android.Graphics.Color AddTransparencyToColour(Android.Graphics.Color color, int transparancy)
{
return Android.Graphics.Color.Argb(transparancy, color.R, color.G, color.B);
}
It's also worth noteing that this can be changed to an extension method like so
public static ColorExtensions
{
public static Android.Graphics.Color AddTransparency(this Android.Graphics.Color color, int transparancy)
{
return Android.Graphics.Color.Argb(transparancy, color.R, color.G, color.B);
}
}
In regards to the alpha value, from MSDN Color.FromArgb:
Remarks
To create an opaque color, set alpha to 255. To create a
semitransparent color, set alpha to any value from 1 through 254.
I use extension functions.
fun Int.withAlpha(#IntRange(from = 0, to = 255) alpha: Int): Int {
return (alpha shl 24) or (this and 0xFFFFFF)
}
Also possible with ColorUtils
ColorUtils.setAlphaComponent(color, alpha)
You could create a colour helper which returns same colour with applied alpha. - Lets say you want to change visibility from 0.0 to 1.0 (double)
val originalColour: Int = primaryColor
val generatedColor = ColorUtil.generateTransparentColor(originalColour, 0.5)
view.setBackgroundColor(generatedColor)
Create a colour generator helper
object ColorUtil {
fun generateTransparentColor(color: Int, alpha: Double?): Int {
val defaultAlpha = 255 // (0 - Invisible / 255 - Max visibility)
val colorAlpha = alpha?.times(defaultAlpha)?.roundToInt() ?: defaultAlpha
return ColorUtils.setAlphaComponent(color, colorAlpha)
}
}
Those in the compose world using androidx.compose.ui.graphics.Color can just use the copy-method:
val slightlyTransparentRed = Color.Red.copy(alpha = 0.9f)