- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我有一部 android 4.0 手机 A 和一部 4.4 平板电脑 B,它们都有一个软件导航栏。我用这个:
showAtLocation(myView, Gravity.NO_GRAVITY, x, y);
在特定位置显示窗口。实际结果是,它在 A 上看起来不错,但在 B 上有一个 y 偏移量。我发现偏移量似乎与 B 的导航栏高度相同。所以我使用以下代码获取高度并进行减法:
private int getNavigationBarHeight(Resources res, Context context) {
final int apiLevel = Build.VERSION.SDK_INT;
if((apiLevel >= Build.VERSION_CODES.HONEYCOMB && apiLevel <= Build.VERSION_CODES.HONEYCOMB_MR2)
||
(apiLevel >= Build.VERSION_CODES.ICE_CREAM_SANDWICH && !ViewConfiguration.get(context).hasPermanentMenuKey())
) {
int resourceId = res.getIdentifier("navigation_bar_height", "dimen", "android");
if (resourceId > 0) {
return res.getDimensionPixelSize(resourceId);
}
}
return 0;
}
新结果是:窗口现在在 B 中正常,但在 A 中显示时,它有一个 y 偏移量。
问题是,我怎样才能使我的窗口在两个设备上都正常显示
最佳答案
今天我遇到了和你完全一样的问题。在我的模拟器上,由于 PopupWindow 的 Gravity.NO_GRAVITY
,PopupWindow 在窗口边界内正确绘制。然而,在我的 Nexus 7 平板电脑上,PopupWindow 显示在底部显示的设备状态栏下方。
在我点击屏幕上的 ImageButton 后,我的 PopupWindow 会出现在那个 ImageButtons 的 y 位置(以及我有 match_parent
的宽度)。这个 ImageButton 的位置可以在窗口的边界内,或者正好/完全在平板电脑的底部状态栏下方。
这是我想出的:
我们有什么:
oldY
)我们计算的内容:
screenHeight - statusBarHeight - popupHeight
)然后我们检查的内容:
oldY
是否大于 maxY
newY
将是 maxY
并且我们重新绘制 PopupWindow。如果不是这种情况,则意味着我们什么都不做,只是使用 oldY
作为正确的 Y 位置。注意 1: 我为此编写了代码,但在调试过程中发现状态栏的高度在我的模拟器和 Nexus 平板电脑上均为 0,因此只需使用 screenHeight - popupHeight
对我来说已经足够了。尽管如此,我还是在我的配置文件中包含了使用 bool 值计算底部状态栏高度的代码以启用/禁用它,以防将来该应用程序安装在另一台平板电脑上。
这是在代码中,我只是添加了上面的描述以明确我使用哪种方法来解决这个问题:
// Get the [x, y]-location of the ImageButton
int[] loc = new int[2];
myImageButton.getLocationOnScreen(loc);
// Inflate the popup.xml
LinearLayout viewGroup = (LinearLayout)findViewById(R.id.popup_layout);
LayoutInflater layoutInflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
final View layout = layoutInflater.inflate(R.layout.popup, viewGroup);
// Create the PopupWindow
myPopupWindow = new PopupWindow(ChecklistActivity.this);
myPopupWindow.setContentView(layout);
myPopupWindow.setWindowLayoutMode(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
... // Some more stuff with the PopupWindow's content
// Clear the default translucent background and use a white background instead
myPopupWindow.setBackgroundDrawable(new ColorDrawable(android.graphics.Color.WHITE));
// Displaying the Pop-up at the specified location
myPopupWindow.showAtLocation(layout, Gravity.NO_GRAVITY, 0, loc[1]);
// Because the PopupWindow is displayed below the Status Bar on some Device's,
// we recalculate it's height:
// Wait until the PopupWindow is done loading by using an OnGlobalLayoutListener:
final int[] finalLoc = loc;
if(layout.getViewTreeObserver().isAlive()){
layout.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
// This will be called once the layout is finished, prior to displaying it
// So we can change the y-position of the PopupWindow just before that
@Override
public void onGlobalLayout() {
// Get the PopupWindow's height
int popupHeight = layout.getHeight();
// Get the Status Bar's height
int statusBarHeight = 0;
// Enable/Disable this in the Config-file
// This isn't needed for the Emulator, nor the Nexus 7 tablet
// Since the calculated Status Bar Height is 0 with both of them
// and the PopupWindow is displayed at its correct position
if(D.WITH_STATUS_BAR_CHECK){
// Check whether the Status bar is at the top or bottom
Rect r = new Rect();
Window w = ChecklistActivity.this.getWindow();
w.getDecorView().getWindowVisibleDisplayFrame(r);
int barHeightCheck = r.top;
// If the barHeightCheck is 0, it means our Status Bar is
// displayed at the bottom and we need to get it's height
// (If the Status Bar is displayed at the top, we use 0 as Status Bar Height)
if(barHeightCheck == 0){
int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0)
statusBarHeight = getResources().getDimensionPixelSize(resourceId);
}
}
// Get the Screen's height:
DisplayMetrics dm = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(dm);
int screenHeight = dm.heightPixels;
// Get the old Y-position
int oldY = finalLoc[1];
// Get the max Y-position to be within Window boundaries
int maxY = screenHeight - statusBarHeight - popupHeight;
// Check if the old Y-position is outside the Window boundary
if(oldY > maxY){
// If it is, use the max Y-position as new Y-position,
// and re-draw the PopupWindow
myPopupWindow.dismiss();
myPopupWindow.showAtLocation(layout, Gravity.NO_GRAVITY, 0, maxY);
}
// Since we don't want onGlobalLayout to continue forever, we remove the Listener here again
layout.getViewTreeObserver().removeOnGlobalLayoutListener(this);
}
});
}
注意 2: 我已将 tag_popup
本身设置为 width = match_parent; height = wrap_content
在这一行:
myPopupWindow.setWindowLayoutMode(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
和这个 Popup 的主要布局为 width = match_parent; height = match_parent
:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE xml>
<!-- The DOCTYPE above is added to get rid of the following warning:
"No grammar constraints (DTD or XML schema) detected for the document." -->
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/popup_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@layout/tag_shape"
android:padding="@dimen/default_margin">
... <!-- Popup's Content (EditTexts, Spinner, TextViews, Button, etc.) -->
</RelativeLayout>
注意 3:
我的应用被迫保持纵向模式。我没有在横向模式下对此进行测试,但我认为应该进行一些修改(虽然不确定)。
编辑:经过测试,它在我的两台设备上也可以在横向模式下工作。我不知道这是否也适用于启用底部栏高度的横向模式。
希望这对您和其他遇到类似问题的人有所帮助。希望他们将来会修复 PopupWindow 的 Gravity
,这样它就永远不会低于状态栏,除非程序员自己想要这个并更改 PopupWindow 的设置。
关于android - PopupWindow.showAtLocation 的确切行为是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25111708/
通过多次搜索和pytorch文档本身,我可以发现在嵌入层内部有一个查找表,用于存储嵌入向量。我无法理解的是: 在这一层的培训期间究竟发生了什么? 权重是多少,以及这些权重的梯度是如何计算的? 我的直觉
当应用程序有大量数据(400M)要写入非阻塞套接字时,write() 返回EWOULDBLOCK 或EAGAIN 当发送缓冲区变满时。 当套接字被(e)轮询时,我有时会看到发送缓冲区中有 7M 空间(
就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引起辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the he
我经常阅读一些编程语言对模块的支持(“一流”)(OCaml,Scala,TypeScript [?]),并且最近偶然发现了这样的答案,即在Scala的显着特征中引用模块作为一流公民。 我以为我很清楚模
我已经提交了一个自定义的开放图表故事,但它被拒绝并显示以下消息: 打开图表捐赠(行动类型)提交内容、操作、对象和使用说明必须以英文提交。您可以在应用程序面板的“本地化”选项卡中翻译操作和对象。 如果我
给定一个任意的 boolean 值列表,确定其中一个恰好为真的最优雅的方法是什么? 最明显的 hack 是类型转换:将 false 转换为 0,将 true 转换为 1,然后对它们求和,并返回 sum
这个问题在这里已经有了答案: When to use extern "C" in simple words? [duplicate] (7 个答案) 关闭 9 年前。 如果您想将此问题标记为重复问题
我是一名优秀的程序员,十分优秀!