大多数例子都精确地指定了弹出窗口的宽度和高度。我希望它们是包装内容-因为内容是由数据决定的,所以在构造函数中,我为宽度和高度设置了-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的宽度和高度,然后按预期使用setWidthsetHeight
编辑:
我自己试了一下,加了这行代码
    // -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);

07-28 02:09
查看更多