Android custom ViewPager for ever-changing image Switching

Source: Internet
Author: User

Android custom ViewPager for ever-changing image Switching

 

I remember seeing the ViewPager control for the first time. In an instant, the main interface for doing things is ViewPager, and the image switching also discards ImageSwitch and so on. After a long time, the switching effect of ViewPager is boring, resulting in aesthetic fatigue ~~ We need to change. Today we will teach you how to change the effect of ViewPager switching to achieve personalized image switching ~~

Take a look at the effect of image switching:

Is it more personalized than traditional ones ~~ In fact, it is very simple. After learning this blog, you can customize the switching effect and make various crazy switching ~~

1. pre-production analysis

Observe that the animation is actually changed during the switch. It's easy to get the current View and the next View during the switch, and then add the animation. Good,Step 1: Obtain the current View and the destination View to which the user switches.

Let's take a look at it. If the current View and the target View are used, we need to slide slowly for the animation, preferably based on the user's gesture. For example, when a user slides, the target image appears slowly and gradually increases based on the user's sliding distance. Good,Step 2: design the Gradient Changes of the animation.

After analysis, we have summarized the two steps. Next we will start to build them step by step ~~~

2. Obtain the current View and the destination View to which the user switches.

ViewPager also needs to listen to user gestures, so it certainly provides a method. So looking at the ViewPager method, we found a method called onPageScrolled (int position, float positionOffset, int positionOffsetPixels ~~

That's right. This method is called during Page scrolling ~

The following describes the parameters:

Test results:

When the first and last pages are not displayed, slide to the next page. position indicates the current page position. Move to the previous page. position indicates the current page-1.

PositionOffset slides to the next page, and changes in the range [); slides to the previous page: (1, 0]

PositionOffsetPixels this is similar to positionOffset: Sliding to the next page, [0, width) interval changes; sliding to the previous page: (width, 0] interval changes

On the first page: slide to the previous page position = 0, the other is basically 0; the last page slides to the next page position is the current page position, the other two parameters are 0

 

Suddenly, we need to solve the problem in step 2. positionOffset is suitable for the gradient and scaling control parameters. positionOffsetPixels can be used as the control parameters for translation.

So how can we get the current View and the target View:

Share some of my mistakes:

1. [Error] I use getChildAt (position), getChildAt (position + 1), and getChildAt (position-1) to get the two views on the left and right. At first glance, really nice ~~~ When the code is written, the effect will be improved ~~ Cause of error: We ignore a very large object. The ViewPager mechanism dynamically loads and deletes views during sliding. ViewPager actually only maintains two to three views, the range of position is basically infinite ~~

2. [Error] I get the current location through getCurrentItem, and then + 1,-1 to get the next or previous one ~~ Stealing joy, hurry up and change the code. What's wrong with the effect ~~ Observe the log carefully. The getCurrentItem changes when the user's finger leaves the screen and the Page is still being animated ~~ No wonder ~ The entire sliding process is not fixed ~~ Alas, my heart is broken ~

3. [Error] The position does not change throughout the Sliding Process, and ViewPager saves two or three views. So I think, for the first or last page, getChildAt (0) and getChildAt (1) are used. For other pages, getChildAt (0) and getChildAt (2) are used ), after a series of changes ~ I think this will always be the right one, so I encountered the first problem. On the first page, no matter whether the position is 0, Nima, which is the left View and the right View ~~

With so many mistakes, you can bypass these detours and see what you want from them ~

The following is correct. In fact, when ViewPager adds a View or destroys a View, it is controlled by our own PageAdapter. Therefore, we can maintain a HashMap in ViewPager. And then, when sliding, get (position). For example, the above effect is always the View change on the right side, either from small to large, or from large to small.

 

Slide the next page: View on the left: map. get (position), View on the right: map. get (position + 1 ).

Slide the previous page: View on the left: map. get (position), View on the right: map. get (position + 1), same, because slide to the previous page, position is the current page-1

Now, we have analyzed and solved all the steps.

3. Code

MainActivity

 

package com.example.zhy_jazzyviewpager;import android.app.Activity;import android.os.Bundle;import android.support.v4.view.PagerAdapter;import android.view.Menu;import android.view.View;import android.view.ViewGroup;import android.widget.ImageView;import android.widget.ImageView.ScaleType;public class MainActivity extends Activity{protected static final String TAG = MainActivity;private int[] mImgIds;private MyJazzyViewPager mViewPager;@Overrideprotected void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);mImgIds = new int[] { R.drawable.a, R.drawable.b, R.drawable.c,R.drawable.d };mViewPager = (MyJazzyViewPager) findViewById(R.id.id_viewPager);mViewPager.setAdapter(new PagerAdapter(){@Overridepublic boolean isViewFromObject(View arg0, Object arg1){return arg0 == arg1;}@Overridepublic void destroyItem(ViewGroup container, int position,Object object){container.removeView((View) object);}@Overridepublic Object instantiateItem(ViewGroup container, int position){ImageView imageView = new ImageView(MainActivity.this);imageView.setImageResource(mImgIds[position]);imageView.setScaleType(ScaleType.CENTER_CROP);container.addView(imageView);mViewPager.setObjectForPosition(imageView, position);return imageView;}@Overridepublic int getCount(){return mImgIds.length;}});}}

This common code is to initialize ViewPager ~~ There's nothing to say ~~ One thing to note: In the instantiateItem method, we call an mViewPager. setObjectForPosition (imageView, position); in fact, it is used to save the Map value.

 

Mainly refer to custom ViewPager

 

