Preface:
Originally is in the cool dog music to see this effect, can not see the source of the cool dog, so according to their own ideas to write a. Hope to be useful to everyone, of course, more hope that there are high-level people to help improve, because there are still some problems to be optimized.
Effect:
This is a kind of animation in the activity switch, you can touch the page to drag and realize the page jump.
The following effects:
Ideas and implementation process:
There are two approaches, each with its advantages and disadvantages.
Let’s look at the first:
Get the activity’s contentView and animate it in a touch event. But there are two shortcomings:
First: you can’t use the layout of the child view to listen to touch events, the reason is very simple, animation triggered after the activity’s view is moving, listening to the event itself view is also moving, coordinate data acquisition chaos, animation all kinds of jitter, I have practiced, we can try.
Second, once the child view is excluded from listening for touch events, the onTouchEvent(MotionEvent Event) method can only be overwritten to allow the entire window to listen for touch events without interfering with the various controls in the activity. However, to use this method, you must ensure that none of the controls on the page intercept or consume touch events, otherwise the events will not reach here. This makes it cumbersome for controls to handle onClick() and so on, and makes it very, very difficult to extract a tool class. So it’s not recommended unless you’re just trying to achieve this.
Of course, this is my limit in their own level of conclusion, I also hope to have god to give advice, point out a bright road. Because the next way of thinking although make up for the above two shortcomings, but really around a small circle, also have flaws ah!
Since it’s not ideal to operate the activity’s contentView directly, I’ll make a copy of it, and I’ll operate yours. So he started going around in this little circle: Get the contentView, get its bitmap, construct an ImageView and place it in the bitmap, use WindowManager to add the ImageView, select the specified control to listen for the Touch event, make the contentView invisible, Processing animation for ImageView… Is it a little circle? Is it a bit of a hassle? There is no way, I can only think of this method to deal with this problem, can still be used, once again entreated to see the god to help guide the maze! Thanks a lot!
The idea is probably like this, let’s look at the implementation process, basically is the code.
Create a utility class for Responsibility 1: Get the content of the activity image and put it into a Bitmap.
/** * Public bitmap getRootViewBitmap() {rootView = activity.getWindow().getDecorView().findViewById(android.R.id.content); Log.d(TAG, "root = " + rootView + " ,width = " + rootView.getWidth() + " ,height = " + rootView.getHeight()); rootView.setDrawingCacheEnabled(true); Bitmap rootViewBitmap = rootView.getDrawingCache(); return rootViewBitmap; }Copy the code
Responsibility 2: Create an ImageView, set the parameters, and add it to the window.
Private void addImage() {rotateImageView = new ImageView(activity); rotateImageView.setImageBitmap(rootBitmap); rotateImageParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN; rotateImageParams.format = PixelFormat.TRANSLUCENT; Rotateimageparams.width = rootView.getwidth (); rotateImageParams.width = rootView.getwidth (); rotateImageParams.height = rootView.getHeight(); rotateImageParams.verticalMargin = stationBarHeigth; / / distance at the top of the height of the height of a status bar rotateImageView. SetRotation (0); rotateImageView.setPivotX(rootView.getWidth() * 1f / 2f); rotateImageView.setPivotY(rootView.getHeight() * 5f / 4f); activity.getWindow().getWindowManager().addView(rotateImageView, rotateImageParams); }Copy the code
Responsibility 3: Handle touch events.
The touch event calculates the rotation Angle (0 to 90 degrees) based on the horizontal move distance, and determines which animation to execute based on the current Angle detected after lifting the finger. If the Angle is small, rotate back to the original state. If the Angle is large, rotate outward until it disappears, then finish the page.
/** * You need to set the touch slide listener in the corresponding activity, */ public view.onTouchListener OnTouchListener = new view.onTouchListener () {@override public Boolean onTouch(View v, MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: touchStartX = event.getX(); touchStartY = event.getY(); addImage(); new Thread(rootViewInvisibleDelay).start(); Log.i(TAG, "ACTION_DOWN touchStartX = " + touchStartX + " ,touchStartY = " + touchStartY); break; case MotionEvent.ACTION_MOVE: touchMoveX = event.getX(); touchMoveY = event.getY(); Log.i(TAG, "ACTION_MOVE touchStartX = " + touchStartX + " ,touchMoveX = " + touchMoveX + " ,touchStartY = " + touchStartY + " ,touchMoveY = " + touchMoveY); float moveLength = touchMoveX - touchStartX; if (! rotateOpen && moveLength > 10 && Math.abs(touchMoveY - touchStartY) < 50) { rotateOpen = true; } if (rotateOpen) { float rotateAngle = getRotateAngle(moveLength); rotateImageView.setRotation(rotateAngle); activity.getWindow().getWindowManager().updateViewLayout(rotateImageView, rotateImageParams); } break; case MotionEvent.ACTION_UP: rotateOpen = false; float finalRotate = rotateImageView.getRotation(); ValueAnimator valueAnimator; Log.v(TAG, "ACTION_UP finalRotate = " + finalRotate); if (finalRotate < 20) { valueAnimator = ValueAnimator.ofFloat(finalRotate, 0); rootView.setTag(resume); } else {valueAnimator = valueanimator. ofFloat(finalRotate, 90); rootView.setTag(finish); } / / logo, end page valueAnimator. SetDuration (300); valueAnimator.addUpdateListener(animatorUpdateListener); valueAnimator.addListener(animatorListener); valueAnimator.start(); break; } return true; }};Copy the code
Listen to two animations:
/** * Animation is in progress, Listen. * / ValueAnimator AnimatorUpdateListener AnimatorUpdateListener = new ValueAnimator. AnimatorUpdateListener () { @Override public void onAnimationUpdate(ValueAnimator animation) { float rotateAngle = (float) animation.getAnimatedValue(); rotateImageView.setRotation(rotateAngle); activity.getWindow().getWindowManager().updateViewLayout(rotateImageView, rotateImageParams); }}; / * * * end of animation began, cancel, and repeat. Listen * / Animator AnimatorListener AnimatorListener = new Animator. AnimatorListener () {@ Override public void onAnimationStart(Animator animation) { } @Override public void onAnimationEnd(Animator animation) { int tag = (int) rootView.getTag(); if (tag == resume) { rootView.setVisibility(View.VISIBLE); new Thread(removeImgDelay).start(); } else if (tag == finish) { activity.finish(); } } @Override public void onAnimationCancel(Animator animation) { } @Override public void onAnimationRepeat(Animator animation) { } };Copy the code
Using this class is also easy. In the Activity, the following lines of code are set up.
One important thing to note is that you should never construct an object inside the onCreate() method, the layout is not initialized, what size can not be measured, there will be no effect.
This can be done in the onWindowFocusChanged method.
private ActivityRotateAnimationUtil activityRotateAnimationUtil;
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
activityRotateAnimationUtil = new ActivityRotateAnimationUtil(this);
bgImage.setOnTouchListener(activityRotateAnimationUtil.onTouchListener);
}Copy the code
Then, there is the problem that at the beginning and end of the animation, we have to add a copy of the ImageView while making the source contentView disappear. If we do this together, the page always flashes. Even if you put the code that adds copies first, you can’t because the interval is too short, and adding copies takes a certain amount of time. So there’s a two-step delay between these two parts of the code, and that’s why those two seemingly redundant child threads exist. I’m still looking for a better solution…
One more note, which is also important: Use this tool, you need to set up the theme of the activity of the android: theme = “@ android: style/theme. Translucent”, or you have other way, let the activity background transparent, otherwise, the animation is executed, The background color will block the activity page below, which is usually black, and the effect will be greatly reduced.
To sum up, it’s not that difficult to achieve this effect. It’s the details that matter. And after this effect is realized, push along, what translation ah, zoom ah, gradient ah, including some other attributes can be treated in the same way, the space to play is relatively large, depending on the imagination is not enough, can design a more gorgeous effect.
Finally, put a utility class source resources: download.csdn.net/detail/chen…
Welcome clap brick, welcome give directions!