Android conflict between Kotlin Int and Java int representation - android

I have colors stored as IntArrays this is a simple function to convert to the argb color value used by Android.
fun IntArray.toColor(): UInt {
var color: Long = 0xFF000000
val maxIndex = size - 1
this.withIndex().forEach { (index, value) ->
color = color or (value.toLong() shl (8 * (maxIndex - index)))
}
return color.toUInt()
}
If you look at Android's own source code, you'll find color notation expressed as below
...
#ColorInt public static final int RED = 0xFFFF0000;
#ColorInt public static final int GREEN = 0xFF00FF00;
#ColorInt public static final int BLUE = 0xFF0000FF;
...
If I try to use the same value e.g. 0xFFFF0000 as Kotlin Int it's not possible, says the literal doesn't conform to the type Int. So I use UInt in my method.
Android's own code(in Java) android.graphics.Paint.setColor(#ColorInt int color) requires int and in my Kotlin Code I can only use and Int and not a UInt and when I use UInt.toInt() the value gets messed up.
Example
val color = arrayOf(0x11, 0x22, 0x33).toIntArray().toColor()
print(color.toString(16)) // ff112233 (UInt)
print(color.toInt().toString(16)) // -eeddcd (Int)
How do I convert any Kotlin type larger then Int to Int with the value intact?
Is it possible to solve this without calling Java in Kotlin?
Thanks

Kotlin Int should work well. Have you tried to use this value as color? Nevermind that color.toInt().toString(16) returns -eeddcd. It should return that because Int value dedicates highest bit for sign. That's representation issue, but the actual value is 0xff112233. So Kotlin Int with value -eeddcd when you pass it to setColor should look same as 0xff112233.
So try implement your function Int.toColor as follows:
fun IntArray.toColor(): Int {
var color: Int = 0xFF000000.toInt()
val maxIndex = size - 1
this.withIndex().forEach { (index, value) ->
color = color or (value shl (8 * (maxIndex - index)))
}
return color
}

I have tested the colors in working code. It's working fine, the issue is in Kotlin's string representation.

Related

Create color int from alpha, red, green, blue in Android

How do I create a color int from alpha, red, green, blue values (all from 0-255)?
I need this color int to set a view's background color.
I tried this:
protected int colorStringToColor(String colorString){ // whereas colorString is i.e. "214+13+22+255" or "214+13+22+85"
String[] comps = colorString.split("\\+");
int myColor = 0;
if(comps.length == 3){
int a = 255;
int r = Integer.parseInt(comps[0]);
int g = Integer.parseInt(comps[1]);
int b = Integer.parseInt(comps[2]);
myColor = Color.argb(a, r, g, b);
} else if (comps.length == 4){
int a = Integer.parseInt(comps[3]);
int r = Integer.parseInt(comps[0]);
int g = Integer.parseInt(comps[1]);
int b = Integer.parseInt(comps[2]);
myColor = Color.argb(a, r, g, b);
}
return myColor;
}
However, when I use the result for setting a views background color, both example colorString are of the same red???
Thanks a lot.
You can convert it by using the argb(int red, int green, int blue) method from Color class like this :
int convertedColor= Color.argb(red, green, blue);
and set it into your view like this:
yourView.setBackgroundColor(convertedColor);
Color opaqueRed = Color.valueOf(0xffff0000); // from a color int
Color translucentRed = Color.valueOf(1.0f, 0.0f, 0.0f, 0.5f);
int nonTransparentRed = Color.argb(255, 255, 0, 0);
From your question, it seems you're not annotating the return value of the function by #ColorInt.
Change your function to
#ColorInt
private int colorStringToColor(){...};
Also, in your function, annotate
#ColorInt int myColor = 0;
Android has android.graphics.Color class, which provides methods to operate on Colors.
To get a ColorInt from ARGB values, you can use Color.argb(int alpha, int red, int green, int blue);
method, which will return you corresponding ColorInt value.
You can find more about Color class from here
android.graphics.Color
Your code is perfect there is no issue.
One thing is that, if you send this "214+13+22+85" value as integer then you will get the result value as the sum of these values. so may you have done mistake there.
import android.graphics.Color;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = findViewById(R.id.txt);
textView.setTextColor(colorStringToColor("214+13+22+235"));
}
public int colorStringToColor(String colorString){ // whereas colorString is i.e. "214+13+22+255" or "214+13+22+85"
String[] comps = colorString.split("\\+");
int myColor = 0;
if(comps.length == 3){
int a = 255;
int r = Integer.parseInt(comps[0]);
int g = Integer.parseInt(comps[1]);
int b = Integer.parseInt(comps[2]);
myColor = Color.argb(a, r, g, b);
} else if (comps.length == 4){
int a = Integer.parseInt(comps[3]);
int r = Integer.parseInt(comps[0]);
int g = Integer.parseInt(comps[1]);
int b = Integer.parseInt(comps[2]);
myColor = Color.argb(a, r, g, b);
}
return myColor;
}
I Implement your code in my project, and I checked it by well. What I saw there! It's working.
I'm going to go ahead an agree with Prince here, your code is fine. But, also offer a theory. You are setting the view color and it's stripping the transparency. Check your numbers are they different? They should be. When you feed them into setBackgroundColor they are do the same thing. If I recall correctly it doesn't actually set the alpha. Try stripping off the alpha and using in view.setAlpha(color>>24) after you set the color. Is that functionally different?
Prince is feeding it into setTextColor rather than setBackgroundColor.
view.setBackgroundColor(color);
view.setAlpha(color>>24);

