大多数示例都准确指定了弹出窗口的宽度和高度。我希望它们是 WRAP_CONTENT - 因为内容是动态确定的,所以在构造函数中我将宽度和高度都设置为 -2 并通过 showAsDropDown(View anchor)
显示它这样做,弹出窗口总是绘制在 anchor View 下方,这意味着它可以绘制在屏幕外。以下代码段演示了该问题。尝试单击最后一个 TextView,您将看不到任何 PopupWindow,因为它显示在窗口边界之外。为什么它不起作用?我注意到明确指定维度(例如 200、100)不会触发问题。自己试试看
package com.zybnet.example.popupdemo;
import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.LinearLayout;
import android.widget.PopupWindow;
import android.widget.TextView;
public class PopupDemoActivity extends Activity implements OnClickListener {
private PopupWindow popup;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// -2 means WRAP_CONTENT THIS TRIGGERS THE PROBLEM
popup = new PopupWindow(getPopupContent(), -2, -2);
// When you specify the dimensions everything goes fine
//popup = new PopupWindow(getPopupContent(), 200, 100);
LinearLayout layout = new LinearLayout(this);
layout.setOrientation(LinearLayout.VERTICAL);
// FILL_PARENT and same layout weight for all children
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(-1, -1, 1);
for (int i = 0; i < 10; i++) {
TextView tv = new TextView(this);
tv.setText("Click to show popup");
tv.setOnClickListener(this);
layout.addView(tv, params);
}
setContentView(layout);
}
@Override
public void onClick(View view) {
popup.dismiss();
popup.showAsDropDown(view);
}
private View getPopupContent() {
TextView popupContent = new TextView(this);
popupContent.setText("Some text here");
popupContent.setTextColor(Color.parseColor("#5000ae"));
popupContent.setBackgroundColor(Color.parseColor("#ff00ff"));
popupContent.setPadding(10, 20, 20, 10);
return popupContent;
}
}
最佳答案
我开始怀疑在 PopupWindow
的上下文中 -2,-2 实际上意味着 WRAP_CONTENT
而我认为它只是将它解释为 width = -2 高度 = -2
这是来自 Android 的源代码
public PopupWindow(View contentView, int width, int height, boolean focusable) {
if (contentView != null) {
mContext = contentView.getContext();
mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
}
setContentView(contentView);
setWidth(width);
setHeight(height);
setFocusable(focusable);
}
其中 setWidth(int width)
只是一个简单的 mWidth = width;
我认为您正在寻找的是 setWindowLayoutMode (int widthSpec, int heightSpec)方法。那是您应该传入 WRAP_CONTENT
如果所有其他方法都失败了,请测量 TextView
的宽度和高度,然后按预期使用 setWidth
和 setHeight
。
编辑:
我自己试了一下,加上这行代码就可以了
// -2 means WRAP_CONTENT THIS TRIGGERS THE PROBLEM
popup = new PopupWindow(getPopupContent(), 200, 100);
popup.setWindowLayoutMode(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
// When you specify the dimensions everything goes fine
//popup = new PopupWindow(getPopupContent(), 200, 100);
LinearLayout layout = new LinearLayout(this);
layout.setOrientation(LinearLayout.VERTICAL);
我把原来的评论留在那里,这样你就可以自己看看所有的东西应该放在哪里。
编辑 2: 好的,所以我使用了您发布的代码并在我的设备上逐字逐句地尝试了它,您是对的,它没有用,因为当 Android 确定将其放置在哪个 View 中时,它取决于您提供的宽度和高度.这意味着因为你使用 0 和 0 作为你的宽度和高度,Android 会出现并说,“哦看,这个框只是一个 0 x 0 的框所以我可以将它显示为内容下方的弹出窗口。”这不是我们想要的!问题是,您知道盒子会比那个大,所以让我们开始输入一些不同的数字并查看由此产生的结果。
popup = new PopupWindow(getPopupContent(), 1, 1);
现在,当我点击底部框时,请注意它跳到了上方。 (见屏幕截图)这是因为 Android 知道宽度和高度为 1(正如我在构造函数中设置的那样)并且列表项下方的可用屏幕空间为 0。好吧,如果没有足够的空间在那里显示它,那么它必须在上面然后!
但是等等!如果像我当前的示例一样,字符串每次都会添加更多内容怎么办?好吧,这就是事情变得有趣的地方。你看,在我的下一个屏幕截图中,弹出窗口虽然应该向上显示,因为它现在有 6 行长,但实际上显示在底部!哦,废话,对!那是因为它是根据我在构造函数中使用的 1 1
进行测量的。那么有什么解决方案呢?
解决方案一:我的首选方法是猜测 TextView
的平均最大高度是多少,然后简单地输入一个一般较大的数字。
popup = new PopupWindow(getPopupContent(), 300, 300); //just guessing it won't get bigger than that
方案二:这个比较合适,但是牺牲了一点速度。使用 Paint
类来测量文本内容的大小,并将其传递到 setWidth()
和 setHeight()
之前你显示弹出窗口。我继续构建了一个几乎完整的解决方案,但我没有测量填充和其他东西(见评论)
private int maxWidth;
private int maxHeight;
private Paint p = new Paint();
private Rect bounds = new Rect();
private View getPopupContent() {
maxWidth = 0;
maxHeight = 0;
TextView popupContent = new TextView(this);
popupContent.setText(popupText += "\n" + DEMO);
popupContent.setTextColor(Color.parseColor("#5000ae"));
popupContent.setBackgroundColor(Color.parseColor("#ff00ff"));
popupContent.setPadding(10, 20, 20, 10);
//the measure can only work line by line so I split it up by line
String[] temp = popupText.split("\n");
for (String s : temp){
//measure each line of string and get its width and height
p.getTextBounds(s, 0, s.length(), bounds);
//keep a running total of the longest width
maxWidth = (bounds.width() > maxWidth) ? bounds.width() : maxWidth;
//add up each of the heights
maxHeight += bounds.height();
}
//also take in account the padding too... if you REALLY want it to be completely robust
//probably adding another 20 or 30 to the maxHeight should be good
return popupContent;
}
然后在 onClick()
中我添加了这两行
popup.setHeight(maxHeight);
popup.setWidth(maxWidth);
关于android - 未指定大小时 PopupWindow 超出屏幕,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7696246/