preface

Again yue four seasons, especially busy busy person interview, overtime, idle people is also a special idle, just like me, every stroke, idle write articles, do animation, at the same time it is constantly poured into a variety of new technology, driver software industry development, don’t worry, don’t try so hard, learn part, and extend skills. So without further ado, let me show you how it works.

The Github link has been opened by consensus

This is the native effect

This is what it looks like

Decomposition of animation

Animation decomposition is actually very important. If you want to imitate the animation and interaction effects of an App, you must carefully observe its interaction details to slow down each operation, and then write code according to this dynamic. Otherwise the final effect is not the same, it is not in vain. No more nonsense, code to see steps.

The first step is video original state analysis

As you can see, the initial state of the video is a VideoView (surfaceView or whatever), plus a list, up and down layout, but VideoView, it dynamically adjusts the width and height according to the size of the video, not fixed, let’s analyze the process

  1. In the first drop-down, if the video height does not reach the native height, then the following ListView cannot consume the touch event, and VideoView consumes the event, adjusting the video aspect ratio according to the current drop Y value
  2. The second case is if the ListView has slid a little bit and it’s pulling down, but the viewVideo hasn’t really reached the height, then the touch event is still consumed by the ListView, and when it slides to the top it intercepts the touch and passes it to VideoView
  3. In the third case, when the ListView slides down quickly, there will be a process of inertia. Even if the hand leaves the phone, the Listview is still sliding, which we call inertia sliding. When the inertia slides to the top, if the video height does not reach the original height, this time to adjust the video height according to the inertia value.

The second step is video slide process analysis

As can be seen from the figure above, when we drop down the video, the top left and right margin machine listView changes, and the videoView height also changes.

  1. In the drop-down, the left and right top bottom values of the margin are changing, and the videoView height is also changing. At the same time, the ListView is gradually disappearing into a white background, and the listView height is gradually decreasing. At the same time, it can be seen that the Z-axis has also changed. Maybe the picture isn’t clear enough to see the z-axis transformation
  2. When the ListView disappears, the videoView width changes and the controller appears. The VideoView width is still shrinking.
  3. When the minimum video hover level is reached, the whole view becomes more and more transparent when it is pulled down, while the entire layout slides down according to gestures.

The third step is video slide up process analysis

The upslide is the reverse of the slide, so I’m not going to go back too far.

Lu code

The main logic in the above, below I will be simple to the above logic analysis, the overall code to the old iron private message I can leave a message

How to distribute listView and VideoView in touch

Here I use a LinearLayout as the parent to assemble the two child Views, and then distribute the events according to the viewGroup’s dispatchTouchEvent method. There’s a lot of code on the web and I’m not going to go through it in detail, but there are a lot of things that I can optimize, so this is just a demo.

  • See if videoView is at its maximum and listView is at the top.
  • We can call addOnScrollListener () at the top to see if the listView is the first visible item * and see if the VideoView has reached its maximum value, depending on the width and height of the video. You can get it through Mediaplayer,
