前言
最近在学习一些开源项目,无意中看到一个很不错的引导页效果,实现起来也比较简单,所以在这里分享给大家。先看下效果图:
看着比普通的图片引导页是不是要好上一些呢?
实践
其实,这个效果实现起来还是比较简单的。主要是运用到了ViewPager的setPageTransformer(),这个方法。具体的方法讲解我在这里就不过多的介绍了,等下面用到的时候会简单说下。那么我们先来看下整体的时间流程。
其实很简单,就是ViewPager中放入Fragemnt。我们先看代码:
private void initView() {
mViewPager = (ViewPager) findViewById(R.id.page);
mViewPager.setAdapter(new ScreenSlidePagerAdapter(getSupportFragmentManager()));
/**
* 为viewpager的滑动添加自定义的动画效果
*/
mViewPager.setPageTransformer(true, new CrossfadePageTransformer());
mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
Log.d("onPageScrolled", "position: " + position);
Log.d("onPageScrolled", "positionOffset: " + positionOffset);
Log.d("onPageScrolled", "positionOffsetPixels: " + positionOffsetPixels);
}
@Override
public void onPageSelected(int position) {
if (position == NUM_PAGES - 1) {
startActivity(new Intent(getApplicationContext(), MainActivity.class));
finish();
}
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
}
class ScreenSlidePagerAdapter extends FragmentPagerAdapter {
public ScreenSlidePagerAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int position) {
WelcomeFragment wf = null;
switch (position) {
case 0:
wf = WelcomeFragment.newInstance(R.layout.fragment_welcome_one);
break;
case 1:
wf = WelcomeFragment.newInstance(R.layout.fragment_welcome_two);
break;
case 2:
wf = WelcomeFragment.newInstance(R.layout.fragment_welcome_three);
break;
case 3:
wf = WelcomeFragment.newInstance(R.layout.fragment_welcome_four);
break;
case 4:
wf = WelcomeFragment.newInstance(R.layout.fragment_welcome_five);
break;
}
return wf;
}
@Override
public int getCount() {
return NUM_PAGES;
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
Log.d(TAG, "instantiateItem: " + position);
return super.instantiateItem(container, position);
}
}
这段代码相信大家都能看明白,主要是就是给ViewPager创建适配器,在适配器中实例化Fragemnt。在这里根据滑动position的不同动态创建5个WelcomeFragment,在这里他们的布局是不同的,最后一个布局为空白页。这样就会有一个过渡的效果。这里面的重点是 mViewPager.setPageTransformer(true, new CrossfadePageTransformer());这个方法主要就是设置ViewPager切换的动画的,是这个方法第一个参数通常设置为true。第二个方法需要PageTransformer。那么我们看下CrossfadePageTransformer这个类做了什么:
/**
* 自定义PageTransformer实现自定义动画
*/
class CrossfadePageTransformer implements ViewPager.PageTransformer {
@Override
public void transformPage(View page, float position) {
int name = page.getId();
Log.d(TAG, "view: " + name + "-------- position: " + position);
Log.d("TAG", "-------- position: " + position);
int pageWidth = page.getWidth();
View backgroundView = page.findViewById(R.id.welcome_fragment);
View text_head = page.findViewById(R.id.heading);
View text_content = page.findViewById(R.id.content);
/**
* one
*/
View object1 = page.findViewById(R.id.a000);
View object2 = page.findViewById(R.id.a001);
View object3 = page.findViewById(R.id.a002);
/**
* two
*/
View object4 = page.findViewById(R.id.a003);
View object5 = page.findViewById(R.id.a004);
View object6 = page.findViewById(R.id.a005);
View object7 = page.findViewById(R.id.a006);
/**
* three
*/
View object10 = page.findViewById(R.id.a011);
View object8 = page.findViewById(R.id.a008);
View object11 = page.findViewById(R.id.a007);
/**
* four
*/
View object9 = page.findViewById(R.id.a010);
View object12 = page.findViewById(R.id.a012);
View object13 = page.findViewById(R.id.a013);
if (0 <= position && position < 1) {
/**
* [1 , 0]右侧page处理,抵消page本身的滑动动画
* pageWidth * -position 结果为负 右侧向左
*/
page.setTranslationX(pageWidth * (-position));
}
if (-1 < position && position < 0) {
/**
* [-1 , 0)左侧page处理,抵消page本身的滑动动画
* pageWidth * -position 结果为正 左侧向右
*/
page.setTranslationX(pageWidth * -position);
}
if (position <= -1.0f || position >= 1.0f) {
/**
* (-& ~ -1),(1 ~ +&)不可见部分不作处理
*/
} else if (position == 0.0f) {
/**
* 当前页面
*/
} else {
/**
* [-1,1] 此时 postion为相反数
* 针对具体的View,移动产生视差
*/
if (backgroundView != null) {
backgroundView.setAlpha(1.0f - Math.abs(position));
}
if (text_head != null) {
text_head.setTranslationX(pageWidth * position);
text_head.setAlpha(1.0f - Math.abs(position));
}
if (text_content != null) {
text_content.setTranslationX(pageWidth * position);
text_content.setAlpha(1.0f - Math.abs(position));
}
if (object1 != null) {
object1.setTranslationX(pageWidth * position);
}
// parallax effect
if (object2 != null) {
object2.setTranslationX(pageWidth * position);
}
if (object4 != null) {
object4.setTranslationX(pageWidth / 2 * position);
}
if (object5 != null) {
object5.setTranslationX(pageWidth / 2 * position);
}
if (object6 != null) {
object6.setTranslationX(pageWidth / 2 * position);
}
if (object7 != null) {
object7.setTranslationX(pageWidth / 2 * position);
}
if (object8 != null) {
object8.setTranslationX((float) (pageWidth / 1.5 * position));
}
if (object9 != null) {
object9.setTranslationX(pageWidth / 2 * position);
}
if (object10 != null) {
object10.setTranslationX(pageWidth / 2 * position);
}
if (object11 != null) {
object11.setTranslationX((float) (pageWidth / 1.2 * position));
}
if (object12 != null) {
object12.setTranslationX((float) (pageWidth / 1.3 * position));
}
if (object13 != null) {
object13.setTranslationX((float) (pageWidth / 1.8 * position));
}
if (object3 != null) {
object3.setTranslationX((float) (pageWidth / 1.2 * position));
}
}
}
}
它主要实现PageTransformer这个接口,里面只需要重新写一个方法transformPage(View page, float position)这个一个方法page就是显示的View这里的position不是滑动view的位置position,因为他是一个浮点型的。为了通俗简单概括,可以这么理解:
现在从右往左滑动,page0为当前屏幕page1为即将出现的页面。那么没滑动之前position为0和1,在滑动过程完成后为-1,0.我们就可以理解0时为我们可见页面。1为右侧页面,-1为左侧页面。滑动时是已浮点数不断变化的。这里的position可以为2个数值,最大为3个数值。在理解之后我们知道他一共有几个区间:
if (position <= -1.0f || position >= 1.0f) {
/**
* (-& ~ -1),(1 ~ +&)不可见部分不作处理
*/
} else if (position == 0.0f) {
/**
* 当前页面
*/
} else
/**
* [-1.1] 即将显示在屏幕的区间
* 这里有可以分成[-1,0]从左往右滑动和从右往左滑动(0,1]
* 此时在2中情况 position互为相反数 所以我们做平移变化时
* 在这个if语句中做 *这样根据左右滑动与position的关系做出我们想要的动画
*/
}
在弄清楚我们应该在那个区间做我们想要的动画后就开始做我们想要的动画。我这里做的是平移和透明度。如果你有更好的想法,就看你像这么修改了。这里面参数为可要用*postion因为他有正负这份这样我们就不用去判断平移的方向了。
结语
其实实现起来还是比较简单的。这个效果的难点在于对transformPage的理解和动画实现的参数方式。下面我在给大家推荐几篇文章,方便大家理解。