Android(安卓)开发之通用的 PopupWindow
16lz
2021-01-26
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,布局文件和用到的动画我会上传到我的资源,请自行前往下载!
更多相关文章
- 设置程序[置顶] android(10)_android权限大全
- Android中Adapter使用ViewHolder优化
- Android(安卓)Studio初次使用genymotion注意几点
- Android之多语言设置
- android 焦点控制
- Android学习笔记(14):相对布局RelativeLayout
- Android(安卓)Material Design NavigationView
- android新特性: 底部导航栏BottomNavigationView系统库与第三方库
- 文章【Android(安卓)的视频编码 H263 MP4V H264】的代码实现