未指定大小时弹出窗口弹出窗口
大多数示例都指定了弹出窗口的宽度和高度。我想他们是WRAP_CONTENT - 由于内容dinamically决定的,所以在构造函数中我设置-2宽度和高度,并通过showAsDropDown(查看锚)未指定大小时弹出窗口弹出窗口
这样做表明它,在弹出总是画在锚点视图下方,这意味着它可以在屏幕外画出。以下片段演示了这个问题。尝试点击最后一个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
,而我认为它只是将其解释为宽度= -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是确定哪些意见,布局,把它放在它依赖于你提供的宽度和高度。这意味着,因为您使用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);
我通过调用measure()
方法在弹出的内容视图解决了这个问题:
View content = getPopupContent();
content.measure(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
int measuredHeight = content.getMeasuredHeight();
popup = new PopupWindow(content, ViewGroup.LayoutParams.WRAP_CONTENT, measuredHeight);
我读得源,它似乎更多的A ndroid的bug,因为大小是正确的,但放置是错误的。自从我提供演示以来,您可以亲自测试它。现在我正在试验PopupWindow.showAtLocation() – Raffaele
正如我怀疑你需要在'setWindowLayoutMode'中添加我编辑我的答案并添加到您需要的确切工作代码。我在我的android设备上测试了它,所有东西! :) – Bob
如果下一次调用弹出内容视图更改会发生什么?这就是为什么我需要WRAP_CONTENT – Raffaele