How to get the vertical and horizontal alignment by an integer?

1

I'm trying to convert an integer value to a content alignment. The integer can hold both a horizontal and a vertical alignment at the same time.

First I created an enum, which describes all possibilities (i have to use the values of android Gravity class: http://developer.android.com/reference/android/view/Gravity.html)

typedef enum{
    GravityHorizontalCenter         = 1,    // (0x00000001) 
    GravityLeft                     = 2,    // (0x00000002) 
    GravityRight                    = 5,    // (0x00000005) 
    GravityVerticalCenter           = 16,   // (0x00000010) 
    GravityTop                      = 48,   // (0x00000030) 
    GravityBottom                   = 80,   // (0x00000050) 
} GravityType;

So int alignment = GravityRight | GravityTop would be 53.

I want to check the alignment of my view-objects like this:

if ((textAlignment & GravityHorizontalCenter) == GravityHorizontalCenter){

    return NSTextAlignmentCenter;
}...

But there seems to be something missing, because for 53 the if statement textAlignment & GravityHorizontalCenter) == GravityHorizontalCenter returns True.

ios
objective-c
alignment
bit-shift
bitmask
asked on Stack Overflow Jun 7, 2013 by Chrizzor • edited Jun 7, 2013 by khellang

2 Answers

2

You need masks for the the Vertical and Horizontal ranges.

typedef enum{
    GravityHorizontalCenter         = 1,    // (0x00000001) 
    GravityLeft                     = 2,    // (0x00000002) 
    GravityRight                    = 5,    // (0x00000005) 
    GravityHorizontalMask           = 7,    // (0x00000007) 
    GravityVerticalCenter           = 16,   // (0x00000010) 
    GravityTop                      = 48,   // (0x00000030) 
    GravityBottom                   = 80,   // (0x00000050) 
    GravityVerticalMask             = 112,  // (0x00000070) 
} GravityType;

Then you can do a test with:

(textAlignment & GravityHorizontalMask) == GravityHorizontalCenter

or

(textAlignment & GravityVerticalMask) == GravityTop

These values are only really suitable for direct comparison, since 5 (101 binary) and 1 (001 binary) overlap as bit masks. But since you are storing two values in the same number (the first 4 bits for the horizontal alignment, and the second 4 bits for the vertical alignment), you need a mask to isolate the range of bits that you want to compare.

Also, you should be aware that on Android the value of LEFT (the left gravity constant) is 3 and not 2. So if your enum really needs to be compatible with Android then your GravityLeft value is probably incorrect.

answered on Stack Overflow Jun 7, 2013 by James Holderness • edited Jun 7, 2013 by James Holderness
1

Because these values are not suited for being used as bit flags (masks).

& is not magic - it's just the bitwise AND operator. And if you bitwise AND a number with 1 then you compare the result to 1, that only checks if the least significant bit was set in the original number, i. e. if it was odd. Thus, (textAlignment & GravityHorizontalCenter) == GravityHorizontalCenter will yield true for any odd number.

If you want to use numbers as flags, you have to make them different powers of two, like this:

GravityHorizontalCenter         = 1,
GravityLeft                     = 2,
GravityRight                    = 4,
GravityVerticalCenter           = 8,
GravityTop                      = 16,
GravityBottom                   = 32,
answered on Stack Overflow Jun 7, 2013 by (unknown user)

User contributions licensed under CC BY-SA 3.0