序言:
我们知道在ViewPager中给我们提供了PageTransformer接口用于ViewPager切换的动画效果实现,一般我们需要实现这个接口里的transformPage方法实现切换的动画效果,这样我们就实现了ViewPager中Item之间切换的效果,例如下面的效果(摘自鸿洋博客图片):
我们发现,这里实现的是Item之间切换的效果,但是每个Item页里面的View并没有动画效果,我们也知道在做App的Guide引导页的时候,通过几个静态的图片展示切换,效果太过平庸,所以这次我们就介绍下SCViewPager这个库如果实现Item的动态变换。效果图来一发:
开源项目地址: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>
看到这个效果图是不是一脸懵逼,确实,这种布局效果图出来跟上面的动画效果对比确实让人大吃一惊,这个就是他设计的巧妙之处,根据设计的动画效果,首先在RelativeLayout中将View的起始位置设置布局完毕。
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的使用,现在我们就结合源码分析下实现过程。 首先看看结构图:
(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
转载注明出处,谢谢
==========