自定义 popWindow弹框 工具包
前言:因为Android 没有像IOS一样的ActionSheet,虽然在github上看到有一些类似ActionSheet的库,总觉得不好用,不如自己写一个弹框通用类,样式全部自已来多好。
Step 1
废话不多说,直接上代码。
public class CustomPopWindow implements PopupWindow.OnDismissListener{
private static final String TAG = "CustomPopWindow";
private static final float DEFAULT_ALPHA = 0.7f;
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 Window mWindow;//当前Activity 的窗口
/**
* 弹出PopWindow 背景是否变暗,默认不会变暗。
*/
private boolean mIsBackgroundDark = false; private float mBackgroundDrakValue = 0;// 背景变暗的值,0 - 1
/**
* 设置是否允许点击 PopupWindow之外的地方,关闭PopupWindow
*/
private boolean enableOutsideTouchDisMiss = true;// 默认点击pop之外的地方可以关闭 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);
} // 2017.3.17 add
// 获取当前Activity的window
Activity activity = (Activity) mContentView.getContext();
if(activity!=null && mIsBackgroundDark){
//如果设置的值在0 - 1的范围内,则用设置的值,否则用默认值
final float alpha = (mBackgroundDrakValue > 0 && mBackgroundDrakValue < 1) ? mBackgroundDrakValue : DEFAULT_ALPHA;
mWindow = activity.getWindow();
WindowManager.LayoutParams params = mWindow.getAttributes();
params.alpha = alpha;
mWindow.addFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
mWindow.setAttributes(params);
} 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);//设置一些属性 if(mWidth == 0 || mHeight == 0){
mPopupWindow.getContentView().measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
//如果外面没有设置宽高的情况下,计算宽高并赋值
mWidth = mPopupWindow.getContentView().getMeasuredWidth();
mHeight = mPopupWindow.getContentView().getMeasuredHeight();
} // 添加dissmiss 监听
mPopupWindow.setOnDismissListener(this); //2017.6.27 add:fix 设置 setOutsideTouchable(false)点击外部取消的bug.
// 判断是否点击PopupWindow之外的地方关闭 popWindow
if(!enableOutsideTouchDisMiss){
//注意这三个属性必须同时设置,不然不能disMiss,以下三行代码在Android 4.4 上是可以,然后在Android 6.0以上,下面的三行代码就不起作用了,就得用下面的方法
mPopupWindow.setFocusable(true);
mPopupWindow.setOutsideTouchable(false);
mPopupWindow.setBackgroundDrawable(null);
//注意下面这三个是contentView 不是PopupWindow
mPopupWindow.getContentView().setFocusable(true);
mPopupWindow.getContentView().setFocusableInTouchMode(true);
mPopupWindow.getContentView().setOnKeyListener(new View.OnKeyListener() {
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
mPopupWindow.dismiss(); return true;
}
return false;
}
});
//在Android 6.0以上 ,只能通过拦截事件来解决
mPopupWindow.setTouchInterceptor(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) { final int x = (int) event.getX();
final int y = (int) event.getY(); if ((event.getAction() == MotionEvent.ACTION_DOWN)
&& ((x < 0) || (x >= mWidth) || (y < 0) || (y >= mHeight))) {
Log.e(TAG,"out side ");
Log.e(TAG,"width:"+mPopupWindow.getWidth()+"height:"+mPopupWindow.getHeight()+" x:"+x+" y :"+y);
return true;
} else if (event.getAction() == MotionEvent.ACTION_OUTSIDE) {
Log.e(TAG,"out side ...");
return true;
}
return false;
}
});
}else{
mPopupWindow.setFocusable(mIsFocusable);
mPopupWindow.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
mPopupWindow.setOutsideTouchable(mIsOutside);
}
// update
mPopupWindow.update(); return mPopupWindow;
} @Override
public void onDismiss() {
dissmiss();
} /**
* 关闭popWindow
*/
public void dissmiss(){ if(mOnDismissListener!=null){
mOnDismissListener.onDismiss();
} //如果设置了背景变暗,那么在dissmiss的时候需要还原
if(mWindow!=null){
WindowManager.LayoutParams params = mWindow.getAttributes();
params.alpha = 1.0f;
mWindow.setAttributes(params);
}
if(mPopupWindow!=null && mPopupWindow.isShowing()){
mPopupWindow.dismiss();
}
} public PopupWindow getPopupWindow() {
return mPopupWindow;
} 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;
} /**
* 设置背景变暗是否可用
* @param isDark
* @return
*/
public PopupWindowBuilder enableBackgroundDark(boolean isDark){
mCustomPopWindow.mIsBackgroundDark = isDark;
return this;
} /**
* 设置背景变暗的值
* @param darkValue
* @return
*/
public PopupWindowBuilder setBgDarkAlpha(float darkValue){
mCustomPopWindow.mBackgroundDrakValue = darkValue;
return this;
} /**
* 设置是否允许点击 PopupWindow之外的地方,关闭PopupWindow
* @param disMiss
* @return
*/
public PopupWindowBuilder enableOutsideTouchableDissmiss(boolean disMiss){
mCustomPopWindow.enableOutsideTouchDisMiss = disMiss;
return this;
} public CustomPopWindow create(){
//构建PopWindow
mCustomPopWindow.build();
return mCustomPopWindow;
} } }
Step 2
make a example.举一个分享的例子吧。
点击分享,弹出这样的一个分享框。
Step 3
怎么用呢?
1.调用的函数,展示一个分享的pop弹框,用kotlin来写。 声明一下:popWindow_share是CustomPopWindow类型的。
fun showShareDialog(title:String,content:String,link:String,id:String){
val contentView:View=LayoutInflater.from(context).inflate(R.layout.ask_share,null)
hanleShareDialog(contentView,title,content,link,id)//分享处理函数
popWindow_share= CustomPopWindow.PopupWindowBuilder(context)
.setView(contentView)
.enableBackgroundDark(true)
.setBgDarkAlpha(0.7f)
.setFocusable(true)
.setOutsideTouchable(true)
.setAnimationStyle(R.style.ask_share_anim)
.create()
popWindow_share!!.showAtLocation(ask_main_right_btn,Gravity.CENTER,0,0) }
2.分享的布局--ask_share.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" > <LinearLayout
android:layout_width="500pt"
android:layout_height="400pt"
android:background="@drawable/textview_four_round"
android:orientation="vertical"
> <TextView
android:id="@+id/ask_choose_tv"
android:layout_width="500pt"
android:layout_height="80pt"
android:text="分享到"
android:textSize="32pt"
android:gravity="center"
android:textColor="@color/black"/> <LinearLayout
android:id="@+id/ask_share_first_line"
android:orientation="horizontal"
android:layout_marginLeft="50pt"
android:layout_marginRight="50pt"
android:layout_width="match_parent"
android:layout_height="160pt"> <RelativeLayout
android:id="@+id/ask_share_qq"
android:layout_width="133pt"
android:layout_height="133pt"
android:background="@color/white"
> <ImageView
android:id="@+id/ask_share_qq_iv"
android:layout_width="65pt"
android:layout_height="65pt"
android:layout_centerHorizontal="true"
android:layout_marginTop="20pt"
android:src="@mipmap/qq"
/> <TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="QQ"
android:layout_centerHorizontal="true"
android:layout_below="@+id/ask_share_qq_iv"
android:layout_marginTop="8pt"
android:textSize="30pt"
android:textColor="@color/share_words"
/> </RelativeLayout> <RelativeLayout
android:id="@+id/ask_share_wechat"
android:layout_width="133pt"
android:layout_height="133pt"
android:background="@color/white"
> <ImageView
android:id="@+id/ask_share_wechat_iv"
android:layout_width="65pt"
android:layout_height="65pt"
android:layout_centerHorizontal="true"
android:layout_marginTop="20pt"
android:src="@mipmap/wechat"
/> <TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="微信"
android:layout_centerHorizontal="true"
android:layout_below="@+id/ask_share_wechat_iv"
android:layout_marginTop="8pt"
android:textSize="30pt"
android:textColor="@color/share_words"
/> </RelativeLayout> <RelativeLayout
android:id="@+id/ask_share_copy"
android:layout_width="134pt"
android:layout_height="133pt"
android:background="@color/white"
> <ImageView
android:id="@+id/ask_share_copy_iv"
android:layout_width="65pt"
android:layout_height="65pt"
android:layout_centerHorizontal="true"
android:layout_marginTop="20pt"
android:src="@mipmap/link"
/> <TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="复制链接"
android:layout_centerHorizontal="true"
android:layout_below="@+id/ask_share_copy_iv"
android:layout_marginTop="8pt"
android:textSize="30pt"
android:textColor="@color/share_words"
/> </RelativeLayout> </LinearLayout> <LinearLayout
android:id="@+id/ask_share_second_line"
android:layout_width="match_parent"
android:orientation="horizontal"
android:layout_marginLeft="50pt"
android:layout_marginRight="50pt"
android:layout_height="160pt"> <RelativeLayout
android:id="@+id/ask_share_qq_zone"
android:layout_width="133pt"
android:layout_height="133pt"
android:background="@color/white"
> <ImageView
android:id="@+id/ask_share_qq_zone_iv"
android:layout_width="65pt"
android:layout_height="65pt"
android:layout_centerHorizontal="true"
android:layout_marginTop="20pt"
android:src="@mipmap/qzone"
/> <TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="QQ空间"
android:layout_centerHorizontal="true"
android:layout_below="@+id/ask_share_qq_zone_iv"
android:layout_marginTop="8pt"
android:textSize="30pt"
android:textColor="@color/share_words"
/> </RelativeLayout> <RelativeLayout
android:id="@+id/ask_share_wechat_friends"
android:layout_width="133pt"
android:layout_height="133pt"
android:background="@color/white"
> <ImageView
android:id="@+id/ask_share_friends_iv"
android:layout_width="65pt"
android:layout_height="65pt"
android:layout_centerHorizontal="true"
android:layout_marginTop="20pt"
android:src="@mipmap/moments"
/> <TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="朋友圈"
android:layout_centerHorizontal="true"
android:layout_below="@+id/ask_share_friends_iv"
android:layout_marginTop="8pt"
android:textSize="30pt"
android:textColor="@color/share_words"
/> </RelativeLayout> </LinearLayout> </LinearLayout> </LinearLayout>
3.pop弹框的动画--ask_share_anim.xml
<!--问问分享弹框样式-->
<style name="ask_share_anim" parent="android:Animation">
<item name="android:windowEnterAnimation">@anim/pop_share_enter_anim</item>
<item name="android:windowExitAnimation">@anim/pop_share_exit_anim</item>
</style>
//pop_share_enter_anim.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<scale
android:fromXScale="0.6"
android:toXScale="1.0"
android:fromYScale="0.6"
android:toYScale="1.0"
android:pivotX="50%"
android:pivotY="50%"
android:duration="300" />
<alpha
android:interpolator="@android:anim/decelerate_interpolator"
android:fromAlpha="0.0"
android:toAlpha="1.0"
android:duration="300" />
</set>
//pop_share_exit_anim.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<scale
android:fromXScale="1.0"
android:toXScale="0.5"
android:fromYScale="1.0"
android:toYScale="0.5"
android:pivotX="50%"
android:pivotY="50%"
android:duration="300" />
<alpha
android:interpolator="@android:anim/accelerate_interpolator"
android:fromAlpha="1.0"
android:toAlpha="0.0"
android:duration="300" />
</set>
That's all.
If you have any qestions,please leave me messages .
自定义 popWindow弹框 工具包的更多相关文章
- JavaScript实现自定义alert弹框
aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAh0AAAFkCAYAAACEpYlzAAAfj0lEQVR4nO3dC5BddZ0n8F93pxOQCO
- CodePush自定义更新弹框及下载进度条
CodePush 热更新之自定义更新弹框及下载进度 先来几张弹框效果图 非强制更新场景 image 强制更新场景 image 更新包下载进度效果 image 核心代码 这里的热更新Modal框,是封装 ...
- 自定义alert弹框,title不显示域名
问题: 系统默认的alert弹框的title会默认显示网页域名 解决办法: (修改弹框样式) (function() { window.alert = function(name) { $(" ...
- WPF 如何自定义一个弹框
------------吾亦无他,唯手熟尔,谦卑若愚,好学若饥------------- 简述: 手工以原生Grid的方式,自定义了一个仿弹窗效果,优点可以自定义,缺点需要自己实现以及维护整个弹窗的效 ...
- 自定义alert弹框,title不显示域名(重写alert)
问题: 系统默认的alert弹框的title会默认显示网页域名 解决办法: (修改弹框样式) (function() { window.alert = function(name) { $(" ...
- swift4.2 - 一个自定义view弹框
import UIKit /* * 注册协议view:没找到 UI原图,咱不实现 */ class JYRegisterProtocolView: UIView { /// 点击同意协议的回调 pri ...
- 自定义alert弹框
/**************** UIAlertControllerStyleAlert *************************/ /*创建一个 可以自定义文字颜色和字体大小的IAler ...
- vue自定义插件-弹框
<template> <transition name="msgbox"> <div v-if="show" class=&quo ...
- vue 自定义动态弹框
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
随机推荐
- SpringMVC10 InitBinder 注册自定义编辑器
1.配置web.xml文件 <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3// ...
- 使用startForeground让android服务前台运行
最近在使用android 4.1系统的时候,发现在手机休眠一段时间后(1-2小时),后台运行的服务被强行kill掉,有可能是系统回收内存的一种机制,要想避免这种情况可以通过startForegroun ...
- IOS 一些好的框架和 技术大牛的博客
http://blog.csdn.net/rodulf/article/details/51871093 比较好的框架链接: http://www.jianshu.com/p/9216c561b0f ...
- 【洛谷1486】[NOI2004] 郁闷的出纳员(Splay的小运用)
点此看题面 大致题意: 你是一个公司的出纳员,现在有\(n\)个操作,操作有4种:新来一个员工.增加全体员工工资.减少全体员工工资.查询第\(k\)多的工资.若一个员工的工资在某一时刻低于合同上的工资 ...
- 【BZOJ2002】[HNOI2010] 弹飞绵羊(大力分块)
点此看题面 大致题意: 有\(n\)个弹力装置,当到达第\(i\)个装置时,会被弹到第\(i+k_i\)个装置,若不存在第\(i+k_i\)个装置,就会被弹飞.有两种操作,一种操作是将\(k_x\)改 ...
- 博弈论经典算法(一)——对抗搜索与Alpha-Beta剪枝
前言 在一些复杂的博弈论题目中,每一轮操作都可能有许多决策,于是就会形成一棵庞大的博弈树. 而有一些博弈论题没有什么规律,针对这样的问题,我们就需要用一些十分玄学的算法. 例如对抗搜索. 对抗搜索简介 ...
- Angular2--显示数据
1.插值表达式 要显示组件的属性,最简单的方式就是通过插值表达式来绑定属性名.要使用插值表达式,就把属性名包裹在双花括号里放进视图模板,如 {{}} eg: <h1>{{ name }}& ...
- 【转载】WEB架构师成长之路
本人也是coding很多年,虽然很失败,但也总算有点失败的心得,不过我在中国,大多数程序员都是像我一样,在一直走着弯路,如果想成为一个架构师,就必须走正确的路,否则离目标越来越远,正在辛苦工作的程序员 ...
- spring-boot自定义启动端口
有时候我们可能需要启动不止一个SpringBoot,而SpringBoot默认的端口号是8080,所以这时候我们就需要修改SpringBoot的默认端口了.修改SpringBoot的默认端口有两种方式 ...
- WPF中对XML的读写
XML(可扩展标记语言) 定义:用于标记电子文件使其具有结构性的标记语言,可以用来标记数据.定义数据类型,是一种允许用户对自己的标记语言进行定义的源语言. 写操作: XmlTextWriter wri ...