大多数示例都指定了弹出窗口的宽度和高度。我希望它们是WRAP_CONTENT - 因为内容是由dinamically确定的,所以在构造函数中我为宽度和高度设置-2并通过 showAsDropDown(View anchor)显示它
执行此操作时,弹出窗口始终绘制在锚点视图下方,这意味着它可以在屏幕外绘制。以下代码段演示了此问题。尝试单击最后一个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;
}
}
答案 0 :(得分:16)
我开始怀疑在PopupWindow
的情况下,-2,-2实际上意味着WRAP_CONTENT
,而我认为它只是将其解释为width = -2 height = -2
这是来自Android Source
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);
答案 1 :(得分:7)
我通过在弹出式内容视图中调用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);
答案 2 :(得分:0)
var selectedDays = modifyRecordData.selectedDays;
var splitSelectedDays = selectedDays.split(',');
splitSelectedDays.forEach(day => {
let val = day.trim();
if(val == 'Mon') {
$('#mon').removeClass('btn-default');
$('#mon').addClass('btn-primary');
}
if (val == 'Tue') {
$('#tue').removeClass('btn-default');
$('#tue').addClass('btn-primary');
}
if (val == 'Wed') {
$('#wed').removeClass('btn-default');
$('#wed').addClass('btn-primary');
}
if (val == 'Thur') {
$('#thur').removeClass('btn-default');
$('#thur').addClass('btn-primary');
}
if (val == 'Fri') {
$('#fri').removeClass('btn-default');
$('#fri').addClass('btn-primary');
}
if (val == 'Sat') {
$('#sat').removeClass('btn-default');
$('#sat').addClass('btn-primary');
}
if (val == 'Sun') {
$('#sun').removeClass('btn-default');
$('#sun').addClass('btn-primary');
}
})
//以上是我检查过的有效代码