Android中的PopupWindow中getWidth、getHeight为0或者-2

  在Android开发中,需要用到PopupWindow这个类。在初始化完成,显示之前,都需要获得这个对象的width,height去计算popupWindow弹出的位置。

这个时候会发现取得的width和height都是-2;使用popupWindow.getContentView().getMeasuredWidth()和popupWindow.getContentView().getMeasuredHeight()取得的值都是0。如下面的代码:

activity_main.xml

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 3               android:orientation="vertical"
 4               android:layout_width="fill_parent"
 5               android:layout_height="fill_parent"
 6         >
 7
 8     <Button
 9             android:layout_width="wrap_content"
10             android:layout_height="wrap_content"
11             android:text="New Button"
12             android:id="@+id/button"
13             android:layout_gravity="center_horizontal"/>
14 </LinearLayout>

popwin_layout.xml

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 3               android:orientation="vertical"
 4               android:layout_width="match_parent"
 5               android:layout_height="match_parent">
 6     <ImageView
 7             android:layout_width="wrap_content"
 8             android:layout_height="wrap_content"
 9             android:src="@drawable/ic_launcher"/>
10 </LinearLayout>

MyActivity.class

 1 package com.example.popwinsize;
 2
 3 import android.app.Activity;
 4 import android.graphics.drawable.BitmapDrawable;
 5 import android.os.Bundle;
 6 import android.text.Layout;
 7 import android.util.Log;
 8 import android.view.LayoutInflater;
 9 import android.view.View;
