Android 小技巧之通用 PopupWindow
2021-06-23 本文已影响0人
Kevin_小飞象
每日一图.jpg
Android 中的弹窗基本有两种,一种是AlertDialog,另一种是PopupWindow。AlertDialog 的显示位置是固定的,PopWindow 的显示位置是我们可以设置和调整的,因此,像项目中的一些场景如:某个功能的提示说明、点击按钮在按钮上方或者下方弹出菜单、新功能弹窗引导等。
API
- 构造函数
public PopupWindow(int width, int height)
public PopupWindow(View contentView, int width, int height)
public PopupWindow(View contentView, int width, int height, boolean focusable)
- 设置显示的View
public void setContentView(View contentView)
- 设置展示的宽、高
// 设置宽
public void setWidth(int width)
//设置高
public void setHeight(int height)
- 设置是否获取焦点
public void setFocusable(boolean focusable)
- 设置点击外区域是否隐藏 PopupWindow
public void setOutsideTouchable(boolean touchable)
- 隐藏
public void dismiss()
- 设置dissmiss 回调监听
public void setOnDismissListener(OnDismissListener onDismissListener)
- 显示 PopupWindow
//直接显示在参照View 的左下方
public void showAsDropDown(View anchor)
// 显示在参照View的左下方,可以通过xoff,yOff,来调节x,y方向的偏移
public void showAsDropDown(View anchor, int xoff, int off)
public void showAsDropDown(View anchor, int xoff, int yoff, int gravity)
//显示在指定位置,相对于整个屏幕的window而言,通过gravity调解显示在左、上、右、下、中. x,y调整两个方向的偏移
public void showAtLocation(View parent, int gravity, int x, int y)
源码
public class CustomPopWindow {
private Context mContext;
private int mWidth;
private int mHeight;
private boolean mIsFocusable = true;
private boolean mIsOutside = true;
private int mResLayoutId = -1;
private View mContentView;
private PopupWindow mPopupWindow;
private int mAnimationStyle = -1;
private boolean mClippEnable = true;//default is true
private boolean mIgnoreCheekPress = false;
private int mInputMode = -1;
private PopupWindow.OnDismissListener mOnDismissListener;
private int mSoftInputMode = -1;
private boolean mTouchable = true;//default is ture
private View.OnTouchListener mOnTouchListener;
private CustomPopWindow(Context context){
mContext = context;
}
public int getWidth() {
return mWidth;
}
public int getHeight() {
return mHeight;
}
/**
*
* @param anchor
* @param xOff
* @param yOff
* @return
*/
public CustomPopWindow showAsDropDown(View anchor, int xOff, int yOff){
if(mPopupWindow!=null){
mPopupWindow.showAsDropDown(anchor,xOff,yOff);
}
return this;
}
public CustomPopWindow showAsDropDown(View anchor){
if(mPopupWindow!=null){
mPopupWindow.showAsDropDown(anchor);
}
return this;
}
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
public CustomPopWindow showAsDropDown(View anchor, int xOff, int yOff, int gravity){
if(mPopupWindow!=null){
mPopupWindow.showAsDropDown(anchor,xOff,yOff,gravity);
}
return this;
}
/**
* 相对于父控件的位置(通过设置Gravity.CENTER,下方Gravity.BOTTOM等 ),可以设置具体位置坐标
* @param parent
* @param gravity
* @param x the popup's x location offset
* @param y the popup's y location offset
* @return
*/
public CustomPopWindow showAtLocation(View parent, int gravity, int x, int y){
if(mPopupWindow!=null){
mPopupWindow.showAtLocation(parent,gravity,x,y);
}
return this;
}
/**
* 添加一些属性设置
* @param popupWindow
*/
private void apply(PopupWindow popupWindow){
popupWindow.setClippingEnabled(mClippEnable);
if(mIgnoreCheekPress){
popupWindow.setIgnoreCheekPress();
}
if(mInputMode!=-1){
popupWindow.setInputMethodMode(mInputMode);
}
if(mSoftInputMode!=-1){
popupWindow.setSoftInputMode(mSoftInputMode);
}
if(mOnDismissListener!=null){
popupWindow.setOnDismissListener(mOnDismissListener);
}
if(mOnTouchListener!=null){
popupWindow.setTouchInterceptor(mOnTouchListener);
}
popupWindow.setTouchable(mTouchable);
}
private PopupWindow build(){
if(mContentView == null){
mContentView = LayoutInflater.from(mContext).inflate(mResLayoutId,null);
}
if(mWidth != 0 && mHeight!=0 ){
mPopupWindow = new PopupWindow(mContentView,mWidth,mHeight);
}else{
mPopupWindow = new PopupWindow(mContentView, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
}
if(mAnimationStyle!=-1){
mPopupWindow.setAnimationStyle(mAnimationStyle);
}
apply(mPopupWindow);//设置一些属性
mPopupWindow.setFocusable(mIsFocusable);
mPopupWindow.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
mPopupWindow.setOutsideTouchable(mIsOutside);
if(mWidth == 0 || mHeight == 0){
mPopupWindow.getContentView().measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
//如果外面没有设置宽高的情况下,计算宽高并赋值
mWidth = mPopupWindow.getContentView().getMeasuredWidth();
mHeight = mPopupWindow.getContentView().getMeasuredHeight();
}
mPopupWindow.update();
return mPopupWindow;
}
/**
* 关闭popWindow
*/
public void dissmiss(){
if(mPopupWindow!=null){
mPopupWindow.dismiss();
}
}
public static class PopupWindowBuilder{
private CustomPopWindow mCustomPopWindow;
public PopupWindowBuilder(Context context){
mCustomPopWindow = new CustomPopWindow(context);
}
public PopupWindowBuilder size(int width,int height){
mCustomPopWindow.mWidth = width;
mCustomPopWindow.mHeight = height;
return this;
}
public PopupWindowBuilder setFocusable(boolean focusable){
mCustomPopWindow.mIsFocusable = focusable;
return this;
}
public PopupWindowBuilder setView(int resLayoutId){
mCustomPopWindow.mResLayoutId = resLayoutId;
mCustomPopWindow.mContentView = null;
return this;
}
public PopupWindowBuilder setView(View view){
mCustomPopWindow.mContentView = view;
mCustomPopWindow.mResLayoutId = -1;
return this;
}
public PopupWindowBuilder setOutsideTouchable(boolean outsideTouchable){
mCustomPopWindow.mIsOutside = outsideTouchable;
return this;
}
/**
* 设置弹窗动画
* @param animationStyle
* @return
*/
public PopupWindowBuilder setAnimationStyle(int animationStyle){
mCustomPopWindow.mAnimationStyle = animationStyle;
return this;
}
public PopupWindowBuilder setClippingEnable(boolean enable){
mCustomPopWindow.mClippEnable =enable;
return this;
}
public PopupWindowBuilder setIgnoreCheekPress(boolean ignoreCheekPress){
mCustomPopWindow.mIgnoreCheekPress = ignoreCheekPress;
return this;
}
public PopupWindowBuilder setInputMethodMode(int mode){
mCustomPopWindow.mInputMode = mode;
return this;
}
public PopupWindowBuilder setOnDissmissListener(PopupWindow.OnDismissListener onDissmissListener){
mCustomPopWindow.mOnDismissListener = onDissmissListener;
return this;
}
public PopupWindowBuilder setSoftInputMode(int softInputMode){
mCustomPopWindow.mSoftInputMode = softInputMode;
return this;
}
public PopupWindowBuilder setTouchable(boolean touchable){
mCustomPopWindow.mTouchable = touchable;
return this;
}
public PopupWindowBuilder setTouchIntercepter(View.OnTouchListener touchIntercepter){
mCustomPopWindow.mOnTouchListener = touchIntercepter;
return this;
}
public CustomPopWindow create(){
//构建PopWindow
mCustomPopWindow.build();
return mCustomPopWindow;
}
}
}
使用
public class MainActivity extends BaseActivity {
@BindView(R.id.show_top)
Button mShowTop;
@BindView(R.id.show_center)
Button mShowCenter;
@BindView(R.id.show_bottom)
Button mShowBottom;
@BindView(R.id.show_left)
Button mShowLeft;
@BindView(R.id.show_right)
Button mShowRignt;
private CustomPopWindow mPopupWindow;
@OnClick({R.id.show_top,R.id.show_center,R.id.show_bottom,R.id.show_left,R.id.show_right})
public void onClicked(View view) {
switch (view.getId()) {
case R.id.show_top:
showBottom();
break;
case R.id.show_center:
break;
case R.id.show_bottom:
showSelectPhoto();
break;
case R.id.show_left:
showLeft();
break;
case R.id.show_right:
showRight();
break;
default:
break;
}
}
@Override
public int getLayoutId() {
return R.layout.activity_main;
}
@Override
public void initView() {
}
private void showBottom() {
View contentView = LayoutInflater.from(this).inflate(R.layout.popup_left_or_right,null);
handleBottom(contentView);
PopUtils.setBackgroundAlpha(MainActivity.this, 0.4f);
mPopupWindow = new CustomPopWindow.PopupWindowBuilder(this)
.setView(contentView)
.size(ViewGroup.LayoutParams.WRAP_CONTENT,ViewGroup.LayoutParams.WRAP_CONTENT)
.setFocusable(true)
.setOutsideTouchable(true)
.setAnimationStyle(R.style.AnimDown)
.setOnDissmissListener(new PopupWindow.OnDismissListener() {
@Override
public void onDismiss() {
// popupWindow隐藏时恢复屏幕正常透明度
PopUtils.setBackgroundAlpha(MainActivity.this, 1.0f);
}
})
.create()
.showAsDropDown(mShowTop,0,10);
}
private void showRight() {
View contentView = LayoutInflater.from(this).inflate(R.layout.popup_left_or_right,null);
handleBottom(contentView);
PopUtils.setBackgroundAlpha(MainActivity.this, 0.4f);
mPopupWindow = new CustomPopWindow.PopupWindowBuilder(this)
.setView(contentView)
.size(ViewGroup.LayoutParams.WRAP_CONTENT,ViewGroup.LayoutParams.WRAP_CONTENT)
.setFocusable(true)
.setOutsideTouchable(true)
.setAnimationStyle(R.style.AnimHorizontal)
.setOnDissmissListener(new PopupWindow.OnDismissListener() {
@Override
public void onDismiss() {
// popupWindow隐藏时恢复屏幕正常透明度
PopUtils.setBackgroundAlpha(MainActivity.this, 1.0f);
}
})
.create()
.showAsDropDown(mShowRignt,mShowRignt.getWidth(),-mShowRignt.getHeight());
}
private void showLeft() {
View contentView = LayoutInflater.from(this).inflate(R.layout.popup_left_or_right,null);
handleBottom(contentView);
PopUtils.setBackgroundAlpha(MainActivity.this, 0.4f);
mPopupWindow = new CustomPopWindow.PopupWindowBuilder(this)
.setView(contentView)
.size(ViewGroup.LayoutParams.WRAP_CONTENT,ViewGroup.LayoutParams.WRAP_CONTENT)
.setFocusable(true)
.setOutsideTouchable(true)
.setAnimationStyle(R.style.AnimHorizontal)
.setOnDissmissListener(new PopupWindow.OnDismissListener() {
@Override
public void onDismiss() {
// popupWindow隐藏时恢复屏幕正常透明度
PopUtils.setBackgroundAlpha(MainActivity.this, 1.0f);
}
})
.create()
.showAsDropDown(mShowLeft,-mShowLeft.getWidth(),-mShowLeft.getHeight());
}
private void handleBottom(View contentView) {
View.OnClickListener listener = new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mPopupWindow != null) {
mPopupWindow.dissmiss();
}
switch (v.getId()) {
case R.id.tv_like:
ToastUtils.showToast(MainActivity.this,"赞一个");
break;
case R.id.tv_hate:
ToastUtils.showToast(MainActivity.this,"踩一个");
break;
default:
break;
}
}
};
//设置点击事件
contentView.findViewById(R.id.tv_like).setOnClickListener(listener);
contentView.findViewById(R.id.tv_hate).setOnClickListener(listener);
}
private void showSelectPhoto() {
View contentView = LayoutInflater.from(this).inflate(R.layout.popup_up,null);
handleLogic(contentView);
PopUtils.setBackgroundAlpha(MainActivity.this, 0.4f);
mPopupWindow = new CustomPopWindow.PopupWindowBuilder(this)
.setView(contentView)
.size(ViewGroup.LayoutParams.MATCH_PARENT,contentView.getMeasuredHeight())
.setFocusable(true)
.setOutsideTouchable(true)
.setAnimationStyle(R.style.AnimUp)
.setOnDissmissListener(new PopupWindow.OnDismissListener() {
@Override
public void onDismiss() {
// popupWindow隐藏时恢复屏幕正常透明度
PopUtils.setBackgroundAlpha(MainActivity.this, 1.0f);
}
})
.create()
.showAtLocation(mShowBottom,Gravity.BOTTOM,0,0);
}
private void handleLogic(View contentView) {
View.OnClickListener listener = new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mPopupWindow != null) {
mPopupWindow.dissmiss();
}
switch (v.getId()) {
case R.id.btn_take_photo:
break;
case R.id.btn_select_photo:
break;
case R.id.btn_cancel:
break;
default:
break;
}
}
};
//设置点击事件
contentView.findViewById(R.id.btn_take_photo).setOnClickListener(listener);
contentView.findViewById(R.id.btn_select_photo).setOnClickListener(listener);
contentView.findViewById(R.id.btn_cancel).setOnClickListener(listener);
}
}