ViewPager动态变换效果之SCViewPager源码解析

来源:互联网 发布:知乎用户童谣 编辑:程序博客网 时间:2024/05/21 06:37

序言:
我们知道在ViewPager中给我们提供了PageTransformer接口用于ViewPager切换的动画效果实现,一般我们需要实现这个接口里的transformPage方法实现切换的动画效果,这样我们就实现了ViewPager中Item之间切换的效果,例如下面的效果(摘自鸿洋博客图片):
viewpager

我们发现,这里实现的是Item之间切换的效果,但是每个Item页里面的View并没有动画效果,我们也知道在做App的Guide引导页的时候,通过几个静态的图片展示切换,效果太过平庸,所以这次我们就介绍下SCViewPager这个库如果实现Item的动态变换。效果图来一发:

example

开源项目地址:https://github.com/sacot41/SCViewPager

一:项目原理概述

我们通过上面的效果图发现,SCViewPager给我们提供了一种更棒的切换效果,效果比以前的静态图片切换展示确实强的太多。下面,我们就简要介绍下SCViewPager效果的实现原理。首先,必须要监听ViewPager的PageScrolled事件,当PageScrolled事件触发时,我们就进行动画的执行,这样就实现了效果。其次是效果怎么设计才能正确展示,这里就需要我们探究源码一步步解析才能明白其中的原理,我们可以简单的以SCViewPager提供的example进行研究下实现。
1、首先看example的布局文件:

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"        xmlns:tools="http://schemas.android.com/tools"        android:layout_width="fill_parent"        android:layout_height="fill_parent"        android:clipChildren="true"        android:clipToPadding="true"        tools:context=".MainActivity">        <com.dev.sacot41.scviewpager.SCViewPager            android:id="@+id/viewpager_main_activity"            android:layout_width="match_parent"            android:layout_height="match_parent">        </com.dev.sacot41.scviewpager.SCViewPager>        <com.dev.sacot41.scviewpager.DotsView            android:orientation="horizontal"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_alignParentBottom="true"            android:layout_centerHorizontal="true"            android:layout_marginBottom="10dp"            android:id="@+id/dotsview_main"        />        <ImageView            android:id="@+id/imageview_main_activity_name_tag"            android:layout_width="match_parent"            android:layout_height="wrap_content"            android:paddingLeft="40dp"            android:paddingRight="50dp"            android:layout_alignParentTop="true"            android:rotation="-10"            android:src="@drawable/name_tag"/>        <ImageView            android:id="@+id/imageview_main_activity_currently_work"            android:layout_width="match_parent"            android:layout_height="wrap_content"            android:layout_marginTop="225dp"            android:src="@drawable/currently_work"/>        <ImageView            android:id="@+id/imageview_main_activity_at_skex"            android:layout_width="match_parent"            android:layout_height="wrap_content"            android:layout_marginTop="450dp"            android:src="@drawable/at_skex_2"/>        <ImageView            android:id="@+id/imageview_main_activity_commonly"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_marginTop="95dp"            android:layout_centerHorizontal="true"            android:src="@drawable/commonly"/>        <ImageView            android:id="@+id/imageview_main_activity_django_python"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_marginLeft="75dp"            android:layout_marginTop="400dp"            android:layout_centerHorizontal="true"            android:src="@drawable/django_python"/>        <ImageView            android:id="@+id/imageview_main_activity_mobile"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_marginTop="180dp"            android:layout_centerHorizontal="true"            android:src="@drawable/mobile"/>        <ImageView            android:id="@+id/imageview_main_activity_but"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_centerHorizontal="true"            android:src="@drawable/but"/>        <ImageView            android:id="@+id/imageview_main_activity_diploma"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_marginTop="250dp"            android:layout_centerHorizontal="true"            android:src="@drawable/diploma"/>        <ImageView            android:id="@+id/imageview_main_activity_why"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_marginBottom="50dp"            android:layout_alignParentBottom="true"            android:layout_centerHorizontal="true"            android:src="@drawable/why"/>       <ImageView           android:id="@+id/imageview_main_future"           android:layout_width="wrap_content"           android:layout_height="wrap_content"           android:layout_centerHorizontal="true"           android:src="@drawable/future"/>        <ImageView            android:id="@+id/imageview_main_arduino"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_below="@id/imageview_main_future"            android:layout_marginTop="20dp"            android:layout_marginLeft="50dp"            android:src="@drawable/arduino"/>        <ImageView            android:id="@+id/imageview_main_raspberry_pi"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_below="@id/imageview_main_arduino"            android:layout_marginTop="40dp"            android:layout_alignParentRight="true"            android:layout_marginRight="50dp"            android:src="@drawable/raspberry_pi_logo"/>        <ImageView            android:id="@+id/imageview_main_connected_device"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_alignParentBottom="true"            android:layout_marginBottom="75dp"            android:layout_marginLeft="50dp"            android:src="@drawable/connect_device"/>        <ImageView            android:id="@+id/imageview_main_check_out"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_centerHorizontal="true"            android:src="@drawable/check_out"/>        <TextView            android:id="@+id/textview_main_github_link"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:paddingLeft="20dp"            android:paddingRight="20dp"            android:textColor="@color/theme_700"            android:layout_centerHorizontal="true"            android:layout_below="@id/imageview_main_check_out"            android:autoLink="web"            android:textAppearance="@android:style/TextAppearance.Large"            android:text="https://github.com/sacot41"/>        <TextView            android:id="@+id/textview_main_linkedin_link"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:paddingLeft="20dp"            android:paddingRight="20dp"            android:textColor="@color/theme_700"            android:layout_centerHorizontal="true"            android:layout_marginTop="50dp"            android:layout_below="@id/textview_main_github_link"            android:autoLink="web"            android:textAppearance="@android:style/TextAppearance.Large"            android:text="https://ca.linkedin.com/pub/samuel-côté/62/211/22a"/>    </RelativeLayout>

