自定义 popWindow弹框 工具包

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了自定义 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;
        }

    }

}
View Code

 

 

   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)

    }
View Code

 

            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>
View Code

 

    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>
View Code
技术分享
//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>
View Code
技术分享
//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>
View Code

 

    That‘s all.

    If you have any qestions,please leave me messages .

 

以上是关于自定义 popWindow弹框 工具包的主要内容,如果未能解决你的问题,请参考以下文章

popwindow根据屏幕自适应位置弹出

自定义PopWindow模仿微信拍照上传头像

简单的自定义弹框

单例模式:自定义弹框

单例模式:自定义弹框

单例模式:自定义弹框