Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android getColor inconsistency

I need to send a color code to the backend server (forwarded to an iOS client) but ContextCompact.getColor(context, colorResourceId); returns a negative value which is unrecognizable by other clients (iOS).

This is the resource HEX value:

<color name="green">#1FAB06</color>

This code below gives me the following negative integer value: -14701818

int color = ContextCompat.getColor(context, mResourceColor);

This negative value converted in hex is:

1FAB06

If I convert this hex value to decimal back, I'm getting: 2075398

public int getColorDecimal(Context context) {
   int color = ContextCompat.getColor(context, mResourceColor);
   String hexColor = String.format("%06X", (0xFFFFFF & color));
   color = Integer.parseInt(hexColor, 16);

   return color;
}

The problem appears if I apply this positive decimal to the View. Android does not recognize this value. The edit-text remains white.

mETName.setTextColor(getColorDecimal(context));

The client and the web-service should have the same value (somehow) because of the data synchronization.

like image 608
Zbarcea Christian Avatar asked Jul 22 '16 16:07

Zbarcea Christian


1 Answers

According to DOCS this method does not return a unsigned decimal int... but an hexadecimal value:

int getColor (Context context, int id)
Returns a single color value in the form 0xAARRGGBB.

Number received is in Alpha/Red/Green/Blue format.

Since your color is full opaque, getColor() automatically returns FF as alpha for your color. So, in fact, you color is: FF1FAB06

They are all the same

All numbers are a representation of the same binary number.

FF1FAB06 is the hexadecimal representation of following binary number:

  ALPHA      RED      GREEN      BLUE
--------- --------- --------- ---------
1111 1111 0001 1111 1010 1011 0000 0110
  F    F    1    F    A    B    0    1

-14701818 is the signed decimal representation of following binary number:

  ALPHA      RED      GREEN      BLUE
--------- --------- --------- ---------
1111 1111 0001 1111 1010 1011 0000 0110
  F    F    1    F    A    B    0    1

Note that 32th Most Significant Bit is 1. So, this number should be read as a negative value in a signed system/variable.

That's why you get a negative number from getColor()

2075398, however, is the following binary number:

  ALPHA      RED      GREEN      BLUE
--------- --------- --------- ---------
0000 0000 0001 1111 1010 1011 0000 0110
  0    0    1    F    A    B    0    1

So, first byte is 00000000. So, Alpha is 00 and in other words, 2075398 is a full transparent color

ANDROID

In case of Android, setTextColor() and getColor() are expecting hexadecimal values in format 0xAARRGGBB.. So, you have to keep that in mind when getting/setting color...

They are expecting Alpha attribute also(and not only red/green/blue). So, for fully opaque color, you have 0xFF******

An hexadecimal value that starts with FF is in fact an negative decimal value for signed int representations...

In fact, everything is just a representation of a binary number in memory

This way, in Android, if you want to set color, you have to keep the negative value since -14701818 is decimal representation of FF1FAB06 hexadecimal (when using signed int which is the case).

If for some reason you need to send the decimal positive value to server, use that positive value only for your server and keep Android Color separated. Otherwise, you must keep converting it to proper system (Android/iOS) everytime you want to use them.

IOS

I'm not sure how IOS handle colors.. But probably, you must covert the value to a format that IOS can handle.

like image 115
W0rmH0le Avatar answered Nov 11 '22 09:11

W0rmH0le