展现的效果:
effect

看到这个效果图是不是一脸懵逼,确实,这种布局效果图出来跟上面的动画效果对比确实让人大吃一惊,这个就是他设计的巧妙之处,根据设计的动画效果,首先在RelativeLayout中将View的起始位置设置布局完毕。

2、接着我们看看MainActivity中怎么实现的:

package com.dev.sacot41.myresume;import android.graphics.Point;import android.os.Bundle;import android.support.v4.app.FragmentActivity;import android.support.v4.view.ViewPager;import android.view.View;import android.view.Window;import android.view.WindowManager;import com.dev.sacot41.scviewpager.DotsView;import com.dev.sacot41.scviewpager.SCPositionAnimation;import com.dev.sacot41.scviewpager.SCViewAnimation;import com.dev.sacot41.scviewpager.SCViewAnimationUtil;import com.dev.sacot41.scviewpager.SCViewPager;import com.dev.sacot41.scviewpager.SCViewPagerAdapter;public class MainActivity extends FragmentActivity {    private static final int NUM_PAGES = 5;    private SCViewPager mViewPager;    private SCViewPagerAdapter mPageAdapter;    private DotsView mDotsView;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        getWindow().requestFeature(Window.FEATURE_ACTION_BAR);        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);        setContentView(R.layout.activity_main);        mViewPager = (SCViewPager) findViewById(R.id.viewpager_main_activity);        mDotsView = (DotsView) findViewById(R.id.dotsview_main);        mDotsView.setDotRessource(R.drawable.dot_selected, R.drawable.dot_unselected);        mDotsView.setNumberOfPage(NUM_PAGES);        mPageAdapter = new SCViewPagerAdapter(getSupportFragmentManager());        mPageAdapter.setNumberOfPage(NUM_PAGES);        mPageAdapter.setFragmentBackgroundColor(R.color.theme_100);        mViewPager.setAdapter(mPageAdapter);        mViewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {            @Override            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {            }            @Override            public void onPageSelected(int position) {                mDotsView.selectDot(position);            }            @Override            public void onPageScrollStateChanged(int state) {            }        });        final Point size = SCViewAnimationUtil.getDisplaySize(this);        View nameTag = findViewById(R.id.imageview_main_activity_name_tag);        SCViewAnimation nameTagAnimation = new SCViewAnimation(nameTag);        nameTagAnimation.addPageAnimation(new SCPositionAnimation(this, 0,0,-size.y/2));        mViewPager.addAnimation(nameTagAnimation);        View currentlyWork = findViewById(R.id.imageview_main_activity_currently_work);        SCViewAnimation currentlyWorkAnimation = new SCViewAnimation(currentlyWork);        currentlyWorkAnimation.addPageAnimation(new SCPositionAnimation(this, 0, -size.x, 0));        mViewPager.addAnimation(currentlyWorkAnimation);        View atSkex = findViewById(R.id.imageview_main_activity_at_skex);        SCViewAnimationUtil.prepareViewToGetSize(atSkex);        SCViewAnimation atSkexAnimation = new SCViewAnimation(atSkex);        atSkexAnimation.addPageAnimation(new SCPositionAnimation(getApplicationContext(), 0, 0, -( size.y - atSkex.getHeight() )));        atSkexAnimation.addPageAnimation(new SCPositionAnimation(getApplicationContext(), 1, -size.x, 0));        mViewPager.addAnimation(atSkexAnimation);        View mobileView = findViewById(R.id.imageview_main_activity_mobile);        SCViewAnimation mobileAnimation = new SCViewAnimation(mobileView);        mobileAnimation.startToPosition((int)(size.x*1.5), null);        mobileAnimation.addPageAnimation(new SCPositionAnimation(this, 0, -(int)(size.x*1.5), 0));        mobileAnimation.addPageAnimation(new SCPositionAnimation(this, 1, -(int)(size.x*1.5), 0));        mViewPager.addAnimation(mobileAnimation);        View djangoView = findViewById(R.id.imageview_main_activity_django_python);        SCViewAnimation djangoAnimation = new SCViewAnimation(djangoView);        djangoAnimation.startToPosition(null, -size.y);        djangoAnimation.addPageAnimation(new SCPositionAnimation(this, 0, 0, size.y));        djangoAnimation.addPageAnimation(new SCPositionAnimation(this, 1, 0, size.y));        mViewPager.addAnimation(djangoAnimation);        View commonlyView = findViewById(R.id.imageview_main_activity_commonly);        SCViewAnimation commonlyAnimation = new SCViewAnimation(commonlyView);        commonlyAnimation.startToPosition(size.x, null);        commonlyAnimation.addPageAnimation(new SCPositionAnimation(this, 0, -size.x, 0));        commonlyAnimation.addPageAnimation(new SCPositionAnimation(this, 1, -size.x, 0));        mViewPager.addAnimation(commonlyAnimation);        View butView = findViewById(R.id.imageview_main_activity_but);        SCViewAnimation butAnimation = new SCViewAnimation(butView);        butAnimation.startToPosition(size.x, null);        butAnimation.addPageAnimation(new SCPositionAnimation(this, 1, -size.x,0));        butAnimation.addPageAnimation(new SCPositionAnimation(this, 2, -size.x,0));        mViewPager.addAnimation(butAnimation);        View diplomeView = findViewById(R.id.imageview_main_activity_diploma);        SCViewAnimation diplomeAnimation = new SCViewAnimation(diplomeView);        diplomeAnimation.startToPosition((size.x *2), null);        diplomeAnimation.addPageAnimation(new SCPositionAnimation(this, 1, -size.x*2,0));        diplomeAnimation.addPageAnimation(new SCPositionAnimation(this, 2, -size.x*2 ,0));        mViewPager.addAnimation(diplomeAnimation);        View whyView = findViewById(R.id.imageview_main_activity_why);        SCViewAnimation whyAnimation = new SCViewAnimation(whyView);        whyAnimation.startToPosition(size.x, null);        whyAnimation.addPageAnimation(new SCPositionAnimation(this, 1, -size.x, 0));        whyAnimation.addPageAnimation(new SCPositionAnimation(this, 2, -size.x, 0));        mViewPager.addAnimation(whyAnimation);        View futureView = findViewById(R.id.imageview_main_future);        SCViewAnimation futureAnimation = new SCViewAnimation(futureView);        futureAnimation.startToPosition(null, -size.y);        futureAnimation.addPageAnimation(new SCPositionAnimation(this, 2, 0, size.y));        futureAnimation.addPageAnimation(new SCPositionAnimation(this, 3, -size.x, 0));        mViewPager.addAnimation(futureAnimation);        View arduinoView = findViewById(R.id.imageview_main_arduino);        SCViewAnimation arduinoAnimation = new SCViewAnimation(arduinoView);        arduinoAnimation.startToPosition(size.x * 2, null);        arduinoAnimation.addPageAnimation(new SCPositionAnimation(this, 2, - size.x *2, 0));        arduinoAnimation.addPageAnimation(new SCPositionAnimation(this, 3, - size.x, 0));        mViewPager.addAnimation(arduinoAnimation);        View raspberryView = findViewById(R.id.imageview_main_raspberry_pi);        SCViewAnimation raspberryAnimation = new SCViewAnimation(raspberryView);        raspberryAnimation.startToPosition(-size.x, null);        raspberryAnimation.addPageAnimation(new SCPositionAnimation(this, 2, size.x, 0));        raspberryAnimation.addPageAnimation(new SCPositionAnimation(this, 3, -size.x, 0));        mViewPager.addAnimation(raspberryAnimation);        View connectedDeviceView = findViewById(R.id.imageview_main_connected_device);        SCViewAnimation connectedDeviceAnimation = new SCViewAnimation(connectedDeviceView);        connectedDeviceAnimation.startToPosition((int)(size.x *1.5), null);        connectedDeviceAnimation.addPageAnimation(new SCPositionAnimation(this, 2, -(int) (size.x * 1.5), 0));        connectedDeviceAnimation.addPageAnimation(new SCPositionAnimation(this, 3,  - size.x, 0));        mViewPager.addAnimation(connectedDeviceAnimation);        View checkOutView = findViewById(R.id.imageview_main_check_out);        SCViewAnimation checkOutAnimation = new SCViewAnimation(checkOutView);        checkOutAnimation.startToPosition(size.x, null);        checkOutAnimation.addPageAnimation(new SCPositionAnimation(this, 3, -size.x, 0));        mViewPager.addAnimation(checkOutAnimation);        View linkedinView = findViewById(R.id.textview_main_linkedin_link);        SCViewAnimation linkedinAnimation = new SCViewAnimation(linkedinView);        linkedinAnimation.startToPosition(size.x, null);        linkedinAnimation.addPageAnimation(new SCPositionAnimation(this, 3, -size.x, 0));        mViewPager.addAnimation(linkedinAnimation);        View githubView = findViewById(R.id.textview_main_github_link);        SCViewAnimation githubAnimation = new SCViewAnimation(githubView);        githubAnimation.startToPosition(size.x, null);        githubAnimation.addPageAnimation(new SCPositionAnimation(this, 3, -size.x, 0));        mViewPager.addAnimation(githubAnimation);    }}

