PopupWindow
PopupWindow从名字上面可以很容易看出,PopupWindow是用来弹出一个窗口的,类似于AlertDialog,不同的是,PopupWindow更灵活,在Android应用中,很多地方都可以见到它的身影。下面我们来介绍下这个PopupWindow的基本用法,以及做一个类似于QQ底部弹出菜单的效果。
构造方法
- public PopupWindow(View contentView, int width, int height, boolean focusable)
contentView为要显示的view,width和height为宽和高,值为像素值,也可以是MATCHT_PARENT和WRAP_CONTENT。focusable为是否能够获取焦点。
- public PopupWindow (Context context)
- public PopupWindow(View contentView, int width, int height)
- public PopupWindow(View contentView)
可以看到,其中第一种构造函数最省事,设置了要显示的View,宽度 ,高度以及是否能获得焦点。也可以调用其他构造函数,然后通过调用响应的方法设置这些属性。
设置PopupWindow的视图内容
可以通过public void setContentView(View contentView)来改变popup的显示内容,也可以用来初始化PopupWindow的View。
比如使用构造函数public PopupWindow (Context context)获得的Popupwindow就只能用setContentView来设置内容。
PopupWindow popupWindow = new PopupWindow(context); popupWindow.setContentView(contentview);
设置PopUpWindow的焦点
我们可以通过setFocusable()来设置PopUpWindow能否获得焦点,也就是上面提到的构造方法中的第四个参数
如果setFocusable(true);则PopppWindow本身可以看作一个类似于模态对话框的东西(但有区别),PopupWindow弹出后,所有的触屏和物理按键都有PopupWindows处理。其他任何事件的响应都必须发生在PopupWindow消失之后, (home 等系统层面的事件除外)。比如这样一个PopupWindow出现的时候,按back键首先是让PopupWindow消失,第二次按才是退出activity,准确的说是想退出activity你得首先让PopupWindow消失 。如果设置为false,那么按下back键则由Activity处理
如果PopupWindow中有Editor的话,focusable要为true。一般情况下setFocusable(true);
点击空白处PopupWindow消失
关于PopupWindow最搞笑的地方是setOutsideTouchable方法,原本以为如果你setOutsideTouchable(true)则点击PopupWindow之外的地方PopupWindow会消失,其实这玩意儿一点用都没有。要让点击PopupWindow之外的地方PopupWindow消失你需要调用
setBackgroundDrawable(new BitmapDrawable());
设置背景,为了不影响样式,这个背景是空的。还可以这样写,觉得这样要保险些:
setBackgroundDrawable(new ColorDrawable(0x00000000));背景不为空但是完全透明。如此设置才能让PopupWindow在点击back的时候消失。
获取PopupWindow的宽高
在PopupWindow中,有两个函数
getHeight();
getWidth();
上面两个函数并不能很正确的获取PopupWindow的宽高,如果直接调用这两个函数而不特别处理,那么返回值往往是0或者-2。
正确获取PopupWindow的宽高。
//加载PopupWindow的布局 View view = View.inflate(this, R.layout.popwindow, null); //测量布局的大小 view.measure(0, 0); //将布局大小设置为PopupWindow的宽高 PopupWindow popWindow = new PopupWindow(view, view.getMeasuredWidth(), view.getMeasuredHeight(), true); popWindow.getMeasuredHeight(); popWindow.getMeasuredWidth();
显示PopupWindow
- showAsDropDown(View anchor):相对某个控件的位置(正左下方),无偏移
- showAsDropDown(View anchor, int xoff, int yoff):相对某个控件的位置,有偏移
- showAtLocation(View parent, int gravity, int x, int y):相对于父控件的位置(例如正中央Gravity.CENTER),可以设置偏移或无偏移
我在测试中发现showAtLocation的parent参数很具有迷惑性,传递进来的view并不是parent,而是获得这个view所在的Activity,然后将这个Activity作为parent,showAtLocation是相对于Activity来说的。
仿QQ底部弹出菜单
老规矩,先上效果图,看是否是你需要的。
首先我们先设置弹出菜单的布局文件,有两个LinearLayout,最外面的LinearLayout套着一个LinearLayout和最下面的取消按钮,里层的LinearLayout套着3个按钮.
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:padding="15dp"> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:background="@drawable/button_back" android:orientation="vertical" android:layout_marginBottom="15dp"> <Button android:id="@+id/updata" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@null" android:gravity="center" android:text="版本更新" android:textColor="#5084FE" /> <View android:layout_width="match_parent" android:layout_height="1dp" android:background="#cccccc" /> <Button android:id="@+id/feedback" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@null" android:gravity="center" android:text="反馈" android:textColor="#5084FE" /> <View android:layout_width="match_parent" android:layout_height="1dp" android:background="#cccccc" /> <Button android:id="@+id/back" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@null" android:gravity="center" android:text="退出" android:textColor="#5084FE" /> </LinearLayout> <Button android:id="@+id/cancel" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" android:text="取消" android:background="@drawable/button_back" android:textColor="#5084FE" /> </LinearLayout>
在上面,使用了android:background="@drawable/button_back",button_back.xml是使用shape.xml定义的背景。分别设置给里层的LinearLayout和取消按钮。
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" > <corners android:radius="8dp" /> <solid android:color="#ffffff" /> </shape>
使用已经定义好的背景,去显示PopupWindow
public class MainActivity extends Activity { private Button mShowBtmMenu; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.fragment_main); mShowBtmMenu = (Button) findViewById(R.id.showbottommenu); // 点击按钮,显示底部按钮 mShowBtmMenu.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { showBottomMenu(v); } }); } // 显示底部按钮 private void showBottomMenu(View v) { // 加载PopupWindow的布局 View view = View.inflate(this, R.layout.popwindow, null); PopupWindow popWindow = new PopupWindow(view,LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT, true); popWindow.setBackgroundDrawable(new ColorDrawable(0)); //设置动画 popWindow.setAnimationStyle(R.style.popwin_anim_style); //设置popupwindow的位置 popWindow.showAtLocation(v, Gravity.BOTTOM, 0, 0); //设置背景半透明 backgroundAlpha(0.6f); //点击空白位置,popupwindow消失的事件监听,这时候让背景恢复正常 popWindow.setOnDismissListener(new OnDismissListener() { @Override public void onDismiss() { backgroundAlpha(1.0f); } }); } /** * 设置屏幕的背景透明度 * @param bgAlpha */ public void backgroundAlpha(float bgAlpha) { WindowManager.LayoutParams lp = getWindow().getAttributes(); lp.alpha = bgAlpha; // 0.0-1.0 getWindow().setAttributes(lp); } }
为PopupWindow设置进入退出动画
- setAnimationStyle(int animationStyle)可以用来为PopupWindow设置进入退出的动画。
首先定义两个animation,分别表示进入退出动画
<?xml version="1.0" encoding="utf-8"?> <translate xmlns:android="http://schemas.android.com/apk/res/android" android:duration="100" android:fromYDelta="100%" android:toYDelta="0%" > </translate>
<?xml version="1.0" encoding="utf-8"?> <translate xmlns:android="http://schemas.android.com/apk/res/android" android:duration="100" android:fromYDelta="0%" android:toYDelta="100%" > </translate>
然后在/values/styles文件中定义动画style
<style name="popwin_anim_style"> <item name="android:windowEnterAnimation">@anim/popup_anim_in</item> <item name="android:windowExitAnimation">@anim/popup_anim_out</item> </style>
这样就可以在代码中通过setAnimationStyle(R.style.popwin_anim_style);使用了。
Demo下载地址 : 360云盘 访问密码 e45e