Package com. example. zhy_jazzyviewpager; import java. util. hashMap; import java. util. linkedHashMap; import android. content. context; import android. support. v4.view. viewPager; import android. util. attributeSet; import android. util. log; import android. view. view; import com. nineoldandroids. view. viewHelper; public class MyJazzyViewPager extends ViewPager {private float mTrans; private float mScale;/*** maximum zoom-out ratio */private static final float SCALE_MAX = 0.5f; private static final String TAG = MyJazzyViewPager;/*** save position and View */private HashMap
 
  
MChildrenViews = new LinkedHashMap
  
   
();/*** Elements on the left when sliding */private View mLeft;/*** elements on the right when sliding */private View mRight; public MyJazzyViewPager (Context context, attributeSet attrs) {super (context, attrs) ;}@ Overridepublic void onPageScrolled (int position, float positionOffset, int positionOffsetPixels) {// Log. e (TAG, position = + position +, positionOffset = + positionOffset +, positionOffsetPixels = + positionOffsetPixels +, currentPos = + getCurren TItem (); // when sliding a very small distance, we think there is no motion, and there is a dispensable judgment float between toffset = isSmall (positionOffset )? 0: positionOffset; // obtain the left-side ViewmLeft = findViewFromObject (position); // obtain the right-side ViewmRight = findViewFromObject (position + 1); // Add the animation switching effect animateStack (mLeft, mRight, effectOffset, positionOffsetPixels); super. onPageScrolled (position, positionOffset, positionOffsetPixels);} public void setObjectForPosition (View view, int position) {mChildrenViews. put (position, view);}/*** get the corresponding View through location ** @ param position * @ Return */public View findViewFromObject (int position) {return mChildrenViews. get (position);} private boolean isSmall (float positionOffset) {return Math. abs (positionOffset) <0.0001;} protected void animateStack (View left, View right, float wait toffset, int positionOffsetPixels) {if (right! = Null) {/*** zoom out ratio if the finger slides from right to left (switch to the next one): 0.0 ~ 1.0, that is, from half to maximum * If the finger slides from left to right (to the first one): 1.0 ~ 0, that is, from the maximum to half */mScale = (1-SCALE_MAX) * limit toffset + SCALE_MAX;/*** x offset: if the finger slides from right to left (to the next one): 0-720 if the finger slides from left to right (to the previous one ): 720-0 */mTrans =-getWidth ()-getPageMargin () + positionOffsetPixels; ViewHelper. setScaleX (right, mScale); ViewHelper. setScaleY (right, mScale); ViewHelper. setTranslationX (right, mTrans);} if (left! = Null) {left. bringToFront ();}}}
  
 

As you can see, the core code is onPageScrolled. We use findViewFromObject (position); findViewFromObject (position + 1); to obtain the views on both sides of the left and right, and then add the animation effect; in this example, two animations are added. One is to zoom in from 0.5 to 1.0 or 1.0 to 0.5. That's right, our positionOffset provides the gradient variation ~~ There is also a translation Animation: the next page is directly moved to the current screen (the default is on the right side, you can comment out this effect, how to run it), and then the original default movement is continuously offset by positionOffsetPixels, it makes the user feel like it is being zoomed in and out ~~

 

Okay, so we can implement it ~~ You can easily write your favorite animation effects, such as adding a fade-in or fade-out on the default top ~~ Is it casual ~~

Our layout file:

 

     
  
 


 

4. Use of JazzyViewPager

In fact, the above implementation is the source code of JazzyViewPager on github. Needless to say, it is our MainActivity, which has about 10 Built-in effects, we can set the animation effect through code or layout ~~ The effect of the above example is called Stack;

Code for using JazzViewPager: basically the same ~~ Download the source code of JazzyViewPager.

MainActivity

 

Package com. jfeinstein. jazzyviewpager; import com. jfeinstein. jazzyviewpager. jazzyViewPager. transitionEffect; import android. app. activity; import android. OS. bundle; import android. support. v4.view. pagerAdapter; import android. view. view; import android. view. viewGroup; import android. widget. imageView; import android. widget. imageView. scaleType; public class MainActivity extends Activity {protected static final String TAG = MainActivity; private int [] mImgIds; private JazzyViewPager mViewPager; @ Overrideprotected void onCreate (Bundle savedInstanceState) {super. onCreate (savedInstanceState); setContentView (R. layout. activity_main); mImgIds = new int [] {R. drawable. a, R. drawable. b, R. drawable. c, R. drawable. d}; mViewPager = (JazzyViewPager) findViewById (R. id. id_viewPager); // sets the switching effect of mViewPager. setTransitionEffect (TransitionEffect. stack); mViewPager. setAdapter (new PagerAdapter () {@ Overridepublic boolean isViewFromObject (View arg0, Object arg1) {return arg0 = arg1 ;}@ Overridepublic void destroyItem (ViewGroup container, int position, Object object) {container. removeView (View) object);} @ Overridepublic Object instantiateItem (ViewGroup container, int position) {ImageView imageView = new ImageView (MainActivity. this); imageView. setImageResource (mImgIds [position]); imageView. setScaleType (ScaleType. CENTER_CROP); container. addView (imageView); mViewPager. setObjectForPosition (imageView, position); return imageView;} @ Overridepublic int getCount () {return mImgIds. length ;}});}}

The only difference from our code is:

 

// Set the Switching Effect
MViewPager. setTransitionEffect (TransitionEffect. Stack );

It has an optional switching effect of 12, which is actually to write 12 switching animations ~~~

Now, I will attach a favorite result: Tablet.

Finally, I like to use this blog to attract others ~~ If you are interested in the Code on github, you can analyze it and try to implement it yourself. Sometimes it is not very difficult ~ You can also do it ~!

 

Download source code

 



 

 

 

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.