Android adds an animation for ViewPager-custom ViewPager and androidviewpager
Reprinted please indicate the source: http://blog.csdn.net/allen315410/article/details/44224517
In my previous blog, I wrote a method to use property animation to add a switchover animation for ViewPager, which is compatible with devices of versions earlier than Android, there will be another Implementation Scheme for adding an animation for ViewPager, that is, to customize a ViewPager with its own animation effect, you can click here to view the information of friends who haven't had time to view it. Next, we will create a new project to illustrate how to customize a ViewPager with built-in animation switching effects.
Analysis
First, let's analyze what we need to get when we implement custom ViewPager built-in animation switching? First, we know that different views are switched on the screen during the back-and-forth switching of ViewPager. Therefore, we need to get the two views currently being switched when customizing ViewPager. Second, since we want to add an animation for ViewPager, We need to customize the animation. Well, the above two points are all required in this custom ViewPager. Let's create and obtain them step by step.
Next, I will create a class ViewPagerWithTransformer that inherits from ViewPager to implement custom ViewPager. First, we will overwrite a method in ViewPager. The Code is as follows. We will print the parameters in the method and use the custom ViewPager in the layout file, add the data adapter for this ViewPager in the Activity and add three imageviews to ViewPager to implement switching on ViewPager. For the code, see MainActivity in the previous blog.
@Overrideprotected void onPageScrolled(int position, float offset, int offsetPixels) {super.onPageScrolled(position, offset, offsetPixels);Log.i("TAG", "position = " + position + ",offset = " + offset + ",offsetPixels = " + offsetPixels);}
The parameters in the above method have been printed, and the LOG output is below. First, let's take a look at the LOG slides from page 0th to page 1st:
Then, let's take a look at the LOG that slides from page 1st to page 0th:
Analyze the above LOG:
When page 0th --> page 1st: position from 0 --> 1; offset from 0 --> 1; offsetPixels from 0 --> maximum screen width
When page 1st --> page 0th: position from 1 --> 0; offset from 1 --> 0; offsetPixels from 0 --> maximum screen width
Obviously, it is perceptible. Only position indicates the position of the current View being switched, offset indicates the offset proportion of the View, and offsetPixels indicates the actual offset of the View (px ).
Get the View object in the switch
[Error] in the above analysis, when we define a ViewPager with animation switching, we need to get two View objects in the switching process, so how can we get the two View objects in the code? As you know, we used the source code of ViewPager in the previous blog. The parent class of ViewPager is ViewGroup. We know that if you want to obtain a View object in ViewGroup, getChildAt (int index) exists) the method can get the View object. This method is no problem in ViewGroup, and then an error occurs when it is used in ViewPager, because the cache mechanism is added to ViewPager, A ViewPager can only cache 2-3 View objects by default. When more View objects are loaded into ViewPager, ViewPager discards the previous View object, in this way, the previous, current, and next View objects cannot be obtained through the getChildAt (position), getChildAt (position) (position-1), and getChildAt (position + 1) methods, obviously, position indicates that there are more than two or three View objects, but they are infinite.
[Error] The expected object cannot be obtained through getChildAt (position). Since position cannot be used, another getCurrentItem () in ViewGroup obtains the badge and getChildCount () of the current View () can I use this method to obtain the number of views? First, print the LOG in the onPageScrolled () method.
As we can see, the value of getCurrentItem is constantly changing. When we open page 1st, getCurrentItem = 0, which is based on the value of getCurrentItem that we can bring to getChildAt (getCurrentItem-1) in getChildAt (getCurrentItem) and getChildAt (getCurrentItem + 1), the previous View, current View, and next View can be obtained. Unfortunately, when our fingers are removed from the screen, getCurrentItem is changed to 1, and the View obtained through getChildAt (getCurrentItem) is incorrect. Therefore, getCurrentItem () is also incorrect.
[Correct] none of the above methods can accurately obtain the current View object. Let's take a closer look at the position parameter. Based on the preceding LOG input, when we slide the 0th page to the 1st page in ViewPager, the position is unchanged. In this case, pisition = 0; when we slide from page 1st to page 0th, the position has not changed yet. At this time, the position is 0. Can we still determine the View object based on the position, let's assume that position represents the View on page 0th, and position + 1 represents the View on page 1st, and so on, we can get all the views. Next, we can implement this idea in the code, which is particularly simple, that is, to create a Map set to cache the View, we use position as the key, use the view object as the value, and provide a method to add the View cache and a method to remove the View cache. When we provide an adapter PagerAdapter for ViewPager, we can set the View object to the cache set of View in the instantiateItem (ViewGroup container, int position) method, in the destroyItem (ViewGroup container, int position, object object) method to remove the View from the cache set. The specific code is as follows:
// Save the private Map of the View object on ViewPager <Integer, View> mViewCache = new HashMap <Integer, View> (); /*** set the View cache ** @ param position * @ param viewCache */public void setViewCache (Integer position, View viewCache) {mViewCache. put (position, viewCache);}/*** remove the View with the specified position from the View cache set ** @ param position */public void removeViewCache (Integer position) {mViewCache. remove (position );}
The implementation of switching an animation solves a headache. If you get the View object being switched, this problem has been solved above, and only the animation is left below. In this case, let's imitate the DepthPageTransformer animation effect in the previous blog. We can customize two types of Animation: A Scale animation and a Translate animation, when the two animations are executed in turn, you can imitate the pan-scaling animation effect of DepthPageTransformer. The code is very simple and not pasted separately. The complete code is shown below.
Complete code custom ViewPager source code, ViewPagerWithTransformer. java
Public class ViewPagerWithTransformer extends ViewPager {// Viewprivate View mLeftView on the left; // Viewprivate View mRightView on the right; // gradient value of the translation animation private float mTranslate; // adjust the animation's gradient value private float mScale; // The minimum scaling ratio private static final float MIN_SCALE = 0.6f; // Save the ViewPager's View object private Map <Integer, view> mViewCache = new HashMap <Integer, View> ();/*** sets the View cache ** @ param position * @ param viewCache */public v Oid setViewCache (Integer position, View viewCache) {mViewCache. put (position, viewCache);}/*** remove the View with the specified position from the View cache set ** @ param position */public void removeViewCache (Integer position) {mViewCache. remove (position);} public ViewPagerWithTransformer (Context context, AttributeSet attrs) {super (context, attrs); // TODO Auto-generated constructor stub} @ Overrideprotected void onPageScrolled (int pos Ition, float offset, int offsetPixels) {super. onPageScrolled (position, offset, offsetPixels); mLeftView = mViewCache. get (position); mRightView = mViewCache. get (position + 1); animStack (mLeftView, mRightView, offset, offsetPixels);} private void animStack (View left, View right, float offset, int offsetPixels) {// TODO Auto-generated method stubif (right! = Null) {// from page 0th -- to page 1st, offset: 0 ~ 1. Zoom ratio: 0.6 ~ 1 mScale = (1-MIN_SCALE) * offset + MIN_SCALE; // The distance from the translation to mTranslate =-getWidth ()-getPageMargin () + offsetPixels; // use NineOldAndroids to compile the attribute animation ViewHelper. setScaleX (right, mScale); ViewHelper. setScaleY (right, mScale); ViewHelper. setTranslationX (right, mTranslate);} if (left! = Null) {// The left page is always on the top left. bringToFront ();}}}
Declare in the layout file that activity_main.xml
<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" > <com.example.viewpagerwithtransformeranim.ViewPagerWithTransformer android:id="@+id/viewpager" android:layout_width="match_parent" android:layout_height="match_parent" > </com.example.viewpagerwithtransformeranim.ViewPagerWithTransformer></RelativeLayout>
Use this control in the Activity, MainActivity. java
Public class MainActivity extends Activity {private int [] imgRes = new int [] {R. drawable. guide_image1, R. drawable. guide_image2, R. drawable. guide_image3}; private List <ImageView> imgList = new ArrayList <ImageView> (); private ViewPagerWithTransformer mViewPager; @ Overrideprotected void onCreate (Bundle savedInstanceState) {super. onCreate (savedInstanceState); requestWindowFeature (Window. FEATURE_NO_TITLE); setContentView (R. layout. activity_main); mViewPager = (ViewPagerWithTransformer) findViewById (R. id. viewpager); mViewPager. setAdapter (new PagerAdapter () {@ Overridepublic boolean isViewFromObject (View arg0, Object arg1) {return arg0 = arg1 ;}@ Overridepublic int getCount () {return imgRes. length ;}@ Overridepublic Object instantiateItem (ViewGroup container, int position) {ImageView mImageView = new ImageView (MainActivity. this); mImageView. setBackgroundResource (imgRes [position]); mImageView. setScaleType (ScaleType. CENTER_CROP); imgList. add (mImageView); // set View cache mViewPager for ViewPager. setViewCache (position, mImageView); container. addView (mImageView); return mImageView;} @ Overridepublic void destroyItem (ViewGroup container, int position, Object object) {// remove ViewPager's View cache mViewPager. removeViewCache (position); container. removeView (imgList. get (position ));}});}}
Well, all the source code is above. Note that when you rewrite the instantiateItem method in the adapter PagerAdapter set for ViewPager, remember to call mViewPager. setViewCache (position, mImageView) method, sets the View cache for ViewPager, and then calls mViewPager In the override destroyItem method. the removeViewCache (position) method removes the View cache. Thanks to CSDN blog expert Hong Yang selfless dedication tutorial, tutorial video address: http://www.imooc.com/learn/226
Download the source code here