在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=72I/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=72I/PopupWindow.size﹕ width=72; height=72
效果如下:
另外一个点需要注意:popwin_layout.xml的根Layout必须为LinearLayout;如果为RelativeLayout的话,会在第38行代码出现空指针错误,导致程序崩溃。希望看到此文章的人在开发中需要注意。
案例二:
布局文件:
xml version="1.0" encoding="utf-8"?>xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/grid" android:layout_width="wrap_content" android:layout_height="wrap_content" android:rowCount="4" android:background="@drawable/share_bg_blue" android:paddingTop="10dp" android:paddingLeft="8dp" android:paddingRight="8dp" android:paddingBottom="10dp" android:orientation="vertical"> android:id="@+id/faceBook_img" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/icon_facebook" /> android:id="@+id/twitter_img" android:layout_marginTop="10dp" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/icon_twitter" /> android:id="@+id/instagram_img" android:layout_marginTop="10dp" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/icon_instagram" /> android:id="@+id/tubmlr_img" android:layout_marginTop="10dp" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/icon_tumblr" />
逻辑代码:
PopupWindow popupWindow = new PopupWindow(); View addCourseView = LayoutInflater.from(context).inflate(R.layout.share_my_course, null); addCourseView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED); popupWindow.setContentView(addCourseView); popupWindow.setWidth(ViewGroup.LayoutParams.WRAP_CONTENT); popupWindow.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT); popupWindow.setBackgroundDrawable(new ColorDrawable()); popupWindow.setFocusable(true); popupWindow.setOutsideTouchable(true); //获取屏幕的宽高 DisplayMetrics metric = new DisplayMetrics(); getActivity().getWindowManager().getDefaultDisplay().getMetrics(metric); int width = metric.widthPixels; // 屏幕宽度(像素) int height = metric.heightPixels; // 屏幕高度(像素) float density = metric.density; // 屏幕密度(0.75 / 1.0 / 1.5) int densityDpi = metric.densityDpi; // 屏幕密度DPI(120 / 160 / 240) // int i = width - drawerright.getWidth(); int i = drawer.getWidth() - drawerright.getWidth() - popupWindow.getContentView().getMeasuredWidth(); Log.e("=========", "=====drawer.getWidth()==" + drawer.getWidth()); Log.e("=========", "=====drawerright.getWidth()==" + drawerright.getWidth()); Log.e("=========", "=====addCourseView.getWidth()==" + addCourseView.getWidth()); Log.e("=========", "=====popupWindow.getWidth()==" + popupWindow.getContentView().getMeasuredWidth()); Log.e("=========", "=====i==" + i); popupWindow.showAtLocation(listview, Gravity.LEFT | Gravity.CENTER_VERTICAL, i, 0); addCourseView.findViewById(R.id.faceBook_img).setOnClickListener(new MyListener()); addCourseView.findViewById(R.id.twitter_img).setOnClickListener(new MyListener()); addCourseView.findViewById(R.id.instagram_img).setOnClickListener(new MyListener()); addCourseView.findViewById(R.id.tubmlr_img).setOnClickListener(new MyListener()); } class MyListener implements View.OnClickListener { @Override public void onClick(View view) { switch (view.getId()) { case R.id.faceBook_img: Toast.makeText(context, "faceBook", Toast.LENGTH_SHORT).show(); showShare(true, Facebook.NAME); break; case R.id.twitter_img: Toast.makeText(context, "twitter", Toast.LENGTH_SHORT).show(); showShare(true, Twitter.NAME); break; case R.id.instagram_img: Toast.makeText(context, "instagram", Toast.LENGTH_SHORT).show(); showShare(true, Instagram.NAME); break; case R.id.tubmlr_img: Toast.makeText(context, "tubmlr", Toast.LENGTH_SHORT).show(); showShare(true, Tumblr.NAME); break; } } } private void showShare(boolean silent, String platform) { OnekeyShare oks = new OnekeyShare(); oks.setTitle("Super Classmate"); oks.setText("Super Classmate" + " http://www.mob.com"); oks.setDialogMode(); oks.disableSSOWhenAuthorize(); if (platform != null) { oks.setPlatform(platform); } oks.setShareContentCustomizeCallback(new ShareContentCustomizeCallback() { @Override public void onShare(Platform platform, Platform.ShareParams paramsToShare) { } }); oks.show(context); }
运行结果: