Android PopupWindow with ListView的一些问题

最近开发使用PopupWindow弹框显示ListView,开始使用的固定宽度和高度显示,由于数据量不固定,数据少时会有空白显示,于是改成使用wrap_content,发现了一些之前没注意到的问题,记录下来:

1、必须设置PopupWindow的Height、Width
不设置的话默认都为0,什么都不会显示。
在Android中,控件的大小,都是根据父控件大小确定的。给PopupWindow设置的contentView一般都是inflate得到的,且root为null,没有父布局所以无法计算大小,因此必须设置width和height。

    LayoutInflater inflater = LayoutInflater.from(this);
    View view = inflater.inflate(R.layout.popwindow, null);
    PopupWindow popupWindow = new PopupWindow(view, 
                LayoutParams.WRAP_CONTENT,
                LayoutParams.WRAP_CONTENT);

popwindow.xml:


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    >
    <ListView
        android:id="@+id/listview"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    ListView>
LinearLayout>

由于LinearLayout 没有父布局,因此设置margin是没有用的。

2、PopupWindow宽度设置为WRAP_CONTENT,而其中的ListView宽度为MATCH_PARENT,因此ListView宽度也是WRAP_CONTENT,但是是不起作用的,可以看
http://stackoverflow.com/questions/11295080/android-wrap-content-is-not-working-with-listview
(As Romain Guy (Google Engineer works on UI toolkit) Said in his post

By setting the width to wrap_contentyou are telling ListView to be as wide as the widest of its children. ListView must therefore measure its items and to get the items it has to call getView() on the Adapter. This may happen several times depending on the number of layout passes, the behavior of the parent layout, etc.

So if you set the layout width or layout height of your ListView to wrap_content the ListView will try to measure every single view that is attached to it - which is definitely not what you want.

Keep in mind: avoid setting wrap_content for ListViews or GridViews at all times, for more details see this Google I/O video talking about the world of listview)

3、给PopupWindow添加了mBackground后setOutsideTouchable(true)才会生效,具有外部点击window消失的功能,手机上的返回键将可以使window消失
看源码:

private void preparePopup(WindowManager.LayoutParams p) {
  。。。。。。
 // When a background is available, we embed the content view within
// another view that owns the background drawable.
        if (mBackground != null) {
            mBackgroundView = createBackgroundView(mContentView);
            mBackgroundView.setBackground(mBackground);
        } else {
            mBackgroundView = mContentView;
        }
 。。。。。。
}
private PopupBackgroundView createBackgroundView(View contentView) {
        final ViewGroup.LayoutParams layoutParams = mContentView.getLayoutParams();
        final int height;
        if (layoutParams != null && layoutParams.height == ViewGroup.LayoutParams.WRAP_CONTENT) {
            height = ViewGroup.LayoutParams.WRAP_CONTENT;
        } else {
            height = ViewGroup.LayoutParams.MATCH_PARENT;
        }

        final PopupBackgroundView backgroundView = new PopupBackgroundView(mContext);
        final PopupBackgroundView.LayoutParams listParams = new PopupBackgroundView.LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT, height);
        backgroundView.addView(contentView, listParams);

        return backgroundView;
    }

如果mBackground不为空,会在contentView外再包一层布局,这层布局派生自FrameLayout,同时处理了Touch事件和返回按钮事件。

4、popupwindow布局文件的第一层Layout设置margin不起作用,可以设置padding,或者在第二层布局中设置margin,但是这部分间距仍是popupwindow内的一部分,点击这部分并不能使window消失
Android PopupWindow with ListView的一些问题_第1张图片
如图list周围的一圈空白仍是popupwindow内的布局
解决方法:view.setOnTouchListener

final PopupWindow popupWindow = new PopupWindow(view, 
                LayoutParams.MATCH_PARENT,
                LayoutParams.WRAP_CONTENT);
view.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                popupWindow.dismiss();
                return false;
            }
        });

你可能感兴趣的:(Anndroid学习笔记,android,listview,popwindow)