前言:因为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弹框 工具包的更多相关文章

  1. JavaScript实现自定义alert弹框

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAh0AAAFkCAYAAACEpYlzAAAfj0lEQVR4nO3dC5BddZ0n8F93pxOQCO

  2. CodePush自定义更新弹框及下载进度条

    CodePush 热更新之自定义更新弹框及下载进度 先来几张弹框效果图 非强制更新场景 image 强制更新场景 image 更新包下载进度效果 image 核心代码 这里的热更新Modal框,是封装 ...

  3. 自定义alert弹框,title不显示域名

    问题: 系统默认的alert弹框的title会默认显示网页域名 解决办法: (修改弹框样式) (function() { window.alert = function(name) { $(" ...

  4. WPF 如何自定义一个弹框

    ------------吾亦无他,唯手熟尔,谦卑若愚,好学若饥------------- 简述: 手工以原生Grid的方式,自定义了一个仿弹窗效果,优点可以自定义,缺点需要自己实现以及维护整个弹窗的效 ...

  5. 自定义alert弹框,title不显示域名(重写alert)

    问题: 系统默认的alert弹框的title会默认显示网页域名 解决办法: (修改弹框样式) (function() { window.alert = function(name) { $(" ...

  6. swift4.2 - 一个自定义view弹框

    import UIKit /* * 注册协议view:没找到 UI原图,咱不实现 */ class JYRegisterProtocolView: UIView { /// 点击同意协议的回调 pri ...

  7. 自定义alert弹框

    /**************** UIAlertControllerStyleAlert *************************/ /*创建一个 可以自定义文字颜色和字体大小的IAler ...

  8. vue自定义插件-弹框

    <template> <transition name="msgbox"> <div v-if="show" class=&quo ...

  9. vue 自定义动态弹框

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

随机推荐

  1. 《C#高效编程》读书笔记06-理解几个等同性判断之间的关系

    当创建自定义类型时(无论是class还是struct),应为类型定义"等同性"的含义.C#提供了4种不同的函数来判断两个对象是否"相等": public sta ...

  2. DB2常用函数详解

    (一) 字符串函数 VALUE函数  语法:VALUE(EXPRESSION1,EXPRESSION2) VALUE函数是用返回一个非空的值,当其第一个参数非空,直接返回该参数的值,如果第一个参数为空 ...

  3. linux 下源码编译环境配置

    yum install -y apr* autoconf automake bison bzip2 bzip2* compat* cpp curl curl-devel \ fontconfig fo ...

  4. TestNG并发测试包

    https://www.yiibai.com/testng/basic-annotations.html

  5. Git 推送和删除标签

    事实上Git 的推送和删除远程标签命令是相同的,删除操作实际上就是推送空的源标签refs:git push origin 标签名相当于git push origin refs/tags/源标签名:re ...

  6. Object.keys 函数 (JavaScript)

    Object.keys 函数 (JavaScript) 返回对象的可枚举属性和方法的名称. 在实际开发中,我们有时需要知道对象的所有属性,原生js给我们提供了一个很好的方法:Object.keys() ...

  7. hangfire使用

    1 . NuGet 命令行执行 Install-Package Hangfire2.首先在ConfigureServices 方法中注册服务: services.AddHangfire(r=>r ...

  8. 爬虫爬取代理IP池及代理IP的验证

    最近项目内容需要引入代理IP去爬取内容. 为了项目持续运行,需要不断构造.维护.验证代理IP. 为了绕过服务端对IP 和 频率的限制,为了阻止服务端获取真正的主机IP. 一.服务器如何获取客户端IP ...

  9. Android(java)学习笔记87:Android音视频MediaRecorder用法

    1. Android语音录制可以通过 MediaRecorder 和 AudioRecorder:  MediaRecorder本来是多媒体录制控件,可以同时录制视频和语音,当不指定视频源时就只录制语 ...

  10. 【洛谷1501】[国家集训队] Tree II(LCT维护懒惰标记)

    点此看题面 大致题意: 有一棵初始边权全为\(1\)的树,四种操作:将两点间路径边权都加上一个数,删一条边.加一条新边,将两点间路径边权都加上一个数,询问两点间路径权值和. 序列版 这道题有一个序列版 ...