资料来源
https://blog.csdn.net/a379992210/article/details/48423923
https://blog.csdn.net/shanxuyang/article/details/47068487
popMenu
popMenu实现在某个view的上方或者下方显示一个折叠的系统风格的折叠菜单,向上还是向下弹出由系统控制(下方有空间从下方弹出,下方没有空间从上方弹出)
//初始化按钮
mPopMenuBtn = (Button) findViewById(R.id.button3);//为按钮注册点击事件
public void popMenuBtnOnClick(View view) {
//新建一个popMenu实例mPopMenu = new PopupMenu(this, mPopMenuBtn);
//为这个实例的menu加载布局资源mPopMenu.getMenuInflater().inflate(R.menu.menu_popup_window, mPopMenu.getMenu());mPopMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {@Overridepublic boolean onMenuItemClick(MenuItem item) {//do somethingreturn true;}});mPopMenu.show();}
popWindow
模板代码
private PopupWindow popupWindow;@SuppressLint("InflateParams") View view=LayoutInflater.from(this).inflate(R.layout.pop_window_work_reporte,null);
//初始化popWindowpopupWindow=new PopupWindow(view,ViewGroup.LayoutParams.WRAP_CONTENT,ViewGroup.LayoutParams.WRAP_CONTENT,false);
//让popWindow响应点击背景时可以dismisspopupWindow.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));popupWindow.setOutsideTouchable(true);
//注册popWindow消失监听popupWindow.setOnDismissListener(new PopupWindow.OnDismissListener() {@Overridepublic void onDismiss() {//do someThing}});
与popMenu类似
但是默认实现是点击控件后,在控件下方显示一个窗口,这个窗口可以指定大小以及显示位置,但是不能像popMenu一样自动调整从上方还是下方弹出
另外,popWindow与AlertDialog的区别
最关键的区别是AlertDialog不能指定显示位置,只能默认显示在屏幕最中间(当然也可以通过设置WindowManager参数来改变位置)。而PopupWindow是可以指定显示位置的,随便哪个位置都可以,更加灵活。(引用https://blog.csdn.net/harvic880925/article/details/49272285)
下面简单实现一个popWindow() 实现mPopWindowBtn的下拉菜单效果
//初始化按钮
mPopWindowBtn = (Button) findViewById(R.id.button4);public void popWindowBtnOnClick(View view) {
//通过布局文件获取一个ViewmPopWindowView = getLayoutInflater().inflate(R.layout.dialog_layout, null);
//新建一个window,为这个window填充视图,指定宽度高度,指定是否可以点击
// Focusable 为True,PopupWindow的点击事件才会相应mPopWindow = new PopupWindow(mPopWindowView, WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.WRAP_CONTENT, true);
//为窗口中的控件注册点击事件TextView choosePhoto = (TextView) mPopWindowView.findViewById(R.id.choosePhoto);TextView takePhoto = (TextView) mPopWindowView.findViewById(R.id.takePhoto);choosePhoto.setOnClickListener(this);takePhoto.setOnClickListener(this);
//控制窗口弹出位置
//showAsDropDown,作为下拉菜单.showAtLocation(),选择弹出位置.mPopWindow.showAsDropDown(mPopWindowBtn);}@Overridepublic void onClick(View view) {switch (view.getId()){case R.id.takePhoto:Toast.makeText(this,"点击了拍照",Toast.LENGTH_SHORT).show();Log.i(TAG, "onClick: v.getId="+view.getId());break;case R.id.choosePhoto:Toast.makeText(this,"点击了从相册选择",Toast.LENGTH_SHORT).show();Log.i(TAG, "onClick: v.getId="+view.getId());break;}//关闭窗口mPopWindow.dismiss();}
如果想要控制window弹出的位置
可以通过showAtLocation()来控制
例如,让窗口在actionbar的右下角弹出
int height=layoutActionbar.getHeight() ;
popWindow.showAtLocation(layoutActionbar, Gravity.END| Gravity.TOP,0,height);
高度和宽度是像素值,控件的高度宽度
获取控件高度宽度 https://blog.csdn.net/CodeIsPoisonous/article/details/54316025
像素转换https://www.cnblogs.com/strinkbug/p/5780910.html
showanlocation的一个小bug
参数,x,y,偏移量为0的时候,没有问题,显示在xml的布局右上角
但是 参考 https://segmentfault.com/q/1010000004319065?sort=created
y增加偏移量的时候,发现距离对不上,上文需要添加50像素
其实我猜测,增加偏移量以后,系统设置的偏移量是根据的手机屏幕的右上角或者左上角为原点,而不是我们定义的xml框架的左上角右上角.手机屏幕的上边会有电源信号的状态栏,增加的这50其实就是状态栏的高度
假设状态栏高度为50,如果我们把y偏移量改为49或者任意小于50的数字,发现与0等同.
获取状态栏高度 https://blog.csdn.net/w_kahn/article/details/50684436
private int getStatusBarHeight(Context context) {int result = 0;int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");if (resourceId > 0) {result = context.getResources().getDimensionPixelSize(resourceId);}return result;
}
当状态栏不存在的时候会返回0;
窗口中的点击事件需要自己注册,没有类似于popMenu自己的监听器
默认popWindow点击back和外部控件,会先关闭窗口,需要再次点击back和外部控件才能触发相应的点击事件
如果需要popWindow既能响应back和外部控件点击关闭窗口,又能同时触发外部控件的点击事件
可以这样设置
popupWindow.setFocusable(false);
popupWindow.setOutsideTouchable(true);
有时候popwindow点击外部区域,不会自动dismiss,需要给window设置背景才有效
popWindowEdit.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
设置popwindow点击和消失时的背景变暗效果(设置透明度)
private void setBackgroundAlpha(float v) {WindowManager.LayoutParams lp=this.getWindow().getAttributes();lp.alpha=v;getWindow().setAttributes(lp);}
弹出时设置,消失时改回
setBackgroundAlpha(0.7f);popWindowEdit.setOnDismissListener(new PopupWindow.OnDismissListener() {@Overridepublic void onDismiss() {setBackgroundAlpha(1.0f);}});
模板代码
//点击时显示popWindowcase R.id.cb_selector:if (popMenu == null) {initPopMenu();}popMenu.showAsDropDown(cbSelector);break;//popWindow的初始化
View view=getLayoutInflater().inflate(R.layout.pop_window_review_selector,null,false);popMenu =new PopupWindow(view,ViewGroup.LayoutParams.WRAP_CONTENT,ViewGroup.LayoutParams.WRAP_CONTENT,false);
// 让popWindow支持点击背景消失popMenu.setOutsideTouchable(true);popMenu.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));popMenu.setOnDismissListener(new PopupWindow.OnDismissListener() {@Overridepublic void onDismiss() {//popWindow消失时的逻辑}});
}