如何在自定义 Android 视图中检查重力标志?
How to check gravity flags in a custom Android View?
问题
我有一个自定义 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
}
其中 mGravity
是从 xml 属性 (like this) 中获得的。
如果我将重力设置为 Gravity.CENTER_VERTICAL
它工作正常。但是我惊奇的发现,如果我设置为Gravity.BOTTOM
,Gravity.CENTER_VERTICAL
的校验依然为真!
为什么会这样?
我不得不查看二进制值以了解原因:
- 二进制:
0001 0000
,Gravity.CENTER_VERTICAL
:常数值:16 (0x00000010)
- 二进制:
0101 0000
,Gravity.BOTTOM
:常量值:80 (0x00000050)
因此,当我这样做时
mGravity = Gravity.BOTTOM;
(mGravity & Gravity.CENTER_VERTICAL) == Gravity.CENTER_VERTICAL
// (0101 & 0001) == 0001
我误报了。
我该怎么办?
那么我该如何检查重力标志呢?
我可以做类似 if (mGravity == Gravity.CENTER_VERTICAL)
的事情,但那样我只会得到完全匹配。如果用户将重力设置为 center_vertical|right
之类的值,那么它将失败。
您可以检查 FrameLayout
如何放置其 children。特别是这段代码:
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:
...
}
Gravity
class 中有掩码:VERTICAL_GRAVITY_MASK
、HORIZONTAL_GRAVITY_MASK
可以帮助您找出应用了哪些重力。
这是对@azizbekian 非常有用的解决方案的补充回答。我添加这个是为了帮助自己更全面地了解重力在幕后的工作原理。
横轴重力
LEFT
和 RIGHT
被称为绝对重力。也就是说,如果用户指定 START
或 END
的相对重力,则它是 converted internally 到 RIGHT
或 LEFT
的绝对重力,具体取决于情况。
0000 0001 CENTER_HORIZONTAL
0000 0011 LEFT
0000 0101 RIGHT
---------
0000 0111 HORIZONTAL_GRAVITY_MASK
关于 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
正如您在此处看到的,START
和 LEFT
仅存在一点点差异。 END
和 RIGHT
相同。因此,如果您直接在 START
和 END
上使用 HORIZONTAL_GRAVITY_MASK
,它们将分别默认为 LEFT
和 RIGHT
。但是,应谨慎使用。 Right-to-left 应考虑语言环境。
垂直轴重力
y 轴重力从 x 轴(水平)重力偏移超过 4 位。
0001 0000 CENTER_VERTICAL
0011 0000 TOP
0101 0000 BOTTOM
---------
0111 0000 VERTICAL_GRAVITY_MASK
双轴
请注意 CENTER
是 CENTER_VERTICAL
和 CENTER_HORIZONTAL
的组合。因此,您也可以使用其中一种重力蒙版进行转换。
0000 0001 CENTER_HORIZONTAL
0001 0000 CENTER_VERTICAL
0001 0001 CENTER
---------
0000 0111 HORIZONTAL_GRAVITY_MASK
0111 0000 VERTICAL_GRAVITY_MASK
位数学
使用位或运算符 (|
) 组合水平和垂直重力。
示例:
int myGravity = Gravity.RIGHT | Gravity.BOTTOM;
0000 0101 RIGHT
0101 0000 BOTTOM
---------
0101 0101 myGravity
将位与运算符 (&
) 与重力掩码之一结合使用,以隔离水平或垂直重力。
例子
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
问题
我有一个自定义 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
}
其中 mGravity
是从 xml 属性 (like this) 中获得的。
如果我将重力设置为 Gravity.CENTER_VERTICAL
它工作正常。但是我惊奇的发现,如果我设置为Gravity.BOTTOM
,Gravity.CENTER_VERTICAL
的校验依然为真!
为什么会这样?
我不得不查看二进制值以了解原因:
- 二进制:
0001 0000
,Gravity.CENTER_VERTICAL
:常数值:16 (0x00000010) - 二进制:
0101 0000
,Gravity.BOTTOM
:常量值:80 (0x00000050)
因此,当我这样做时
mGravity = Gravity.BOTTOM;
(mGravity & Gravity.CENTER_VERTICAL) == Gravity.CENTER_VERTICAL
// (0101 & 0001) == 0001
我误报了。
我该怎么办?
那么我该如何检查重力标志呢?
我可以做类似 if (mGravity == Gravity.CENTER_VERTICAL)
的事情,但那样我只会得到完全匹配。如果用户将重力设置为 center_vertical|right
之类的值,那么它将失败。
您可以检查 FrameLayout
如何放置其 children。特别是这段代码:
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:
...
}
Gravity
class 中有掩码:VERTICAL_GRAVITY_MASK
、HORIZONTAL_GRAVITY_MASK
可以帮助您找出应用了哪些重力。
这是对@azizbekian 非常有用的解决方案的补充回答。我添加这个是为了帮助自己更全面地了解重力在幕后的工作原理。
横轴重力
LEFT
和 RIGHT
被称为绝对重力。也就是说,如果用户指定 START
或 END
的相对重力,则它是 converted internally 到 RIGHT
或 LEFT
的绝对重力,具体取决于情况。
0000 0001 CENTER_HORIZONTAL
0000 0011 LEFT
0000 0101 RIGHT
---------
0000 0111 HORIZONTAL_GRAVITY_MASK
关于 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
正如您在此处看到的,START
和 LEFT
仅存在一点点差异。 END
和 RIGHT
相同。因此,如果您直接在 START
和 END
上使用 HORIZONTAL_GRAVITY_MASK
,它们将分别默认为 LEFT
和 RIGHT
。但是,应谨慎使用。 Right-to-left 应考虑语言环境。
垂直轴重力
y 轴重力从 x 轴(水平)重力偏移超过 4 位。
0001 0000 CENTER_VERTICAL
0011 0000 TOP
0101 0000 BOTTOM
---------
0111 0000 VERTICAL_GRAVITY_MASK
双轴
请注意 CENTER
是 CENTER_VERTICAL
和 CENTER_HORIZONTAL
的组合。因此,您也可以使用其中一种重力蒙版进行转换。
0000 0001 CENTER_HORIZONTAL
0001 0000 CENTER_VERTICAL
0001 0001 CENTER
---------
0000 0111 HORIZONTAL_GRAVITY_MASK
0111 0000 VERTICAL_GRAVITY_MASK
位数学
使用位或运算符 (|
) 组合水平和垂直重力。
示例:
int myGravity = Gravity.RIGHT | Gravity.BOTTOM;
0000 0101 RIGHT
0101 0000 BOTTOM
---------
0101 0101 myGravity
将位与运算符 (&
) 与重力掩码之一结合使用,以隔离水平或垂直重力。
例子
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