@override public Boolean dispatchTouchEvent(MotionEvent ev) {y = ev.gety (); int pointerId = ev.getPointerId(0); switch (ev.getAction()) {case MotionEvent.ACTION_DOWN:
                mDownY = ev.getY();
                Log.i(TAG, "dispatchTouchEvent: ACTION_DOWN " + mDownY);
                if (mVelocityTracker == null) {
                    mVelocityTracker = VelocityTracker.obtain();
                } else {
                    mVelocityTracker.clear();
                }
                mVelocityTracker.addMovement(ev);
                break;
            case MotionEvent.ACTION_MOVE:

                float dDownY = y - mDownY;

                Log.i(TAG, "dispatchTouchEvent: " + mDownY + "" + y);
                mVelocityTracker.addMovement(ev);
                mVelocityTracker.computeCurrentVelocity(1000);


                if((mDownY >= (layoutPVideo.getHeight() + layoutPVideo.getMarginTop())) && dDownY > 0 && layoutPVideo.getHeight() < OriginalHeight + 600&& (isList2Top)) {// Determine the range of clicks and the current video size. SetHeight ((int) (layoutVideo.getheight () + dDownY)); Log.i(TAG,"dispatchTouchEvent: xia " + dDownY);
                    mDownY = y;
                    return true;
                } else if((mDownY >= (layoutPVideo.getHeight() + layoutPVideo.getMarginTop())) && dDownY <= 0 && layoutPVideo.getHeight() >= OriginalHeight {// Adjust video view height layoutPVideo.setheight ((int) (layoutPVideo.getheight () + dDownY)); // We can add an elastic animation to make it smoother."dispatchTouchEvent: shang " + dDownY);
                    mDownY = y;
                    return true;
                }
                break;
            case MotionEvent.ACTION_UP:
                float yVelocity = VelocityTrackerCompat.getYVelocity(mVelocityTracker,
                        pointerId);
                Log.i("VelocityTrackerCompat"."Y velocity: " +
                        yVelocity);
                
                if(yVelocity >= 5685&&layoutpVideo.getheight () < originalHeight + 600) { }else {
                    Log.i(TAG, "headMoveToMax: not come in" + "" + (layoutPVideo.getHeight() < originalHeight + 600));
                }
                break;
            case MotionEvent.ACTION_CANCEL:
                mVelocityTracker.recycle();
                break;
        }


        return super.dispatchTouchEvent(ev);
    }

Copy the code

How to dynamically jump left and right margins and video width and height

Here I use a wrapper class to get the layoutParams of the current view, and then use touchEvent to get the sliding value to dynamically change the width, height and margin of the current view. This code is modified by the set Get method.

  • Step 1 Slide to adjust margin left, right, up, down, and videoView height.
  • The second step is to slide down to adjust the width of the VideoView
  • Step 3 Slide down to hide the whole view
 private void updateVideoView(int m, int originY) {

        canHide = false;
        if (mDetailView.getHeight() == 0) {
            if(layoutPVideoView.getMarginRight() <= videoWidthPx && 0 < originY) { int value = layoutPVideoView.getMarginRight() + originY * 9; // Accelerate the zoomif (value > videoWidthPx) {
                    value = (int) videoWidthPx;
                }
                float percent = (videoWidthPx - value) / videoWidthPx;
                if (0 > percent) {
                    percent = 0.f;
                }
                int videoHeight = (int) (videoMinHeightPx * (1 - percent));
                int videoMTop = (int) (allMinScrollY * (1 - percent));
                layoutPVideo.setMarginTop((int) (allScrollY + videoMTop));
                layoutPVideo.setHeight((int) (videoHeightPx - videoHeight));
                layoutPVideoView.setMarginRight(value);



                canHide = true;
                Log.i(TAG, "updateVideoView: "+isBottomMax);
                if (layoutPVideoView.getMarginRight() >= videoWidthPx) {
                    if (isBottomMax) {

                        layoutPVideo.setMarginTop(m);
                        float v = m - (allScrollY + allMinScrollY); Mvideoview. setAlpha(1.0F-V/swipePx2Dismiss);if (v >= swipePx2Dismiss) {
                            setVisibility(INVISIBLE); mVideoView.setAlpha(1f); }}}return; }// Reduce the right margin of the videoif (layoutPVideoView.getMarginRight() >= 0 && 0 > originY) {
                int value = layoutPVideoView.getMarginRight() + originY * 9;
//                if (0 > value) {
//                    value = 0;
//                }
                float percent = (videoWidthPx - value) / videoWidthPx;
                if (0 > percent) {
                    percent = 0.f;
                }
                int videoHeight = (int) (videoMinHeightPx * (1 - percent));
                int videoMTop = (int) (allMinScrollY * (1 - percent));
                layoutPVideo.setMarginTop((int) (allScrollY + videoMTop));
                layoutPVideo.setHeight((int) (videoHeightPx - videoHeight));
                layoutPVideoView.setMarginRight(value);
                return; }// Zoom in on the right margin of the videoif (layoutPVideoView.getMarginRight() >= 0 && originY > 0) {

                return; }// Minimize phase}if(layoutPVideo.getMarginTop() <= 0 && originY < 0) { m = 0; }// Maximization phasefloat percent = (allScrollY - m) / allScrollY;
        if (0 > percent) {
            percent = 0;
            return; } int videoHeight = (int) (originalHeight - (originalHeight - videoHeightPx) * (1 - percent)); int listHeight = (int) ((originListHeight) * (percent)); layoutPVideo.setMarginTop(m); layoutPVideo.setHeight(videoHeight); layoutPList.setMarginBottom((int) (marginBottomPx * (1 - percent))); layoutPList.setHeight(listHeight); layoutPCoverView.getView().setAlpha((1 - percent)); layoutPContainer.setMarginRight((int) (marginRLPx * (1 - percent))); layoutPContainer.setMarginLeft((int) (marginRLPx * (1 - percent))); int mr = (int) ((1f - percent) * marginPx); // Margin layoutpVideo.setz (Mr / 2); // Margin layoutpVideo.setz (Mr / 2); // This is the z-axis value, levitation effect}Copy the code

ending

I spent a couple of hours writing, hoping to bring the old iron people a store of knowledge rather than a waste of time. Not early not early off work, want to code of the old iron can be private message.