【安卓笔记】popupWindow使用浅析
2014-04-20 22:43
253 查看
概述:
popupWindow可以用来实现弹出框效果,弹出框的布局可以任意指定,这个弹出框是悬浮在当前activity之上的。
使用方式:
1.为popupWindow填充一个布局;
2.new出popupWindow实例;
3.调用showAsDropDown或者showAtLocation方法显示弹出框.
示例:
1.popupWindow的布局:
2.activity:
activity的布局很简单,只有一个button,用于显示popupWindow,就不贴了。
![](https://img-blog.csdn.net/20140420223843187?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvY2hkamo=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
当我们点击按钮后,将会弹出上面定义的弹出框,另外如果我们希望给其增加动画,我们可以调用
setAnimationStyle方法。
添加自定义动画
比如我们希望给这个弹出框增加淡入淡出的效果。
首先我们先定义好动画:
in.xml
现在弹出框就有了淡入淡出的效果了.
注意:
当我们触摸弹出框外侧或者点击back键时,弹出框会自动消失,这符合我们的使用常识。但是当我们去掉下面这一句后,将会发现弹出框不能被dismiss掉。
这是为什么呢?我们跟踪源码看看。
从showAtLocation方法开始:
可以看到如果mBackground 为空则将mContentView赋给popupView,否则在mContentView外侧包装一个popupViewContainer。mContentView即弹出框上显示的view,那么这个popupViewContainer是啥?
经查找,发现它是PopupWindow的一个内部类:
观察这个类,我们发现这个类重写了onTouchEvent,dispatchTouchEvent,dispatchKeyEvent等方法。
比如说这个onTouchEvent就定义了当我们点击popupWindow外就会自动dismiss掉弹出框:
popupWindow可以用来实现弹出框效果,弹出框的布局可以任意指定,这个弹出框是悬浮在当前activity之上的。
使用方式:
1.为popupWindow填充一个布局;
2.new出popupWindow实例;
3.调用showAsDropDown或者showAtLocation方法显示弹出框.
示例:
1.popupWindow的布局:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_height="match_parent" android:layout_width="match_parent" android:background="#00ff00" android:orientation="vertical" > <TextView android:id="@+od/tv" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center_horizontal" android:textSize="25sp" android:text="立 即 更 新" /> <ImageView android:layout_width="match_parent" android:layout_height="1dp" android:background="#000" /> <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center_horizontal" > <Button android:id="@+id/but_neg" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="取消" /> <Button android:id="@+id/but_pos" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="确定" android:layout_marginLeft="20dp" android:layout_toRightOf="@id/but_neg" /> </RelativeLayout> </LinearLayout>
2.activity:
activity的布局很简单,只有一个button,用于显示popupWindow,就不贴了。
package com.example.popupwindowdemo; import android.app.Activity; import android.graphics.drawable.BitmapDrawable; import android.os.Bundle; import android.view.Gravity; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.LinearLayout.LayoutParams; import android.widget.PopupWindow; import android.widget.Toast; public class MainActivity extends Activity implements OnClickListener { private PopupWindow pw = null; private Button but_pos = null; private Button but_neg = null; private Button but_show = null; private int screenWidth = 0; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); screenWidth = getWindowManager().getDefaultDisplay().getWidth(); but_show = (Button) findViewById(R.id.but_show); but_show.setOnClickListener(this); } public void initPopupWindow() { View view = getLayoutInflater().inflate(R.layout.layout_popup_window,null); but_pos = (Button) view.findViewById(R.id.but_pos); but_neg = (Button) view.findViewById(R.id.but_neg); but_neg.setOnClickListener(this); but_pos.setOnClickListener(this); pw = new PopupWindow(view, LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT,true); pw.setWidth(screenWidth*3/4); pw.setBackgroundDrawable(new BitmapDrawable()); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.but_neg: Toast.makeText(this,"取消", 0).show(); pw.dismiss(); break; case R.id.but_pos: Toast.makeText(this,"开始下载", 0).show(); pw.dismiss(); break; case R.id.but_show: initPopupWindow(); //显示在指定位置 pw.showAtLocation(findViewById(R.id.root),Gravity.CENTER,0,0); //默认显示在指定的view左下,可以指定偏移量,这里让其显示在中间 // pw.showAsDropDown(but_show,(screenWidth-pw.getWidth())/2,0); break; } } }显示效果:
当我们点击按钮后,将会弹出上面定义的弹出框,另外如果我们希望给其增加动画,我们可以调用
setAnimationStyle方法。
添加自定义动画
比如我们希望给这个弹出框增加淡入淡出的效果。
首先我们先定义好动画:
in.xml
<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android"> <alpha android:fromAlpha="0" android:toAlpha="1" android:duration="2000" /> </set>out.xml
<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android"> <alpha android:fromAlpha="1" android:toAlpha="0" android:duration="1000" /> </set>然后在styles.xml文件中定义:
<style name="popup_window_style"> <item name="android:windowEnterAnimation">@anim/in</item> <item name="android:windowExitAnimation">@anim/out</item> </style>最后在initPopupWindow方法中增加这样一行代码:
pw.setAnimationStyle(R.style.popup_window_style);
现在弹出框就有了淡入淡出的效果了.
注意:
当我们触摸弹出框外侧或者点击back键时,弹出框会自动消失,这符合我们的使用常识。但是当我们去掉下面这一句后,将会发现弹出框不能被dismiss掉。
pw.setBackgroundDrawable(new BitmapDrawable());
这是为什么呢?我们跟踪源码看看。
从showAtLocation方法开始:
public void showAtLocation(IBinder token, int gravity, int x, int y) { if (isShowing() || mContentView == null) { return; } unregisterForScrollChanged(); mIsShowing = true; mIsDropdown = false; WindowManager.LayoutParams p = createPopupLayout(token); p.windowAnimations = computeAnimationResource(); preparePopup(p); if (gravity == Gravity.NO_GRAVITY) { gravity = Gravity.TOP | Gravity.START; } p.gravity = gravity; p.x = x; p.y = y; if (mHeightMode < 0) p.height = mLastHeight = mHeightMode; if (mWidthMode < 0) p.width = mLastWidth = mWidthMode; invokePopup(p); }可以看到,内部先会调用PreparePopup方法,跟进去:
private void preparePopup(WindowManager.LayoutParams p) { if (mContentView == null || mContext == null || mWindowManager == null) { throw new IllegalStateException("You must specify a valid content view by " + "calling setContentView() before attempting to show the popup."); } if (mBackground != null) { final ViewGroup.LayoutParams layoutParams = mContentView.getLayoutParams(); int height = ViewGroup.LayoutParams.MATCH_PARENT; if (layoutParams != null && layoutParams.height == ViewGroup.LayoutParams.WRAP_CONTENT) { height = ViewGroup.LayoutParams.WRAP_CONTENT; } // when a background is available, we embed the content view // within another view that owns the background drawable PopupViewContainer popupViewContainer = new PopupViewContainer(mContext); PopupViewContainer.LayoutParams listParams = new PopupViewContainer.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, height ); popupViewContainer.setBackgroundDrawable(mBackground); popupViewContainer.addView(mContentView, listParams); mPopupView = popupViewContainer; } else { mPopupView = mContentView; } mPopupViewInitialLayoutDirectionInherited = (mPopupView.getRawLayoutDirection() == View.LAYOUT_DIRECTION_INHERIT); mPopupWidth = p.width; mPopupHeight = p.height; }
可以看到如果mBackground 为空则将mContentView赋给popupView,否则在mContentView外侧包装一个popupViewContainer。mContentView即弹出框上显示的view,那么这个popupViewContainer是啥?
经查找,发现它是PopupWindow的一个内部类:
private class PopupViewContainer extends FrameLayout
观察这个类,我们发现这个类重写了onTouchEvent,dispatchTouchEvent,dispatchKeyEvent等方法。
比如说这个onTouchEvent就定义了当我们点击popupWindow外就会自动dismiss掉弹出框:
public boolean onTouchEvent(MotionEvent event) { final int x = (int) event.getX(); final int y = (int) event.getY(); if ((event.getAction() == MotionEvent.ACTION_DOWN) && ((x < 0) || (x >= getWidth()) || (y < 0) || (y >= getHeight()))) { dismiss(); return true; } else if (event.getAction() == MotionEvent.ACTION_OUTSIDE) { dismiss(); return true; } else { return super.onTouchEvent(event); } }而当我们不设置背景时,默认并不会对onTouch等事件进行处理。
相关文章推荐
- 【安卓笔记】Handler+Thread使用浅析
- 安卓学习笔记:使用PopupWindow创建简单菜单
- 安卓笔记:怎么使用横屏布局界面
- bug笔记 - Java --- 网络编程使用BufferedInputStream从缓冲区中读不到数据(浅析BufferedInputStram和BufferedOutputStream的工作机制)
- 安卓开发:模仿微信,QQ评论输入框,使用PopupWindow完美实现(新版)
- MultiChannelPackageTool(安卓多渠道打包工具) 工具使用笔记
- 安卓 多线程、以及使用Handler发送、处理Message(新手笔记-10)
- https 浅析及在安卓中的使用
- 【安卓小笔记】v7包下SearchView的基本使用
- 安卓学习笔记之通知栏的使用
- 笔记17 Animator 安卓属性动画 仿直线菜单 代码量极少抛弃使用animation
- 【安卓小笔记】BottomNavigationView和ViewPager的使用
- 安卓学习笔记---使用AndroidStudio出现的问题错误(错误: -source 1.6 中不支持 diamond 运算符 (请使用 -source 7 或更高版本以启用 diamond 运算)
- 安卓学习笔记之使用widget桌面小控件
- 安卓谷歌电子市场学习笔记系列——Context的使用
- 【安卓笔记】CardView+RecyclerView使用示例
- 安卓学习笔记---使用浏览器打开app指定协议(Url Scheme)
- 【安卓笔记】NineOldAndroids动画兼容库的使用
- 安卓学习笔记:让自己显示在地图上(使用百度地图API)
- 安卓笔记/使用Intent打开activity添加flag防止多次打开