如何在自定义Android视图中检查重力标记?

Sur*_*gch 17 java flags android android-layout android-gravity

问题

我有一个自定义的Android视图,我想让用户设置重力以布局内容onDraw.这是我正在使用的简化版本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
}
Run Code Online (Sandbox Code Playgroud)

其中mGravity从XML属性(获得这样).

如果我将引力设置为Gravity.CENTER_VERTICAL它可以正常工作.但我很惊讶地发现,如果我把它设置为Gravity.BOTTOM,那么Gravity.CENTER_VERTICAL检查仍然是真的!

为什么会这样?

我必须查看二进制值才能看出原因:

因此,当我这样做

mGravity = Gravity.BOTTOM;
(mGravity & Gravity.CENTER_VERTICAL) == Gravity.CENTER_VERTICAL
//  (0101 & 0001) == 0001
Run Code Online (Sandbox Code Playgroud)

我得到了误报.

我该怎么办?

那么我该怎么检查重力旗呢?

我可以做类似的事情if (mGravity == Gravity.CENTER_VERTICAL),但那时我只会得到完全匹配.如果用户将重力设置为类似的center_vertical|right那么它就会失败.

azi*_*ian 17

你可以检查一下FrameLayout它的孩子.特别是,这段代码:

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:
        ...
}
Run Code Online (Sandbox Code Playgroud)

还有就是口罩Gravity类:VERTICAL_GRAVITY_MASK,HORIZONTAL_GRAVITY_MASK这将帮助你找出已经被应用了哪些比重.


Sur*_*gch 6

这是对@azizbekian非常有用的解决方案的补充回答。我添加此内容是为了帮助自己更充分地了解重力在幕后的工作方式。

水平轴重力

LEFTRIGHT称为绝对重力。即,如果用户指定START或的相对重力END,则根据情况将其在内部转换RIGHT或的绝对重力LEFT

0000 0001  CENTER_HORIZONTAL
0000 0011  LEFT
0000 0101  RIGHT
---------  
0000 0111  HORIZONTAL_GRAVITY_MASK
Run Code Online (Sandbox Code Playgroud)

关于START和的注释END

1000 0000 0000 0000 0000 0011  START
0000 0000 0000 0000 0000 0011  LEFT
1000 0000 0000 0000 0000 0101  END
0000 0000 0000 0000 0000 0101  RIGHT
-----------------------------
0000 0000 0000 0000 0000 0111  HORIZONTAL_GRAVITY_MASK
Run Code Online (Sandbox Code Playgroud)

如您在这里看到的,START并且LEFT只有一点点差异。END和和相同RIGHT。因此,如果HORIZONTAL_GRAVITY_MASK直接在START和上使用END,则它们分别默认为LEFTRIGHT。但是,应谨慎使用。应考虑从右到左的语言环境。

垂直轴重力

y轴重力从x轴(水平)重力移了4位。

0001 0000  CENTER_VERTICAL
0011 0000  TOP
0101 0000  BOTTOM
---------
0111 0000  VERTICAL_GRAVITY_MASK
Run Code Online (Sandbox Code Playgroud)

两轴

请注意,CENTER是一个组合CENTER_VERTICALCENTER_HORIZONTAL。因此,您还可以使用重力蒙版之一对其进行转换。

0000 0001  CENTER_HORIZONTAL
0001 0000  CENTER_VERTICAL
0001 0001  CENTER
---------
0000 0111  HORIZONTAL_GRAVITY_MASK
0111 0000  VERTICAL_GRAVITY_MASK
Run Code Online (Sandbox Code Playgroud)

位数学

使用位OR运算符(|)组合水平和垂直重力。

例:

int myGravity = Gravity.RIGHT | Gravity.BOTTOM;

0000 0101  RIGHT
0101 0000  BOTTOM
---------
0101 0101  myGravity
Run Code Online (Sandbox Code Playgroud)

将位AND运算符(&)与一个重力掩码一起使用以隔离水平或垂直重力。

int verticalGravity = myGravity & Gravity.VERTICAL_GRAVITY_MASK;
if (verticalGravity == Gravity.BOTTOM) ...

0101 0101  myGravity
0111 0000  VERTICAL_GRAVITY_MASK
---------
0101 0000  verticalGravity
0101 0000  BOTTOM
Run Code Online (Sandbox Code Playgroud)