PopupWindow画面出来的时候规模是不确定的 [英] PopupWindow out of screen when size is unspecified

查看:233
本文介绍了PopupWindow画面出来的时候规模是不确定的的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

大多数的例子在那里明确指定弹出窗口的宽度和高度。我想他们是WRAP_CONTENT - 由于内容dinamically决定的,因此在构造函数中我设定-2的宽度和高度,并通过的 showAsDropDown(查看锚)

显示它

这样做,在弹出总是画下锚认为,这意味着它可以绘制屏幕外。下面的代码片段演示了此问题。试着点击最后一个TextView的,你不会看到任何PopupWindow,因为它显示的窗口范围之外。为什么不工作?我此话明确指定尺寸(例如200,100)不触发的问题。试一试

 包com.zybnet.example.popupdemo;

进口android.app.Activity;
进口android.graphics.Color;
进口android.os.Bundle;
进口android.view.View;
进口android.view.View.OnClickListener;
进口android.widget.LinearLayout;
进口android.widget.PopupWindow;
进口android.widget.TextView;

公共类PopupDemoActivity扩展活动实现OnClickListener {
    私人PopupWindow弹出;

    @覆盖
    公共无效的onCreate(包savedInstanceState){
        super.onCreate(savedInstanceState);
        // -2手段WRAP_CONTENT这会触发问题
        弹出=新PopupWindow(getPopupContent(),-2,-2);
        //当指定尺寸一切顺利
        //弹出=新PopupWindow(getPopupContent(),200,100);

        的LinearLayout布局=新的LinearLayout(本);
        layout.setOrientation(LinearLayout.VERTICAL);

        // FILL_PARENT和相同的布局重量为所有儿童
        LinearLayout.LayoutParams PARAMS =新LinearLayout.LayoutParams(-1,-1,1);
        的for(int i = 0;我小于10;我++){
            TextView的电视=新的TextView(本);
            tv.setText(单击显示弹出);
            tv.setOnClickListener(本);
            layout.addView(电视,则params);
        }
        的setContentView(布局);
    }

    @覆盖
    公共无效的onClick(视图查看){
        popup.dismiss();
        popup.showAsDropDown(视图);
    }

    私人查看getPopupContent(){
        TextView的popupContent =新的TextView(本);
        popupContent.setText(这里有些文字);
        popupContent.setTextColor(Color.parseColor(#5000ae));
        popupContent.setBackgroundColor(Color.parseColor(#FF00FF));
        popupContent.setPadding(10,20,20,10);
        返回popupContent;
    }
}
 

<类=h2_linDIV>解决方案

我开始怀疑,在一个 PopupWindow 这-2的背景下,实际上-2手段 WRAP_CONTENT ,而我认为它只是跨preting它的宽度= -2高度= -2

这是从Android源代码

 公共PopupWindow(查看内容查看,诠释的宽度,高度INT,布尔可聚焦){
    如果(内容查看!= NULL){
        mContext = contentView.getContext();
        mWindowManager =(窗口管理器)mContext.getSystemService(Context.WINDOW_SERVICE);
    }
    的setContentView(内容查看);
    setWidth(宽);
    自动调用setHeight(高度);
    setFocusable(可聚焦);
}
 

其中, setWidth(INT宽度)只是一个简单的 mWidth =宽度; 我觉得你在找什么反而是<一个href="http://developer.android.com/reference/android/widget/PopupWindow.html#setWindowLayoutMode%28int,%20int%29">setWindowLayoutMode (INT widthSpec,诠释heightSpec)方法。这就是你应该通过在 WRAP_CONTENT

如果一切都失败了,可测量的TextView 的宽度和高度,然后用 setWidth 自动调用setHeight 预期。

修改

刚刚尝试过了自己和加入这一行的code,使其工作

  // -2表示WRAP_CONTENT这会触发问题
    弹出=新PopupWindow(getPopupContent(),200,100);
    popup.setWindowLayoutMode(ViewGroup.LayoutParams.WRAP_CONTENT,ViewGroup.LayoutParams.WRAP_CONTENT);
    //当指定尺寸一切顺利
    //弹出=新PopupWindow(getPopupContent(),200,100);

    的LinearLayout布局=新的LinearLayout(本);
    layout.setOrientation(LinearLayout.VERTICAL);
 

我留在那里的原始意见,所以你可以看到自己在那里一切都应该去。

编辑2: 好了,所以我把你的code你贴和逐字试了一下我的设备上,而你是正确的,它没有工作,因为当机器人被确定为布局,把它放在其中的观点,它依靠的宽度和您所提供的高度。这也就意味着,由于您使用的是0和0作为你的宽度和高度,Android将到来,并说,哦,看,盒子只是一个0:0个框,以便我可以显示为以下内容的弹出窗口。这不是什么需要尽管!关键是,你知道盒子将是大于内容,让我们开始把一些不同的号码,看到了来自它的结果。

 弹出=新PopupWindow(getPopupContent(),1,1);
 

现在,当我去并单击底部中,注意它跳跃以上。 (见截图),这是因为Android的知道,宽度和高度为1(正如我在构造函数中设置),而下方的列表项中可用的屏幕空间为0好吧,如果没有足够的空间来显示它在那里,那么它首先得呢!

别急!如果像我现在的例子串上更多的内容每次都添加了什么?那么,这就是事情变得有趣。你看,我的弹出,即使它,因为它是6号线长现在应该显示了,宁可在底部显示下面的截图!呵呵废话了吧!这是因为它是测量对 1 我用的构造。那么什么是一些解决这个呢?

解决方法一:我的preferred办法是采取一种猜测什么的平均最大高度的TextView 会再请换一个一般大号。

 弹出=新PopupWindow(getPopupContent(),300,300); //只是猜测它不会大于
 

解决方案二:这是比较合适的,但你牺牲一点速度来做到这一点。使用油漆类来衡量什么是文本内容的大小将是和传球是到了 setWidth()自动调用setHeight(),然后显示弹出。我说干就干,建立了一个几乎的完整的解决方案,但我没有在填充和东西(见注释)测量

 私人诠释了maxWidth;
私人诠释了maxHeight;
民营涂料P =新的油漆();
私人矩形边界=新的矩形();
私人查看getPopupContent(){
    了maxWidth = 0;
    了maxHeight = 0;
    TextView的popupContent =新的TextView(本);
    popupContent.setText(popupText + =\ N+ DEMO);
    popupContent.setTextColor(Color.parseColor(#5000ae));
    popupContent.setBackgroundColor(Color.parseColor(#FF00FF));
    popupContent.setPadding(10,20,20,10);
    //该措施只能工作一行行,所以我一行分裂它
    的String []临时= popupText.split(\ N);
    对于(字符串S:TEMP){
        //测量串的每一行,并获得其宽度和高度
        p.getTextBounds(S,0,s.length(),边界);

        //保持运行总时间最长的宽度
        =了maxWidth(bounds.width()&GT;了maxWidth)? bounds.width()了maxWidth;
        //加起来每个高度
        +了maxHeight = bounds.height();
    }

    //也借此帐户填充太...如果你真的希望它是完全健壮
    //可能又增加20或30的了maxHeight应该不错
    返回popupContent;
}
 

然后在的onClick()我加这两条线

  popup.setHeight(了maxHeight);
    popup.setWidth(了maxWidth);
 

Most examples out there specify exactly the width and height of the popup window. I want them to be WRAP_CONTENT - since the content is dinamically determined, so in the constructor I set -2 for both width and height and show it via showAsDropDown(View anchor)

Doing this, the popup is always drawn below the anchor view, which means it can be drawn offscreen. The following snippet demonstrates the problem. Try clicking on the last TextView and you won't see any PopupWindow, since it's shown outside of the windows bounds. Why doesn't it work? I remark that specifying dimension explicitly (for example 200, 100) doesn't trigger the problem. Try it yourself

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;
    }
}

解决方案

I'm starting to doubt that in the context of a PopupWindow that -2, -2 actually means WRAP_CONTENT rather I think that its just interpreting it as width = -2 height = -2

This is from the 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);
}

where setWidth(int width) is just a simple mWidth = width; I think what you are looking for instead is the setWindowLayoutMode (int widthSpec, int heightSpec) method. That is where you should pass in the WRAP_CONTENT

If all else fails, measure the width and height of the TextView and then use setWidth and setHeight as expected.

Edit:

Just tried it out for myself and added this line of code to make it work

    // -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);

I left the original comments in there so you can see for yourself where everything should go.

Edit 2: Okay, so I took your code you posted and verbatim tried it on my device, and you were right, it didn't work because when Android is determining which views to layout to put it in, it relies on the width and height you provided. What that means is since you are using 0 and 0 as your width and height, Android will come along and say, "Oh look, the box is only a 0 by 0 box so I can display it as a popup below the content." This isn't what is desired though! The thing is, you know that the box is going to be bigger than that, so lets start putting in some different numbers and seeing the results that come from it.

popup = new PopupWindow(getPopupContent(), 1, 1);

Now when I go and click the bottom box, notice that it jumps above. (See screenshot) That's because Android KNOWS that the width and height are 1 (as I set in the constructor) and that the available screen space below the list item is 0. Well, if there's not enough room to display it there, then it must above then!

But wait! What if like in my current example the string adds on more content each time? Well, this is where things get interesting. You see, in my next screenshot that the popup, even though it should be displayed up since it is 6 lines long now, is rather displayed at the bottom! Oh crap, right! That's because it is measuring against the 1 1 I used in the constructor. Well what are some solutions to this then?

Solution One: My preferred way would be to take a guess at what the average max height of the TextView would be and then simply toss in one generically big number.

popup = new PopupWindow(getPopupContent(), 300, 300); //just guessing it won't get bigger than that

Solution Two: This is more proper, but you are sacrificing a little speed to do it. Using the Paint class to measure what the text content size is going to be and passing that into the the setWidth() and setHeight() before you display the popup. I went ahead and built an almost complete solution, but I didn't measure in padding and stuff (see the comment)

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;
}

And then in the onClick() I added these two lines

    popup.setHeight(maxHeight);
    popup.setWidth(maxWidth);

这篇关于PopupWindow画面出来的时候规模是不确定的的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