Custom Controls (Imitate Popup Windows)

Keywords: Windows Android github

Implementation of Custom Control

In this paper, we discuss the implementation of native Popup Windows, customize the implementation of imitating Popup Windows style and pay attention to details.
Development based on Android Studio API 23
- Native Popup Window Style Implementation
- Custom Implementation of Popup-like Windows
- concluding remarks

Implementation of native Popup Windows

Implementing ideas in Popup Windows:

Prerequisite: Draw PopupWindow in a layout center and set the root layout background to be translucent --"to achieve a Dialog-like style

1. Pop-up must have a corresponding style View

  View view = LayoutInflater.from(context).inflate(R.layout.public_pop, null);

2. Bullet window must be set wide and high, optional settings appear and hide animation

          PopupWindow window = new PopupWindow(view, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT, isForce);

 window.setAnimationStyle(R.style.pop_style_fade);

3. Click Event Processing of Bullet Window

//Here we must pay attention to setting the click event of the root layout of the content to null, otherwise the click content layout pop will disappear, and we must use the return key of the real machine to test.

//When the requirement disappears for clicking on the outside of Popup Window
//To make Popup Windows disappear by clicking outside of Popup Windows, you need to call
            window.setBackgroundDrawable(new ColorDrawable(0));
            window.setOutsideTouchable(false);
            window.setFocusable(true);
             contentLayout.setOnClickListener(null);
            //Implement click events for root layout, click externally to disappear
            parentLayout.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                   window.dismiss();
                }
            });
//When the requirement does not disappear for clicking on the outside of Popup Window, click Back to Exit Procedure - "Application Scenario: Forced Update
//Equivalent to the entire root layout always gaining focus will not be released
            window.setFocusable(true);
            parentLayout.setFocusable(true);
            parentLayout.setFocusableInTouchMode(true);
            parentLayout.setOnKeyListener(new View.OnKeyListener() {
                @Override
                public boolean onKey(View v, int keyCode, KeyEvent event) {
                    if (keyCode == KeyEvent.KEYCODE_BACK){
                         window.dismiss();
                        System.exit(0);
                        return true;
                    }

                    return false;
                }
            });

4. Display the current interface

//The first parameter is the root layout in activity
 window.showAtLocation(anchorLayout, Gravity.CENTER, 0, 0);

An original OpupWindow can be displayed. The design effect is as follows:

Custom Implementation of Popup-like Windows

Requirements premise: using popup window can not simply slide in and out from which control of the current interface (need to calculate height and need to achieve animation effect in the code alone, the process is more cumbersome and error-prone).

Ideological achievements:
1 Requires View of the current interface to open and close custom animations

2. The Object Animator needs to be implemented to turn on animation and off animation __________

3. Click events need to be implemented (for internal item post-click response to close pop operations), and exposed methods of opening and closing are called externally (for handling some external click events)

At the same time, you need to expose a boolean object for external judgment of the current state

To achieve the premise, requirement and key:

Prerequisite: Ensure the uniqueness of this object in the current activity

Requirements: Use build to initialize the current data using the dialog design style --"AlertDialog.Builder builder=new AlertDialog.Builder(this); // Get the constructor first

Key: 1.
Use public static class in custom controls to pass initialized objects - "context" and current animation interface - "return new" to initialize objects in the current object initialization object
2.
The current interface needs a FrameLayout -: Fill the custom View object into the current interface (Note: This must be the frame Layout in the layout, not the root layout, and the filled FrameLayout needs to be sized)

code block

//This class refers to the content of custom controls on GitHub
public class EyepetizerMenuAnimation implements View.OnClickListener {

    private View mEyepetizerMenuView;
    private Context mContext;

    public static  ObjectAnimator mMenuOpenAnimation;
    public static  ObjectAnimator mMenuCloseAnimation;

    private DecelerateInterpolator mInterpolator;

    public static boolean mIsMenuClose = true;
    private static final String TRANSLATION = "translationY";


