PopupWindow 这个类用来实现一个弹出框,可以使用任意布局的 View 作为其内容,这个弹出框是悬浮在当前 activity 之上的。
效果图:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HaX5p9CD-1575526739000)(https://img-my.csdn.net/uploads/201706/15/1497505682_8071.gif-thumb.jpg)]
1,向下弹出用到了 RecyclerView 所以我们在 app 文件夹下的 build.gradle 添加:
compile 'com.android.support:recyclerview-v7:25.2.0'
compile 'com.zhy:base-rvadapter:3.0.3'
2,封装一个通用的 CommonPopupWindow.java
package com.gyq.popupwindowtest.pop;
import android.content.Context;
import android.view.View;
import android.widget.PopupWindow;
import com.gyq.popupwindowtest.PopupController;
import com.gyq.popupwindowtest.utils.CommonUtil;
/**
* Created by gyq on 2017/6/15 09:53
*/
public class CommonPopupWindow extends PopupWindow {
private PopupController controller;
@Override
public int getWidth() {
return controller.mPopupView.getMeasuredWidth();
}
@Override
public int getHeight() {
return controller.mPopupView.getMeasuredHeight();
}
public interface ViewInterface {
void getChildView(View view, int layoutResId);
}
private CommonPopupWindow(Context context) {
controller = new PopupController(context, this);
}
@Override
public void dismiss() {
super.dismiss();
controller.setBackGroundLevel(1.0f);
}
public static class Builder {
private final PopupController.PopupParams params;
private ViewInterface listener;
public Builder(Context context) {
params = new PopupController.PopupParams(context);
}
/**
* @param layoutResId 设置PopupWindow 布局ID
* @return Builder
*/
public Builder setView(int layoutResId) {
params.mView = null;
params.layoutResId = layoutResId;
return this;
}
/**
* @param view 设置PopupWindow布局
* @return Builder
*/
public Builder setView(View view) {
params.mView = view;
params.layoutResId = 0;
return this;
}
/**
* 设置子View
*
* @param listener ViewInterface
* @return Builder
*/
public Builder setViewOnclickListener(ViewInterface listener) {
this.listener = listener;
return this;
}
/**
* 设置宽度和高度 如果不设置 默认是wrap_content
*
* @param width 宽
* @return Builder
*/
public Builder setWidthAndHeight(int width, int height) {
params.mWidth = width;
params.mHeight = height;
return this;
}
/**
* 设置背景灰色程度
*
* @param level 0.0f-1.0f
* @return Builder
*/
public Builder setBackGroundLevel(float level) {
params.isShowBg = true;
params.bg_level = level;
return this;
}
/**
* 是否可点击Outside消失
*
* @param touchable 是否可点击
* @return Builder
*/
public Builder setOutsideTouchable(boolean touchable) {
params.isTouchable = touchable;
return this;
}
/**
* 设置动画
*
* @return Builder
*/
public Builder setAnimationStyle(int animationStyle) {
params.isShowAnim = true;
params.animationStyle = animationStyle;
return this;
}
public CommonPopupWindow create() {
final CommonPopupWindow popupWindow = new CommonPopupWindow(params.mContext);
params.apply(popupWindow.controller);
if (listener != null && params.layoutResId != 0) {
listener.getChildView(popupWindow.controller.mPopupView, params.layoutResId);
}
CommonUtil.measureWidthAndHeight(popupWindow.controller.mPopupView);
return popupWindow;
}
}
}
其中,用到的 PopupController.java
package com.gyq.popupwindowtest;
import android.app.Activity;
import android.content.Context;
import android.graphics.drawable.ColorDrawable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.PopupWindow;
/**
* Created by gyq on 2017/6/15 09:52
*/
public class PopupController {
private int layoutResId;//布局id
private Context context;
private PopupWindow popupWindow;
public View mPopupView;//弹窗布局View
private View mView;
private Window mWindow;
public PopupController(Context context, PopupWindow popupWindow) {
this.context = context;
this.popupWindow = popupWindow;
}
public void setView(int layoutResId) {
mView = null;
this.layoutResId = layoutResId;
installContent();
}
public void setView(View view) {
mView = view;
this.layoutResId = 0;
installContent();
}
private void installContent() {
if (layoutResId != 0) {
mPopupView = LayoutInflater.from(context).inflate(layoutResId, null);
} else if (mView != null) {
mPopupView = mView;
}
popupWindow.setContentView(mPopupView);
}
/**
* 设置宽度
*
* @param width 宽
* @param height 高
*/
private void setWidthAndHeight(int width, int height) {
if (width == 0 || height == 0) {
//如果没设置宽高,默认是WRAP_CONTENT
popupWindow.setWidth(ViewGroup.LayoutParams.WRAP_CONTENT);
popupWindow.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT);
} else {
popupWindow.setWidth(width);
popupWindow.setHeight(height);
}
}
/**
* 设置背景灰色程度
*
* @param level 0.0f-1.0f
*/
public void setBackGroundLevel(float level) {
mWindow = ((Activity) context).getWindow();
WindowManager.LayoutParams params = mWindow.getAttributes();
params.alpha = level;
mWindow.setAttributes(params);
}
/**
* 设置动画
*/
private void setAnimationStyle(int animationStyle) {
popupWindow.setAnimationStyle(animationStyle);
}
/**
* 设置Outside是否可点击
*
* @param touchable 是否可点击
*/
private void setOutsideTouchable(boolean touchable) {
popupWindow.setBackgroundDrawable(new ColorDrawable(0x00000000));//设置透明背景
popupWindow.setOutsideTouchable(touchable);//设置outside可点击
popupWindow.setFocusable(touchable);
}
public static class PopupParams {
public int layoutResId;//布局id
public Context mContext;
public int mWidth, mHeight;//弹窗的宽和高
public boolean isShowBg, isShowAnim;
public float bg_level;//屏幕背景灰色程度
public int animationStyle;//动画Id
public View mView;
public boolean isTouchable = true;
public PopupParams(Context mContext) {
this.mContext = mContext;
}
public void apply(PopupController controller) {
if (mView != null) {
controller.setView(mView);
} else if (layoutResId != 0) {
controller.setView(layoutResId);
} else {
throw new IllegalArgumentException("PopupView's contentView is null");
}
controller.setWidthAndHeight(mWidth, mHeight);
controller.setOutsideTouchable(isTouchable);//设置outside可点击
if (isShowBg) {
//设置背景
controller.setBackGroundLevel(bg_level);
}
if (isShowAnim) {
controller.setAnimationStyle(animationStyle);
}
}
}
}
3,给 RecyclerView 的 item 设置间距 SpacesItemDecoration.java
package com.gyq.popupwindowtest.pop;
import android.graphics.Rect;
import android.support.v7.widget.RecyclerView;
import android.view.View;
/**
* Created by gyq on 2017/6/15 13:34
*/
public class SpacesItemDecoration extends RecyclerView.ItemDecoration {
private int space;
public SpacesItemDecoration(int space) {
this.space = space;
}
@Override
public void getItemOffsets(Rect outRect, View view,
RecyclerView parent, RecyclerView.State state) {
outRect.left = space;
outRect.right = space;
outRect.bottom = space;
// Add top margin only for the first item to avoid double space between items
if (parent.getChildPosition(view) == 0)
outRect.top = space;
}
}
4,在 MainActivity.java 中使用:
package com.gyq.popupwindowtest;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import com.gyq.popupwindowtest.pop.CommonPopupWindow;
import com.gyq.popupwindowtest.pop.SpacesItemDecoration;
import com.gyq.popupwindowtest.utils.CommonUtil;
import com.zhy.adapter.recyclerview.CommonAdapter;
import com.zhy.adapter.recyclerview.MultiItemTypeAdapter;
import com.zhy.adapter.recyclerview.base.ViewHolder;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private Button mCenter,mTop,mBottom,mLeft,mRight;
private CommonPopupWindow popupWindow;
private CommonAdapter<String> mAdapter;
private List<String> mDatas = new ArrayList<>();
private int spacingInPixels = 18;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initViews();
initListener();
loadDatas();
}
private void loadDatas() {
for (int i = 0;i < 10;i++) {
mDatas.add("王者荣耀");
}
}
private void initListener() {
//仿微信修改头像弹出pop
mCenter.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (popupWindow != null && popupWindow.isShowing()) {
return;
}
View upView = LayoutInflater.from(MainActivity.this).inflate(R.layout.popup_up, null);
CommonUtil.measureWidthAndHeight(upView);
popupWindow = new CommonPopupWindow.Builder(MainActivity.this)
.setView(R.layout.popup_up)
.setWidthAndHeight(ViewGroup.LayoutParams.MATCH_PARENT,upView.getMeasuredHeight())
.setBackGroundLevel(0.5f)//取值范围0.0f-1.0f 值越小越暗
.setAnimationStyle(R.style.AnimUp)
.setViewOnclickListener(new CommonPopupWindow.ViewInterface() {
@Override
public void getChildView(View view, int layoutResId) {
Button btn_take_photo = (Button) view.findViewById(R.id.btn_take_photo);
Button btn_select_photo = (Button) view.findViewById(R.id.btn_select_photo);
Button btn_cancel = (Button) view.findViewById(R.id.btn_cancel);
btn_take_photo.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
toast("拍照");
if (popupWindow != null) {
popupWindow.dismiss();
}
}
});
btn_select_photo.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
toast("相册选取");
if (popupWindow != null) {
popupWindow.dismiss();
}
}
});
btn_cancel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (popupWindow != null) {
popupWindow.dismiss();
}
}
});
view.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (popupWindow != null) {
popupWindow.dismiss();
}
return true;
}
});
}
})
.create();
popupWindow.showAtLocation(mCenter, Gravity.BOTTOM,0,0);
}
});
//向下弹出pop
mTop.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (popupWindow != null && popupWindow.isShowing()) {
return;
}
popupWindow = new CommonPopupWindow.Builder(MainActivity.this)
.setView(R.layout.popup_down)
.setWidthAndHeight(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
.setAnimationStyle(R.style.AnimDown)
.setViewOnclickListener(new CommonPopupWindow.ViewInterface() {
@Override
public void getChildView(View view, int layoutResId) {
RecyclerView rv = (RecyclerView)view.findViewById(R.id.recycler_view);
GridLayoutManager manager = new GridLayoutManager(MainActivity.this,3);
rv.setLayoutManager(manager);
rv.addItemDecoration(new SpacesItemDecoration(spacingInPixels));
mAdapter = new CommonAdapter<String>(MainActivity.this,R.layout.itme_rv_popup,mDatas) {
@Override
protected void convert(ViewHolder holder, String s, int position) {
holder.setText(R.id.tv_item_title,s);
}
};
mAdapter.setOnItemClickListener(new MultiItemTypeAdapter.OnItemClickListener() {
@Override
public void onItemClick(View view, RecyclerView.ViewHolder holder, int position) {
toast("点击了" + position);
}
@Override
public boolean onItemLongClick(View view, RecyclerView.ViewHolder holder, int position) {
return false;
}
});
rv.setAdapter(mAdapter);
}
})
.setOutsideTouchable(true)
.create();
popupWindow.showAsDropDown(view);
}
});
//向右弹pop
mRight.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (popupWindow != null && popupWindow.isShowing()) return;
popupWindow = new CommonPopupWindow.Builder(MainActivity.this)
.setView(R.layout.popup_left_or_right)
.setWidthAndHeight(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)
.setAnimationStyle(R.style.AnimHorizontal)
.setViewOnclickListener(new CommonPopupWindow.ViewInterface() {
@Override
public void getChildView(View view, int layoutResId) {
TextView tv_like = (TextView) view.findViewById(R.id.tv_like);
TextView tv_hate = (TextView) view.findViewById(R.id.tv_hate);
tv_like.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
toast("赞一个");
popupWindow.dismiss();
}
});
tv_hate.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
toast("踩一下");
popupWindow.dismiss();
}
});
}
})
.create();
popupWindow.showAsDropDown(view, view.getWidth(), -view.getHeight());
}
});
//向左弹pop
mLeft.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (popupWindow != null && popupWindow.isShowing()) return;
popupWindow = new CommonPopupWindow.Builder(MainActivity.this)
.setView(R.layout.popup_left_or_right)
.setWidthAndHeight(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)
.setAnimationStyle(R.style.AnimRight)
.setViewOnclickListener(new CommonPopupWindow.ViewInterface() {
@Override
public void getChildView(View view, int layoutResId) {
TextView tv_like = (TextView) view.findViewById(R.id.tv_like);
TextView tv_hate = (TextView) view.findViewById(R.id.tv_hate);
tv_like.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
toast("赞一个");
popupWindow.dismiss();
}
});
tv_hate.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
toast("踩一下");
popupWindow.dismiss();
}
});
}
})
.create();
popupWindow.showAsDropDown(view, -popupWindow.getWidth(), -view.getHeight());
}
});
//向上弹pop
mBottom.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (popupWindow != null && popupWindow.isShowing()) return;
popupWindow = new CommonPopupWindow.Builder(MainActivity.this)
.setView(R.layout.popup_left_or_right)
.setWidthAndHeight(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)
.setViewOnclickListener(new CommonPopupWindow.ViewInterface() {
@Override
public void getChildView(View view, int layoutResId) {
TextView tv_like = (TextView) view.findViewById(R.id.tv_like);
TextView tv_hate = (TextView) view.findViewById(R.id.tv_hate);
tv_like.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
toast("赞一个");
popupWindow.dismiss();
}
});
tv_hate.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
toast("踩一下");
popupWindow.dismiss();
}
});
}
})
.create();
popupWindow.showAsDropDown(view, 0, -(popupWindow.getHeight() + view.getMeasuredHeight()));
}
});
}
private void initViews() {
mCenter = (Button)findViewById(R.id.show_center);
mTop = (Button)findViewById(R.id.show_top);
mBottom = (Button)findViewById(R.id.show_bottom);
mLeft = (Button)findViewById(R.id.show_left);
mRight = (Button)findViewById(R.id.show_right);
}
private void toast(String s) {
Toast.makeText(MainActivity.this,s,Toast.LENGTH_SHORT).show();
}
}
其中,用到的工具类 CommonUtil.java
package com.gyq.popupwindowtest.utils;
import android.view.View;
/**
* Created by gyq on 2017/6/15 10:06
*/
public class CommonUtil {
/**
* 测量View的宽高
*
* @param view View
*/
public static void measureWidthAndHeight(View view) {
int w = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
int h = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
view.measure(w, h);
}
}
5,布局文件和用到的动画我会上传到我的资源,请自行前往下载!