Search code examples
javaandroidandroid-layoutflagsandroid-gravity

How to check gravity flags in a custom Android View?


The problem

I have a custom Android view in which I want get the user set gravity in order to layout the content in onDraw. Here is a simplified version that I am using in onDraw:

// check gravity
if ((mGravity & Gravity.CENTER_VERTICAL) == Gravity.CENTER_VERTICAL) {
    // draw the content centered vertically
} else if ((mGravity & Gravity.BOTTOM) == Gravity.BOTTOM) {
    // draw the content at the bottom
}

where mGravity is obtained from the xml attributes (like this).

If I set the gravity to Gravity.CENTER_VERTICAL it works fine. But I was surprised to find that if I set it to Gravity.BOTTOM, the Gravity.CENTER_VERTICAL check is still true!

Why is this happening?

I had to look at the binary values to see why:

Thus, when I do

mGravity = Gravity.BOTTOM;
(mGravity & Gravity.CENTER_VERTICAL) == Gravity.CENTER_VERTICAL
//  (0101 & 0001) == 0001

I get a false positive.

What do I do?

So how am I supposed to check the gravity flags?

I could do something like if (mGravity == Gravity.CENTER_VERTICAL), but then I would only get an exact match. If the user set gravity to something like center_vertical|right then it would fail.


Solution

  • You can examine how FrameLayout lays its children. Particularly, this code:

    final int layoutDirection = getLayoutDirection();
    final int absoluteGravity = Gravity.getAbsoluteGravity(gravity, layoutDirection);
    final int verticalGravity = gravity & Gravity.VERTICAL_GRAVITY_MASK;
    
    switch (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
        case Gravity.CENTER_HORIZONTAL:
            ...
        case Gravity.RIGHT:
            ...
        case Gravity.LEFT:
            ...
    }
    
    switch (verticalGravity) {
        case Gravity.TOP:
            ...
        case Gravity.CENTER_VERTICAL:
            ...
        case Gravity.BOTTOM:
            ...
    }
    

    There're masks in Gravity class: VERTICAL_GRAVITY_MASK, HORIZONTAL_GRAVITY_MASK which will help you to find out what gravities have been applied.