Android implements personalized ViewPager switching animation practices PageTransformer (compatible with less than Android3.0) and androidviewpager
Reprinted please indicate the source: bytes
I wrote a blog post: Android custom ViewPager creates an ever-changing picture switching effect. Some brothers suggested that ViewPager comes with a setPageTransformer used to set the switching animation ~
This blog post will:
1. describes how to use setPageTransformer to set a switching animation;
2. Custom PageTransformer to implement a personalized switching animation;
3. This method does not work in SDK11 or earlier versions. We will modify it to make it backward compatible.
Official example address: http://developer.android.com/training/animation/screen-slide.html interested can go to see ~~
Now, write the code ~~
2. Use setPageTransformer
First, we can quickly implement a traditional ViewPager EFFECT ~
1. layout File
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" > <android.support.v4.view.ViewPager android:id="@+id/id_viewpager" android:layout_width="fill_parent" android:layout_height="fill_parent" /></RelativeLayout>
2. MainActivity
package com.zhy.demo_zhy_08_viewpageranim;import java.util.ArrayList;import java.util.List;import android.app.Activity;import android.os.Bundle;import android.support.v4.view.PagerAdapter;import android.support.v4.view.ViewPager;import android.view.View;import android.view.ViewGroup;import android.view.Window;import android.widget.ImageView;import android.widget.ImageView.ScaleType;public class MainActivity extends Activity{private ViewPager mViewPager;private int[] mImgIds = new int[] { R.drawable.guide_image1,R.drawable.guide_image2, R.drawable.guide_image3 };private List<ImageView> mImageViews = new ArrayList<ImageView>();@Overrideprotected void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);requestWindowFeature(Window.FEATURE_NO_TITLE);setContentView(R.layout.activity_main);initData();mViewPager = (ViewPager) findViewById(R.id.id_viewpager);mViewPager.setAdapter(new PagerAdapter(){@Overridepublic Object instantiateItem(ViewGroup container, int position){container.addView(mImageViews.get(position));return mImageViews.get(position);}@Overridepublic void destroyItem(ViewGroup container, int position,Object object){container.removeView(mImageViews.get(position));}@Overridepublic boolean isViewFromObject(View view, Object object){return view == object;}@Overridepublic int getCount(){return mImgIds.length;}});}private void initData(){for (int imgId : mImgIds){ImageView imageView = new ImageView(getApplicationContext());imageView.setScaleType(ScaleType.CENTER_CROP);imageView.setImageResource(imgId);mImageViews.add(imageView);}}}
Okay, so a traditional ViewPager is implemented ~~ You should not feel any stranger to the above Code ~ You do not need to map the running effect ~~
3. PageTransformer
ViewPager has a method called:
SetPageTransformer (boolean reverseDrawingOrder, PageTransformer transformer) is used to set the animation effect during ViewPager switching. google also provides two official examples.
You only need to call setPageTransformer in the above Code to add the animation switching effect ~~ The following demonstrates the code and Running Effect of google's two PageTransformer versions.
1. DepthPageTransformer
public class DepthPageTransformer implements ViewPager.PageTransformer { private static final float MIN_SCALE = 0.75f; public void transformPage(View view, float position) { int pageWidth = view.getWidth(); if (position < -1) { // [-Infinity,-1) // This page is way off-screen to the left. view.setAlpha(0); } else if (position <= 0) { // [-1,0] // Use the default slide transition when moving to the left page view.setAlpha(1); view.setTranslationX(0); view.setScaleX(1); view.setScaleY(1); } else if (position <= 1) { // (0,1] // Fade the page out. view.setAlpha(1 - position); // Counteract the default slide transition view.setTranslationX(pageWidth * -position); // Scale the page down (between MIN_SCALE and 1) float scaleFactor = MIN_SCALE + (1 - MIN_SCALE) * (1 - Math.abs(position)); view.setScaleX(scaleFactor); view.setScaleY(scaleFactor); } else { // (1,+Infinity] // This page is way off-screen to the right. view.setAlpha(0); } }}
Call code:
mViewPager.setPageTransformer(true, new DepthPageTransformer());
Effect:
2. ZoomOutPageTransformer
Package com. zhy. view; import android. annotation. suppressLint; import android. support. v4.view. viewPager; import android. util. log; import android. view. view; public class ZoomOutPageTransformer implements ViewPager. pageTransformer {private static final float MIN_SCALE = 0.85f; private static final float MIN_ALPHA = 0.5f; @ SuppressLint ("NewApi") public void transformPage (View view, float position) {int pageWidth = View. getWidth (); int pageHeight = view. getHeight (); Log. e ("TAG", view + "," + position + ""); if (position <-1) {// [-Infinity,-1) // This page is way off-screen to the left. view. setAlpha (0);} else if (position <= 1) // slide page a to page B; page a from 0.0-1; page B from 1 ~ 0.0 {// [-] // Modify the default slide transition to shrink the page as wellfloat scaleFactor = Math. max (MIN_SCALE, 1-Math. abs (position); float vertMargin = pageHeight * (1-scaleFactor)/2; float horzMargin = pageWidth * (1-scaleFactor)/2; if (position <0) {view. setTranslationX (horzMargin-vertMargin/2);} else {view. setTranslationX (-horzMargin + vertMargin/2);} // Scale the page down (between MIN_SCALE and 1) view. setScaleX (scaleFactor); view. setScaleY (scaleFactor); // Fade the page relative to its size. view. setAlpha (MIN_ALPHA + (scaleFactor-MIN_SCALE)/(1-MIN_SCALE) * (1-MIN_ALPHA);} else {// (1, + Infinity] // This page is way off-screen to the right. view. setAlpha (0 );}}}
Call code:
mViewPager.setPageTransformer(true, new ZoomOutPageTransformer());
Effect:
They are all on the google official website. Our test images will be posted below 3.0 compatible, otherwise they will be repeated ~~
Adding a switch for ViewPager is not a happy line of code, but it is not compatible with versions earlier than 3.0. The comment of this method is written:
Setting a PageTransformer prior to Android 3.0 (API 11) will have no effect. setting this method in versions earlier than 3.0 has no effect, then let's see how to make it compatible with versions earlier than 3.0.
3. Version backward compatibility 1. Reasons for incompatibility
First, let's take a look at why it is incompatible. What about 3.0 or lower?
Looking at the two sample codes above, the View animation in the Code uses the property animation, and the property animation is only available in 3.0. Therefore, it must be incompatible with less than 3.0 ~
We will first introduce nineoldandroids so that the animation can run below 3.0:
Modify DepthPageTransformer
Package com. zhy. view; import com. nineoldandroids. view. viewHelper; import android. annotation. suppressLint; import android. support. v4.view. viewPager; import android. view. view; public class DepthPageTransformer implements ViewPager. pageTransformer {private static final float MIN_SCALE = 0.75f; public void transformPage (View view, float position) {int pageWidth = view. getWidth (); if (position <-1) {// [-Infini Ty,-1) // This page is way off-screen to the left. // view. setAlpha (0); ViewHelper. setAlpha (view, 0);} else if (position <= 0) // slide page a to page B; page a from 0.0-1; page B from 1 ~ 0.0 {// [-] // Use the default slide transition when moving to the left page // view. setAlpha (1); ViewHelper. setAlpha (view, 1); // view. setTranslationX (0); ViewHelper. setTranslationX (view, 0); // view. setScaleX (1); ViewHelper. setScaleX (view, 1); // view. setScaleY (1); ViewHelper. setScaleY (view, 1);} else if (position <= 1) {// (0, 1] // Fade the page out. // view. setAlpha (1-position); ViewHelper. setAlpha (view, 1-position); // Counteract the default slide transition // view. setTranslationX (pageWidth *-position); ViewHelper. setTranslationX (view, pageWidth *-position); // Scale the page down (between MIN_SCALE and 1) float scaleFactor = MIN_SCALE + (1-MIN_SCALE) * (1-position ); // view. setScaleX (scaleFactor); ViewHelper. setScaleX (view, scaleFactor); // view. setScaleY (1); ViewHelper. setScaleY (view, scaleFactor);} else {// (1, + Infinity] // This page is way off-screen to the right. // view. setAlpha (0); ViewHelper. setAlpha (view, 1 );}}}
It's easy to set all the property animations with ViewHelper. Now we can go to machines under 3.0 to run it, and we find it still has no effect ~~~
Why?
Let's take a look at the source code of setPageTransformer:
public void setPageTransformer(boolean reverseDrawingOrder, PageTransformer transformer) { if (Build.VERSION.SDK_INT >= 11) { final boolean hasTransformer = transformer != null; final boolean needsPopulate = hasTransformer != (mPageTransformer != null); mPageTransformer = transformer; setChildrenDrawingOrderEnabledCompat(hasTransformer); if (hasTransformer) { mDrawingOrder = reverseDrawingOrder ? DRAW_ORDER_REVERSE : DRAW_ORDER_FORWARD; } else { mDrawingOrder = DRAW_ORDER_DEFAULT; } if (needsPopulate) populate(); } }
I finally found the cause. In this method, I determined that the animation would take effect if it was later than 11 ~~
No way. To be compatible, you must modify the source code of ViewPager ~~
2. Perfect downward compatibility
We copy the source code of ViewPager to our project, change the name to ViewPagerCompat, and comment out the SDK version to judge the sentence.
Public class ViewPagerCompat extends ViewGroup {
public void setPageTransformer(boolean reverseDrawingOrder, ViewPager.PageTransformer transformer) {// if (Build.VERSION.SDK_INT >= 11) { final boolean hasTransformer = transformer != null; final boolean needsPopulate = hasTransformer != (mPageTransformer != null); mPageTransformer = transformer; setChildrenDrawingOrderEnabledCompat(hasTransformer); if (hasTransformer) { mDrawingOrder = reverseDrawingOrder ? DRAW_ORDER_REVERSE : DRAW_ORDER_FORWARD; } else { mDrawingOrder = DRAW_ORDER_DEFAULT; } if (needsPopulate) populate(); } }
...
}
Note that all PageTransformer uses ViewPager. PageTransformer
Change ViewPager in the project to ViewPagerCompat. Remember to modify the layout file and set ViewPager in MainActivity to ViewPagerCompat.
We tested the effect on the simulator 2.3.3:
As you can see, our switching animation runs perfectly on the 2.3.3 machine ~~ So happy ~~ It doesn't matter if the source code of ViewPager is not available. I will add the source code of ViewPager to the source code download at the end of the article so that you can test it as much as possible ~~
Of course, compatibility alone cannot satisfy our curiosity. Are we compatible? Can we only use the example animation provided by Google ~~ What about our powerful innovations ~~ Next we will analyze the setPageTransformer method, and then design a personalized animation switching effect.
4. Custom PageTransformer animation for personalized Switching
public interface PageTransformer { /** * Apply a property transformation to the given page. * * @param page Apply the transformation to this page * @param position Position of page relative to the current front-and-center * position of the pager. 0 is front and center. 1 is one full * page position to the right, and -1 is one page position to the left. */ public void transformPage(View page, float position); }
We can see that this interface only has one method. The first is our view, and the second is position ~~
When we slide, it will print the changes of each View that survive in ViewPager and their position ~~ Note that every one is used, so we recommend that you do not only use log position. Otherwise, you will find the output inexplicable ~~
The possible value of position is as follows:
[-Infinity,-1) No more
(1, + Infinity] No more
[-1, 1]
For more information, see ~~
Suppose that ViewPager slides out of page B on page A, then:
The position change on page A is (0,-1]
The position change on page B is [1, 0].
Knowing the position changes when we move ~~ Then we begin to design the switching effect of our personality;
For the official example, if there is a change in transparency, offset, and scaling, we are going to make a difference. Our change angle is rotation;
The approximate effect is as follows:
The following code is analyzed:
We set the rotation center of the View:
ViewHelper. setinclutx (view, view. getMeasuredWidth () * 0.5f );
ViewHelper. setequalty (view, view. getMeasuredHeight ());
Still ViewPager slides out of page B on page
Page A should be offset from 0 degrees to-20 degrees during the Sliding Process, and page B should be offset from 20 degrees to 0 degrees during the sliding process.
Integration
The position change on page A is (0,-1]
The position change on page B is [1, 0].
The rotation angle is: mRot = (20 * position); page A mRot: 0 ,~ -20; Page B mRot: 20 ~ 0;
It instantly seems easy:
Complete code:
Package com. zhy. view; import com. nineoldandroids. view. viewHelper; import android. annotation. suppressLint; import android. support. v4.view. viewPager; import android. util. log; import android. view. view; public class RotateDownPageTransformer implements ViewPager. pageTransformer {private static final float ROT_MAX = 20366f; private float mRot; public void transformPage (View view, float position) {Log. e ("TAG", view + "," + Position + ""); if (position <-1) {// [-Infinity,-1) // This page is way off-screen to the left. viewHelper. setRotation (view, 0);} else if (position <= 1) // slide page a to page B; page a is from 0.0 ~ -1; page B ranges from 1 ~ 0.0 {// [-] // Modify the default slide transition to shrink the page as wellif (position <0) {mRot = (ROT_MAX * position); ViewHelper. setmediatx (view, view. getMeasuredWidth () * 0.5f); ViewHelper. setpolicty (view, view. getMeasuredHeight (); ViewHelper. setRotation (view, mRot);} else {mRot = (ROT_MAX * position); ViewHelper. setmediatx (view, view. getMeasuredWidth () * 0.5f); ViewHelper. setpolicty (view, view. getMeasuredHeight (); ViewHelper. setRotation (view, mRot);} // Scale the page down (between MIN_SCALE and 1) // Fade the page relative to its size .} else {// (1, + Infinity] // This page is way off-screen to the right. viewHelper. setRotation (view, 0 );}}}
You are not mistaken. The code in if else is the same. It is not merged for better understanding ~~~
At this point, we have introduced the switching effect from setPageTransformer, to modifying ViewPager to backward compatibility until we have defined our own personality ~~
You can use your creativity to make a variety of magical animation effects. OK, that's it!
If you prefer custom ViewPager, go to: Android custom ViewPager to create an ever-changing image switching effect.
Download source code
Bytes ---------------------------------------------------------------------------------------------------------
Some of the bloggers have already been online. If you do not like boring text, stamp it (for initial record, we look forward to your support ):
1. High imitation 5.2.1 main interface and message reminder
2. High imitation QQ5.0 slide
Can I customize the animation type and time of ViewPager in android?
Does the view switching animation refer to the animation when one view jumps to another view?
Android ViewPager enables activity page Switching
In the viewpage, You can intercept the touch event.
However, if the viewpage occupies all the space of the current external page, the external viewpage cannot be moved over.