    public EyepetizerMenuAnimation(EyepetizerMenuBuilder builder) {
        this.mContext = builder.context;
        this.mEyepetizerMenuView = builder.eyepetizerMenuView;
        this.mInterpolator = new DecelerateInterpolator();
        this.mMenuOpenAnimation = buildMenuOpenAnimation();
        this.mMenuCloseAnimation = buildMenuCloseAnimation();
            mEyepetizerMenuView.setVisibility(View.GONE);
    }

    @Override
    public void onClick(View v) {
        if (mIsMenuClose) {
            open();
        }else {
            close();
        }
    }

    public static  void open() {
        mIsMenuClose = false;
        AnimatorSet set = new AnimatorSet();
        set.playTogether( mMenuOpenAnimation);
        set.start();
    }

    public static  void close() {
        mIsMenuClose = true;
        AnimatorSet set = new AnimatorSet();
        set.playTogether( mMenuCloseAnimation);//mActionMenuAnimation
        set.start();

    }

    private ObjectAnimator buildMenuOpenAnimation() {
        ObjectAnimator menuOpenAnimation = ObjectAnimator.ofFloat(
                mEyepetizerMenuView, TRANSLATION, -Utils.getScreenHeight(mContext), 0);
        menuOpenAnimation.setInterpolator(mInterpolator);
        menuOpenAnimation.setDuration(350);
        menuOpenAnimation.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationStart(Animator animation) {
                super.onAnimationStart(animation);
                mEyepetizerMenuView.setVisibility(View.VISIBLE);
            }
        });
        return menuOpenAnimation;
    }

    private ObjectAnimator buildMenuCloseAnimation() {
        ObjectAnimator menuCloseAnimation = ObjectAnimator.ofFloat(
                mEyepetizerMenuView, TRANSLATION, 0, -Utils.getScreenHeight(mContext));
        menuCloseAnimation.setInterpolator(mInterpolator);
        menuCloseAnimation.setDuration(350);
        menuCloseAnimation.addListener(new AnimatorListenerAdapter() {

            @Override
            public void onAnimationEnd(Animator animation) {
                super.onAnimationEnd(animation);
                mEyepetizerMenuView.setVisibility(View.GONE);
            }
        });
        return menuCloseAnimation;
    }

    public static class EyepetizerMenuBuilder {

        private View eyepetizerMenuView;
        private Context context;
        public EyepetizerMenuBuilder(Context context, View eyepetizerMenuView) {
            this.eyepetizerMenuView = eyepetizerMenuView;
            this.context = context;
        }

        public EyepetizerMenuAnimation build() {
            return new EyepetizerMenuAnimation(this);
        }

    }

}

Add view to activity

//FrameeLayout cannot be laid out for the root, but is another frame Layout used for filling in the layout.
  FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
                Utils.getScreenHeight(getActivity()) * 3 / 5);
        root_fl.setLayoutParams(layoutParams);
        mEyepetizerMenuView = LayoutInflater.from(getActivity()).inflate(R.layout.layout_captail_pop_item, null);

        mEyepetizerMenuView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //Truncate transparent background click events
            }
        });
        root_fl.addView(mEyepetizerMenuView);
        new EyepetizerMenuAnimation.EyepetizerMenuBuilder(
                getActivity(), mEyepetizerMenuView)
                .build();

        //After adding, you can close the menu.
          EyepetizerMenuAnimation.close();
        //After adding, you can open the menu.
          EyepetizerMenuAnimation.open();

Concluding remarks

Native Popup Windows meets all the basic requirements, but when the sliding-in and sliding-out requirements arise, many novices will be highly hidden and confused by computation and can not be implemented by Dialog, because the interface is partially translucent when Popup Windows pops up. Considering a variety of factors, we need to customize an animation in order to adapt to different interfaces and the same animation situation --"using linkage mode (that is, the interface is imported from the outside, and the internal interface is acquired for animation effect (the internal interface only controls the opening and closing of the interface). I am accustomed to using Dialog instead of PopupWindow for general requirements. Personally, I feel that Dialog is better for use. See the Custom Dialog for more details:
http://blog.csdn.net/wyh_healer/article/details/54891235

Posted by rkstevens on Sat, 23 Mar 2019 06:18:52 -0700