ARGB Hex Colour To LibGdx Colour

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

Background color of a textView and seekBar value in android

I'm working on this project in which I use a seekBar to change color of a figure. That figure is represented by a textView with a specific background color set in xml. And while i change the value of the seekBar the color should vary.
let's say textView has color #xxxxxx. I want to get the value of this color and modify it propotionaly with the value of the seekBar.
For example , if :
Case 1 : seekBar value increases 0 - > max => #yyyyyy (a different color for each value of the seekBar)
Case 2 : seekBar value decreases max-> 0 => #xxxxxx (same as above)
I know how to get the color of a textView :
ColorDrawable cd = (ColorDrawable) textView.getBackground();
int colorCode = cd.getColor();`
and also how to make the logic of the "increasing" and "decreasing" values of seekBar value.
I just can't figure it out how to use "progress" and color code together to go from x to y and from y to x.
every color is composed by red green blue
so try this:
public int getColor(int progress) {
int startColor = Color.parseColor("#xxxxxx");
int endColor = Color.parseColor("#yyyyyy");
int start_red = Color.red(startColor);
int start_green = Color.green(startColor);
int start_blue = Color.blue(startColor);
int end_red = Color.red(endColor);
int end_green = Color.green(endColor);
int end_blue = Color.blue(endColor);
int progress_red = start_red + (end_red - start_red) * progress / 100;
int progress_green = start_green + (end_green - start_green) * progress / 100;
int progress_blue = start_blue + (end_blue - start_blue) * progress / 100;
int progress_color = Color.rgb(progress_red, progress_green, progress_blue);
return progress_color;
}
You have to write method
int toColor(int progress)
which converts progress value from method onProgressChanged() of seekbar to int color, which you than set to background of textview:
textView.setBackgroundColor(convertedColor);

decimal to char coding

I am trying to convert a decimal into a character.
I have my alphabet which has been converted to a charArray
String alphabet = "abcdefghijklmnopqrstuvwxyz";
alpha = alphabet.toCharArray();
I was using binary numbers so values only from 0 to 255, however when I try to execute this code, it does not work.
private int toChar(int encryptCode){
int base = 26;
int characterSteps = (encryptCode/255)*base;
char character = alpha[characterSteps];
return character;
Lets say I have the decimal 78, 78/255 * 26 would give 7.95 (being int rounds to 8)
It should look up the alpha array and give 'h'. But every character gives 'a' meaning that (encryptCode/255)*base isn't working as intended.
Kevin is right in the comments. Try rearranging your formula like this:
int characterSteps = (encryptCode*base)/255;
change
int characterSteps = (encryptCode/255)*base;
to
int characterSteps = (int) (encryptCode/255.0)*base;
and you are done! 255.0 will cause broadening on encryptCode and base, and then cast to int.
Lets say I have the decimal 78, 78/255 * 26 would give 7.95 (being int rounds to 8)
Casting float/double to int will result in truncation and not round off. 7.95 will be truncated to 7 and not 8. To round the integer, use this:
double x = (encryptCode/255.0)*base;
int characterSteps = (int) Math.round(x);
Happy Coding! :)

Programmatically make a color more transparent

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)

Categories

Resources