Refuse idle work, encapsulate a generic opupWindow

Keywords: Windows

https://juejin.im/post/5961e03e51882568b13c3308

In order to avoid repeating wheels, we usually encapsulate a common control. For example, this time, we need to use more popup windows in the project. If we need to write one by one, it will still be exhausting, and it is useless and meaningless. So, encapsulating a universal control saves us a lot of things besides letting colleagues see the direct brush 666.

Firstly, the effect map is shown.

1. How to use it

So, how much code do we normally need to configure a Popup Windows normal step? As follows:

PopupWindow popupWindow = new PopupWindow(this);
        View contentview = LayoutInflater.from(this).inflate(R.layout.popup_calendar,null);
        popupWindow =
                new PopupWindow(contentview,
                        ViewGroup.LayoutParams.WRAP_CONTENT,
                        ViewGroup.LayoutParams.WRAP_CONTENT,
                        true);
        //Settings Canceled
        popupWindow.setOutsideTouchable(true);
        popupWindow.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));


        //Location
        View rootview = LayoutInflater.from(this).inflate(R.layout.activity_main,null);
        popupWindow.showAtLocation(rootview,Gravity.CENTER,0,0);

Usually we need to implement the basic code above, Popup Windows to run, then we need to add animation, monitor back keys and so on, and then, when another need to be used, it has to be repeated, really desperate, at this time, the idea of encapsulation comes out of the head, then, after encapsulation, how? As follows:

CustomPopupWindow popupWindow = new CustomPopupWindow.Builder(this)
                        .setContentView(R.layout.popup_calendar)
                        .setwidth(LinearLayout.LayoutParams.WRAP_CONTENT)
                        .setheight(LinearLayout.LayoutParams.WRAP_CONTENT)
                        .setFouse(true)
                        .setOutSideCancel(true)
                        .setAnimationStyle(R.style.popup_anim_style)
                        .builder()
                        .showAtLocation(R.layout.activity_calendar, Gravity.CENTER,0,0);

Note that the showAtLocation above is in the middle of the display after the builder; you can also use showAsLocation() if you want it to be displayed in the corresponding position of a view.

And why behind builder()? Because I'm not sure whether to show the location of the parent layout or the corresponding location of a control when I use it, I encapsulate the code as follows:

/**
     * Display the location according to the parent layout
     * @param rootviewid
     * @param gravity
     * @param x
     * @param y
     * @return
     */
    public CustomPopupWindow showAtLocation(int rootviewid,int gravity,int x,int y){
        if (mPopupWindow != null){
            View rootview = LayoutInflater.from(mContext).inflate(rootviewid,null);
            mPopupWindow.showAtLocation(rootview,gravity,x,y);
        }
        return this;
    }

Of course, you can take it out.

Another common case is that we use popup window to act as dialog, so there is button to handle the corresponding logic. So how do you want to get the controls in Popup Windows? In order to facilitate the call, I also use the form of id here, so the call can be as long as this:

mMonthPicker = (PickerView) popupWindow.getItemView(R.id.picker_month);

Then you can use the mMonth Picker view to do things.

In this way, the control in the contentview is taken out and used. As long as you know the id, is it convenient and easy to use? Everyone knows all about ok when they encapsulate it.

Packaging ideas

Compared with encapsulating listview and recyclerview, this is relatively simple, that is, to observe the most original code, extract the most core unchanged; nothing more than the most important layout of Popup Windows.

  • cnotentview, in order to avoid layoutinflate every time, we encapsulate it as an id
  • Size, as we all know, Popup Windows does not have its own layout. After giving contentview, size should also be given.
  • Display location, show two functions, show AtLocation and show AsLocation. For convenience, we also write id, and of course we can pass in view.

Basically, as for other additions, such as animation, clicking on external cancel, listening for back keys, or simple contentview control events, are all changeable, so it is more comfortable to build in Builder mode. That's all. If you are not familiar with Builder, you can see my previous article:

Imitate common framework Builder to initialize data, how to install and force gracefully

3. Custom Popup Windows Completion Code

Below is the code I use now, you can refer to, according to their own needs to add or delete.

public  class CustomPopupWindow {
    private PopupWindow mPopupWindow;
    private View contentview;
    private static Context mContext;
    public CustomPopupWindow(Builder builder) {
        contentview = LayoutInflater.from(mContext).inflate(builder.contentviewid,null);
        mPopupWindow =
                new PopupWindow(contentview,builder.width,builder.height,builder.fouse);
        //Need to be combined with setBackGroundDrawable
        mPopupWindow.setOutsideTouchable(builder.outsidecancel);
        mPopupWindow.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
        mPopupWindow.setAnimationStyle(builder.animstyle);
    }
    /**
     * popup disappear
     */
    public void dismiss(){
        if (mPopupWindow != null){
            mPopupWindow.dismiss();
        }
    }
    /**
     * Get view based on id
     * @param viewid
     * @return
     */
    public View getItemView(int viewid){
        if (mPopupWindow != null){
            return this.contentview.findViewById(viewid);
        }
        return null;
    }
    /**
     * Display the location according to the parent layout
     * @param rootviewid
     * @param gravity
     * @param x
     * @param y
     * @return
     */
    public CustomPopupWindow showAtLocation(int rootviewid,int gravity,int x,int y){
        if (mPopupWindow != null){
            View rootview = LayoutInflater.from(mContext).inflate(rootviewid,null);
            mPopupWindow.showAtLocation(rootview,gravity,x,y);
        }
        return this;
    }
    /**
     * Get the view according to id and display it at the view location
     * @param targetviewId
     * @param gravity
     * @param offx
     * @param offy
     * @return
     */
    public CustomPopupWindow showAsLaction(int targetviewId,int gravity,int offx,int offy){
        if (mPopupWindow != null){
            View targetview = LayoutInflater.from(mContext).inflate(targetviewId,null);
            mPopupWindow.showAsDropDown(targetview,gravity,offx,offy);
        }
        return this;
    }
    /**
     * Display in different locations of targetview
     * @param targetview
     * @param gravity
     * @param offx
     * @param offy
     * @return
     */
    public CustomPopupWindow showAsLaction(View targetview,int gravity,int offx,int offy){
        if (mPopupWindow != null){
            mPopupWindow.showAsDropDown(targetview,gravity,offx,offy);
        }
        return this;
    }
    /**
     * Focus monitoring based on id
     * @param viewid
     * @param listener
     */
    public void setOnFocusListener(int viewid,View.OnFocusChangeListener listener){
        View view = getItemView(viewid);
        view.setOnFocusChangeListener(listener);
    }
    /**
     * builder class
     */
    public static class Builder{
        private int contentviewid;
        private int width;
        private int height;
        private boolean fouse;
        private boolean outsidecancel;
        private int animstyle;
        public Builder(Context context){
            mContext = context;
        }
        public Builder setContentView(int contentviewid){
            this.contentviewid = contentviewid;
            return this;
        }
        public Builder setwidth(int width){
            this.width = width;
            return this;
        }
        public Builder setheight(int height){
            this.height = height;
            return this;
        }
        public Builder setFouse(boolean fouse){
            this.fouse = fouse;
            return this;
        }
        public Builder setOutSideCancel(boolean outsidecancel){
            this.outsidecancel = outsidecancel;
            return this;
        }
        public Builder setAnimationStyle(int animstyle){
            this.animstyle = animstyle;
            return this;
        }
        public CustomPopupWindow builder(){
           return new CustomPopupWindow(this);
        }
    }
}

Posted by SN1P3R_85 on Fri, 14 Jun 2019 13:10:55 -0700