上面的代码都是按照一个逻辑处理,首先穿件一个SCViewAnimation对象,然后调用该对象的startToPosition方法指定View的起始位置,然后在创建一个动画类型(SCPositionAnimation)添加到SCViewAnimation中即可。实现也是非常简单,主要是动画的起点、终点位置的确定。通过上面的布局和代码,我们可以看出SCViewPager使用起来是非常简单,方便的。那么我们还需要学习更深入一点,看看它的源码分析实现的原理。

二:SCViewPager源码分析

在上面我们简要的看了SCViewPager的使用,现在我们就结合源码分析下实现过程。 首先看看结构图:
class-struct

(1)、DotsView:底部原点View,自定义的底部圆点
(2)、SCPageAnimation:抽象类,用于定义View的动画效果实现;
(3)、SCPositionAnimation:平移动画效果,一个SCPageAnimation实现的子类
(4)、SCSizeAnimation:大小改变动画效果,SCPageAnimation的实现子类
(5)、SCViewAnimation:视图动画,提供指定动画起始位置的startToPoSition()、addPageAnimation()和applyAnimation()方法,主要负责动画的管理。
(6)、SCViewAnimationUtil:工具类
(7)、SCViewPager:自定义的ViewPager,重写onPageScrolled()方法,实现滑动切换执行动画。
(8)、SCViewPagerAdapter:FragmentStatePagerAdapter的子类,设置ViewPager的Adapter属性。

