大多数例子都精确地指定了弹出窗口的宽度和高度。我希望它们是包装内容-因为内容是由数据决定的,所以在构造函数中,我为宽度和高度设置了-2,并通过showasdropdown(视图锚定)显示出来
执行此操作时,弹出窗口始终绘制在锚定视图的下方,这意味着可以在屏幕外绘制。下面的代码片段演示了这个问题。尝试单击最后一个文本视图,您将看不到任何弹出窗口,因为它显示在窗口边界之外。为什么不起作用?我注意到显式地指定维度(例如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;
}
}
最佳答案
我开始怀疑在aPopupWindow
的上下文中,-2实际上意味着WRAP_CONTENT
而我认为它只是将它解释为width=-2 height=-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:
好吧,我把你发布的代码一字不差地放在我的设备上,你说得对,它不起作用,因为当安卓决定放在哪个视图中时,它依赖于你提供的宽度和高度。这意味着,因为你使用0和0作为宽度和高度,android会过来说,“哦,看,这个框只是一个0×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);