10 import android.view.ViewGroup;
11 import android.widget.Button;
12 import android.widget.PopupWindow;
13
14 public class MyActivity extends Activity {
15
16     private PopupWindow mPopWin;
17
18     private Button mButton;
19
20     /**
21      * Called when the activity is first created.
22      */
23     @Override
24     public void onCreate(Bundle savedInstanceState) {
25         super.onCreate(savedInstanceState);
26         setContentView(R.layout.activity_main);
27         mButton = (Button) findViewById(R.id.button);
28         mButton.setOnClickListener(new ButtonClickListener());
29
30         initPopupWindow();
31     }
32
33     /**
34      * 初始化PopupWindow
35      */
36     private void initPopupWindow() {
37         View contentView = LayoutInflater.from(this).inflate(R.layout.popwin_layout, null);
38         mPopWin = new PopupWindow(contentView,
39                 ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
40         mPopWin.setBackgroundDrawable(new BitmapDrawable());    //设置背景,否则setOutsideTouchable无效
41         mPopWin.setOutsideTouchable(true);                      //设置点击PopupWindow以外的地方关闭PopupWindow
42         mPopWin.setFocusable(true);                             //获取焦点
43     }
44
45     class ButtonClickListener implements View.OnClickListener {
46
47         @Override
48         public void onClick(View v) {
49             //点击在按钮的中下方弹出mPopWin
50
51             int btnWidth = v.getMeasuredWidth();
52             int btnHeight = v.getMeasuredHeight();
53
54             int popWidth = mPopWin.getContentView().getMeasuredWidth();
55             int popHeight = mPopWin.getContentView().getMeasuredHeight();
56             Log.i("Button.size", "width=" + btnWidth + "; height=" + btnHeight);
57             Log.i("PopupWindow.size", "width=" + popWidth + "; height=" + popHeight);
58             //mPopWin.showAsDropDown(v);    //这个是在按钮的下方出现,x值与按钮的x值相等
59
60             int xoff = (int)((float)(btnWidth - popWidth)/2);    //PopupWindow的x偏移值
61             int yoff = 0;                                        //因为相对于按钮的下方,所以该值为0
62
63             mPopWin.showAsDropDown(v, xoff, yoff);
64         }
65     }
66 }

这个时候你会发现,出现的效果并不是您想要的效果,是在按钮是右下方出现

LogCat捕获的结果是:

   I/Button.size﹕ width=176; height=72
   I/PopupWindow.size﹕ width=0; height=0

出现这个的原因就是因为PopupWindow的尺寸拿不到,因为内容的View的width和height都是wrap_content,所以在PopupWindow里面的contentView还没被绘制出来的时候,这两个值都还是0。

如果直接调用PopupWindow的getWidth()和getHeight(),会发现拿到的都是ViewGroup.LayoutParams.WRAP_CONTENT的值 -2;

解决的方法就是在初始化contentView的时候,强制绘制contentView,并且马上初始化contentView的尺寸。这里只需要一句代码即可

看下面的MyActivity.class的第38行代码:

 1 package com.example.popwinsize;
 2
 3 import android.app.Activity;
 4 import android.graphics.drawable.BitmapDrawable;
 5 import android.os.Bundle;
 6 import android.text.Layout;
 7 import android.util.Log;
 8 import android.view.LayoutInflater;
 9 import android.view.View;
10 import android.view.ViewGroup;
11 import android.widget.Button;
12 import android.widget.PopupWindow;
13
14 public class MyActivity extends Activity {
15
16     private PopupWindow mPopWin;
17
18     private Button mButton;
19
20     /**
21      * Called when the activity is first created.
22      */
23     @Override
24     public void onCreate(Bundle savedInstanceState) {
25         super.onCreate(savedInstanceState);
26         setContentView(R.layout.activity_main);
27         mButton = (Button) findViewById(R.id.button);
28         mButton.setOnClickListener(new ButtonClickListener());
29
30         initPopupWindow();
31     }
32
33     /**
34      * 初始化PopupWindow
35      */
36     private void initPopupWindow() {
37         View contentView = LayoutInflater.from(this).inflate(R.layout.popwin_layout, null);
38         contentView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
39         mPopWin = new PopupWindow(contentView,
40                 ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
41         mPopWin.setBackgroundDrawable(new BitmapDrawable());    //设置背景,否则setOutsideTouchable无效
42         mPopWin.setOutsideTouchable(true);                        //设置点击PopupWindow以外的地方关闭PopupWindow
43         mPopWin.setFocusable(true);                                //获取焦点
44     }
45
46     class ButtonClickListener implements View.OnClickListener {
47
48         @Override
49         public void onClick(View v) {
50             //点击在按钮的中下方弹出mPopWin
51
52             int btnWidth = v.getMeasuredWidth();
53             int btnHeight = v.getMeasuredHeight();
54
55             int popWidth = mPopWin.getContentView().getMeasuredWidth();
56             int popHeight = mPopWin.getContentView().getMeasuredHeight();
57             Log.i("Button.size", "width=" + btnWidth + "; height=" + btnHeight);
58             Log.i("PopupWindow.size", "width=" + popWidth + "; height=" + popHeight);
59             //mPopWin.showAsDropDown(v);    //在按钮的下方出现,x值与按钮的x值相等
60
61             int xoff = (int)((float)(btnWidth - popWidth)/2);    //PopupWindow的x偏移值
62             int yoff = 0;                                        //因为相对于按钮的下方,所以该值为0
63
64             mPopWin.showAsDropDown(v, xoff, yoff);
65         }
66     }
67 }

这个时候LogCat打印出来的结果:

   I/Button.size﹕ width=176; height=72
   I/PopupWindow.size﹕ width=72; height=72

效果如下:

另外一个点需要注意:popwin_layout.xml的根Layout必须为LinearLayout;如果为RelativeLayout的话,会在第38行代码出现空指针错误,导致程序崩溃。希望看到此文章的人在开发中需要注意。

时间: 2024-10-10 04:24:13

Android中的PopupWindow中getWidth、getHeight为0或者-2的相关文章

android 中遇到 imageView getWidth 始终为0 时 ,设置 setImageBitmap 的方法

先说说我的遇到的问题: 1. 我在activity里写一个 fragment 2.这个fragment里有个 imageView ,用于显示图片. 我使用 asyncTask获得图片,并准备在这个imageView 中显示该图片的缩略图,我准备使用  ThumbnailUtils.extractThumbnail 方法生成缩略图. 我们先看看ThumbnailUtils.extractThumbnail(source, width, height);  这个方法的参数   source 源文件(

关于Android PopupWindow中实用Spinner控件点击APP Crash情况整理!

场景异常信息如下: android.view.WindowManager$BadTokenException: Unable to add window -- token [email protected] is not valid; is your activity running? at android.view.ViewRootImpl.setView(ViewRootImpl.java:646) at android.view.WindowManagerGlobal.addView(Wi

Android下在onCreate中获取控件的宽度和高度(通过回调)

有时候需要在onCreate方法中知道某个View组件的宽度和高度等信息, 而直接调用View组件的getWidth().getHeight().getMeasuredWidth().getMeasuredHeight().getTop().getLeft()等方法是无法获取到真实值的,只会得到0. 这是因为View组件布局要在onResume回调后完成. 下面提供实现方法: 第一种: onGlobalLayout回调会在布局完成时自动调用 img1.getViewTreeObserver().

在Activity的onCreate方法中显示PopupWindow导致异常的原因分析及解决方案

一.前言 在某些情况下,我们需要一进入Activity就显示PopupWindow,比如常见的选择界面.但由于PopupWindow是依附于Activity的,如果Activity没有创建完成,Activity还没完全显示出来就显示PopupWindow的话,会出现异常现象. 二.问题复现 我在Activity的onCreate()方法中调用如下方法: public void show( ){ if( null != mPopupWindow ){ mPopupWindow.showAtLoca

Android实践之ScrollView中滑动冲突处理

转载注明出处:http://blog.csdn.net/xiaohanluo/article/details/52130923 1. 前言 在Android开发中,假设是一些简单的布局.都非常easy搞定.可是一旦涉及到复杂的页面,特别是为了兼容小屏手机而使用了ScrollView以后,就会出现非常多点击事件的冲突.最经典的就是ScrollView中嵌套了ListView. 我想大部分刚開始接触Android的同学们都踩到过这个坑,这一篇文章就从近期做的一个项目讲起.然后在过程中提供一些解决冲突

Android在滚动列表中实现视频的播放 ListView RecyclerView

英文原文:Implementing video playback in a scrolled list (ListView & RecyclerView) 本文将讲解如何在列表中实现视频播放.类似于诸如 Facebook, Instagram 或者 Magisto这些热门应用的效果: Facebook: Magisto: Instagram: 这片文章基于开源项目: VideoPlayerManager. 所有的代码和示例都在那里.本文将跳过许多东西.因此如果你要真正理解它是如何工作的,最好下载

Android APP 调试过程中遇到的问题。

调试过过程中APP安装完启动后有的时候会异常退出,报这个错误.有的时候可以直接启动.查找不到原因.网上说把commit方法替换成commitAllowingStateLoss() 也无效. Android APP 调试过程中遇到的问题. >> android 这个答案描述的挺清楚的:http://www.goodpm.net/postreply/android/1010000007192169/AndroidAPP调试过程中遇到的问题.html

android插件化-apkplug中OSGI服务基本原理-08

我们提供 apkplug 下OSGI使用demo 源码托管地址为 http://git.oschina.net/plug/OSGIService 一 OSGI与android Service 异同点 OSGI服务与android Service概念差不多也是Service ,Client 关系. android Service接口  --service.AIDL OSGI接口                --java interface 所以android 进程间通信Service只能传递序列

(转载)Android xml资源文件中@、@android:type、@*、?、@+引用写法含义以及区别

原帖地址:http://blog.csdn.net/zfrong/article/details/7332545 Android xml资源文件中@.@android:type.@*.?.@+引用写法含义以及区别 一[email protected]代表引用资源 1.引用自定义资源.格式:@[package:]type/name android:text="@string/hello" 2.引用系统资源.格式:@android:type/name android:textColor=&