上面我们已经简单的说了,效果的实现就是通过监听PageScrolled方法来实现,当然仅仅知道这一点还是不够的,比如这些View控件怎么布局的,动画怎么实现的,这些都是技术点,所以我们就深入到各个类学习源码的实现。

1、SCPageAnimation抽象类

public abstract class SCPageAnimation {    public int page;    public abstract void applyTransformation(View onView, float positionOffset);}

在这个抽象类中定义了一个page成员变量和applyTransformation方法,page变量用于标识动画作用在第几个ViewPager页面,applyTransformation方法用于执行动画

2、SCPositionAnimation类:

public class SCPositionAnimation extends SCPageAnimation {    public int xPosition;    public int yPosition;    private float xStartPosition;    private float yStartPosition;    /**     * @param forPage page to apply animation     * @param dx x moving, in dp     * @param dy y moving, in dp     */    public SCPositionAnimation(Context context, int forPage, int dx, int dy) {        this.page = forPage;        this.xPosition = dx;        this.yPosition = dy;        this.xStartPosition = -1;        this.yStartPosition = -1;    }    public void applyTransformation(View onView, float positionOffset) {        ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) onView.getLayoutParams();        if (positionOffset <= 0.0001) {            xStartPosition = onView.getTranslationX();            yStartPosition = onView.getTranslationY();            return;        }        onView.setTranslationX((int)(xPosition * positionOffset) + xStartPosition);        onView.setTranslationY((int)(yPosition * positionOffset) + yStartPosition);        onView.requestLayout();    }}

类很简短,继承自SCPageAnimation,该类新增了四个成员变量用于记录控件位置。主要是applyTransformation方法中通过positionOffset(该值介于[0,1))计算View的平移位置,通过setTranslationX/Y方法达到实现效果。

3、SCSizeAnimation源码

public class SCSizeAnimation extends SCPageAnimation {    public float dHeigh;    public float dWidth;    private int startHeigh;    private int startWidth;    /**     *     * @param forPage page to apply animation     * @param dh height variation, in percentage     * @param dw width variation, in percentage     */    public SCSizeAnimation(int forPage, float dh, float dw) {        this.page = forPage;        this.dHeigh = dh;        this.dWidth = dw;    }    @Override    public void applyTransformation(View onView, float positionOffset) {        ViewGroup.LayoutParams param = onView.getLayoutParams();        if(positionOffset <= 0) {            startHeigh = onView.getMeasuredHeight();            startWidth = onView.getMeasuredWidth();            return;        }        param.height = (int)(dHeigh * startHeigh * positionOffset) + startHeigh;        param.width = (int)(dWidth * startHeigh * positionOffset) + startWidth;        onView.setLayoutParams(param);    }}

同样,这个类也是很简短,它新增了startHeight、startWidth两个成员变量,用于记录控件的初始宽高,在applyTransformation方法中通过获取View的LayoutParams属性进行改变控件的大小,以此来实现效果的动态变化。

4、SCViewAnimation类

public class SCViewAnimation {    private View view;    private HashMap<Integer, ArrayList<SCPageAnimation>> pageAnimationMap;    public SCViewAnimation(View inView) {        this.view = inView;        this.pageAnimationMap = new HashMap<Integer, ArrayList<SCPageAnimation>>();    }    public void startToPosition(Integer xPosition, Integer yPosition) {        if (xPosition != null) this.view.setX(xPosition);        if (yPosition != null) this.view.setY(yPosition);        this.view.requestLayout();    }    public void addPageAnimation(SCPageAnimation inPageAnimation) {        ArrayList<SCPageAnimation> animationList = pageAnimationMap.get(inPageAnimation.page);        if (animationList == null) animationList = new ArrayList<SCPageAnimation>();        animationList.add(inPageAnimation);        pageAnimationMap.put(inPageAnimation.page, animationList);    }    public void applyAnimation(int page, float positionOffset) {        ArrayList<SCPageAnimation> animationList = pageAnimationMap.get(page);        if (animationList == null) return;        for(SCPageAnimation animation : animationList) {            animation.applyTransformation(this.view, positionOffset);        }    }}

SCViewAnimation类主要用于管理View的动画,该类包含一个HashMap

public class SCViewAnimationUtil {    public static void prepareViewToGetSize(View view) {        view.measure( View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),  View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));        view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight());    }    public static Point getDisplaySize(Activity activity) {        Display display = activity.getWindowManager().getDefaultDisplay();        final Point size = new Point();        display.getSize(size);        return size;    }}

工具类,主要有两个方法:
(1)、prepareViewToGetSize(view):调用view的measure()方法测量,获取view的宽高。
(2)、getDisplaySize(activity):获取屏幕显示的大小

6、SCViewPager类:

public class SCViewPager extends ViewPager {    private ArrayList<SCViewAnimation> mViewAnimation;    public SCViewPager(Context context) {        super(context);        this.mViewAnimation = new ArrayList<SCViewAnimation>();    }    public SCViewPager(Context context, AttributeSet attr) {        super(context, attr);        this.mViewAnimation = new ArrayList<SCViewAnimation>();    }    public void addAnimation(SCViewAnimation inViewAnimation) {        mViewAnimation.add(inViewAnimation);    }    @Override    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {        super.onPageScrolled(position, positionOffset, positionOffsetPixels);        for (int i = 0; i < mViewAnimation.size(); i++) {            mViewAnimation.get(i).applyAnimation(position, positionOffset);        }    }}

这里是对ViewPager进行各简单的重写,重写了onPageScrolled方法,该方法包含三个参数,position页面的位置,positionOffset页面滑动的比例,取值范围[0,1),positionOffsetPixels页面滑动的距离,单位px。在这个方法里,遍历所有的SCViewAnimation结合,然后调用applyAnimation方法执行动画。

7、SCViewPagerAdapter类

public class SCViewPagerAdapter extends FragmentStatePagerAdapter {    private ArrayList<SCViewPagerFragment> mFragmentList;    private int mNumberOfPage = 0;    private int mBackgroundColor;    public SCViewPagerAdapter(FragmentManager fm) {        super(fm);        mFragmentList = new ArrayList<>();    }    public void setNumberOfPage(int numberOfPage) {        mNumberOfPage = numberOfPage;    }    public void setFragmentBackgroundColor(int colorResource) {        mBackgroundColor = colorResource;    }    @Override    public Fragment getItem(int position) {        SCViewPagerFragment fragment = null;        if (mFragmentList.size()-1 >= position) fragment = mFragmentList.get(position);        if (fragment == null) {            fragment = new SCViewPagerFragment();            fragment.setBackground(mBackgroundColor);        }        return fragment;    }    @Override    public int getCount() {        return mNumberOfPage;    }    public static class SCViewPagerFragment extends Fragment {        private int color;        public SCViewPagerFragment() {            this.color = R.color.white;        }        public void setBackground(int inColor) {            this.color = inColor;        }        @Override        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {            LinearLayout view = new LinearLayout(getActivity());            view.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT));            view.setOrientation(LinearLayout.VERTICAL);            view.setBackgroundColor(getResources().getColor(this.color));            return view;        }        @Override        public void onActivityCreated(Bundle savedInstanceState) {            super.onActivityCreated(savedInstanceState);        }    }}

在SCViewPagerAdapter类中,我们只关注一个成员变量mNumberOfPage,用于设置我们有多少个页面,然后由系统生成相应个数的Fragment,以此达到滑动效果,这里所有的Fragment只显示包含一个LinearLayout的空布局,不包含我们动画展示的View。

至此,我们针对各个类的源码已经介绍完毕,总体的代码量不多,代码也不复杂,主要是一个巧妙。在这里,使用的Fragemnt内容是不关涉到我们的动画View,我们通过将动画View和ViewPager放在同一页面,然后通过startToPosition指定控件的位置,达到控件的隐藏效果,起始他们都是在MainActivity页面,然后将ViewPager的滑动事件绑定到动画的执行,就可以制作出效果。源码看完了,我们在结合example的例子分析下,比如:

View nameTag = findViewById(R.id.imageview_main_activity_name_tag);SCViewAnimation nameTagAnimation = new SCViewAnimation(nameTag);nameTagAnimation.addPageAnimation(new SCPositionAnimation(this, 0,0,-size.y/2));mViewPager.addAnimation(nameTagAnimation);

首先获取View控件nameTag,然后创建SCViewAnimation类,传入nameTag控件进行绑定,然后添加SCPositionAnimation动画,该动画中指定page=0,dx=0,dy=-size.y/2,最后将该SCViewAnimation添加到ViewPager中的SCViewAnimation集合中。滑动进行动画效果展示。

==========
作者:mr_dsw
博客地址:http://blog.csdn.net/mr_dsw
转载注明出处,谢谢

==========

0 0