一.使用最简单的方式创建Android应用引导页(效果如下)
该引导仅需要一个ViewPager和一个ViewPager适配器即可完成。
接下来,小编将从零开始讲解该引导如何实现,准备好了没O(∩_∩)O~,小司机要开车了...
1.首先,为我们的GuideActivity创建一个布局文件(非常简单的布局)。
2.接下来,完成GuideActivity(引导活动页面)。
public class GuideActivity extends AppCompatActivity {
private ViewPager mViewPager;
private ViewPagerAdapter mViewPagerAdapter; // ViewPager适配器
private int[] images; // 图片资源引用数组(填充引用图片的Id)
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initToolbar(); // 初始化标题栏
initView(); // 初始化视图
initData(); // 初始化数据
}
/**
* 初始化标题栏
*/
private void initToolbar() {
getSupportActionBar().hide(); // 隐藏标题栏
}
/**
* 初始化视图
*/
private void initView() {
mViewPager = (ViewPager) findViewById(R.id.viewpager);
}
/**
* 初始化数据
*/
private void initData() {
images = new int[]{R.mipmap.guide_page_one, R.mipmap.guide_page_two, R.mipmap.guide_page_three, R.mipmap.guide_page_four};
mViewPagerAdapter = new ViewPagerAdapter(GuideActivity.this, images);
mViewPager.setAdapter(mViewPagerAdapter);
}
}
图片资源需要各位自己准备,小编就不提供了...O(∩_∩)O~
我们的GuideActivity只是完成了一部分,因为ViewPagerAdapter我们还没有构建,别急...接下来就是它了...
3.最后,构建ViewPager的适配器ViewPagerAdapter。
/**
* @ClassName: ViewPagerAdapter
* @Description: ViewPager适配器
* @Author Wangnan
* @Date 2016/8/25
*/
public class ViewPagerAdapter extends PagerAdapter {
private Context mContext;
private int[] images; // 图片资源引用数组
public ViewPagerAdapter(Context context, int[] datas){
images = datas;
mContext = context;
}
/**
* 获取数据(图片)数量
* @return
*/
@Override
public int getCount() {
return images.length;
}
/**
* 当前View是否是instantiateItem中返回的对象
* @param view 当前view
* @param object 由instantiateItem()方法返回的对象
* @return
*/
@Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
/**
* 初始化Item并向页面添加
* @param container ViewPager
* @param position 要实例化item对应的页面位置
* @return
*/
@Override
public Object instantiateItem(ViewGroup container, int position) {
ImageView mImageView = createImageView(mContext, position);
container.addView(mImageView);
return mImageView;
}
/**
* 移除ViewPager中的Item
* @param container viewpager
* @param position 要移除页面的位置
* @param object 要移除页面的对象
*/
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View)object);
}
/**
* 创建ImageView
* @param mContext
* @param position
* @return imageView
*/
private ImageView createImageView(Context mContext, int position) {
ImageView imageview = new ImageView(mContext);
ViewPager.LayoutParams layoutParams = new ViewPager.LayoutParams(); // 等价于ViewGroup.LayoutParams(FILL_PARENT, FILL_PARENT)
imageview.setLayoutParams(layoutParams); // 设置ImageView充满父容器
imageview.setImageResource(images[position]); // 设置ImageView的显示图片
imageview.setScaleType(ImageView.ScaleType.CENTER_CROP); // 设置ImageView缩放样式
return imageview;
}
}
这段代码可能对于初学者来讲很难理解,但小编已经做了很详细的解释。另外,小编仅教给大家如何使用,如果大家想要理解这些方法的调用原理,可以去查阅PagerAdapter的相关源码...
二.使用PageTransformer打造炫酷翻转动画
1.首先来看下Google为我们提供的样例DepthPageTransformer(下图为运行效果)
是不是感觉很神奇,接下来我们就看看如何使用PageTransformer实现这种效果...
(1).创建DepthPageTransformer(深度效果页面转换器)
/**
* @ClassName: DepthPageTransformer
* @Description: 深度效果页面转换器
* @Author Wangnan
* @Date 2016/8/25
*/
public class DepthPageTransformer implements ViewPager.PageTransformer{
private static final float MIN_SCALE = 0.75F; // 最小缩放比例
@Override
public void transformPage(View page, float position) {
if(position < -1){ // [负无穷,-1):当前页面已经滑出左边屏幕,我们已经看不到了
page.setAlpha(0F);
} else if (position <= 0){ // [-1, 0]:当前页面向左画出,已远离中心位置,但还未滑出左屏幕
page.setAlpha(1F);
page.setTranslationX(0F);
page.setScaleX(1F);
page.setScaleY(1F);
} else if (position <= 1){ // (0,1]:下一页面已经进入屏幕,但还在进入并未到达中间位置
page.setAlpha(1 - position);
page.setTranslationX(page.getWidth() * -position);
float scale = MIN_SCALE + (1 - MIN_SCALE) * (1 - position);
page.setScaleX(scale);
page.setScaleY(scale);
} else { // (1, 正无穷]:下一页面还未进入屏幕
page.setAlpha(0F);
}
}
}
小编对Google提供的样例进行了简单的说明...里面涉及到一些View的样式设置和偏移计算,可能新手朋友们有些难以理解,这里小编进行下详细的说明...老司机们可略过...O(∩_∩)O~
当新页面还未进入屏幕的之前,我们使用page.setAlpha(0F),使新页面View保持透明...
当新页面正在进入屏幕时:
page.setAlpha(1 - position),使新页面逐渐变得可见;
page.setTranslationX(page.getWidth() * -position),使新页面的X轴的偏移量从负的屏幕宽度变为0(即View从左向右平移),因为新页面又是从右向左滑入的,这两种滑动效果在视觉上抵消了...我们会感觉到页面没有出现过平移;
page.setScaleX(scale)和page.setScaleY(scale)设置X轴方向和Y轴方向的页面缩放,从新页面进入的角度看页面是从原页面大小的0.75倍增加到1倍...scale的范围是[0.75,1],scale的计算就不再细说了...
当旧页面向左滑出还未出边界时:
page.setAlpha(1F); 保持透明度完全可见
page.setTranslationX(0F); 保持X轴的偏移量为0
page.setScaleX(1F); 保持X轴方向缩放为视图原大小
page.setScaleY(1F);保持Y轴方向缩放为视图原大小
当旧页面向左滑出左边界时,我们已经看不到该视图了,page.setAlpha(0F),使滑出去的旧页面View保持透明...
(2).说了这么多,如何使用DepthPageTransformer呢?
别担心!仅需一行代码...我们在刚写完的GuideActivty的initData方法最后添加一行代码(如下图所示):
mViewPager.setPageTransformer(true, new DepthPageTransformer());
public class GuideActivity extends AppCompatActivity {
......
/**
* 初始化数据
*/
private void initData() {
images = new int[]{R.mipmap.guide_page_one, R.mipmap.guide_page_two, R.mipmap.guide_page_three, R.mipmap.guide_page_four};
mViewPagerAdapter = new ViewPagerAdapter(GuideActivity.this, images);
mViewPager.setAdapter(mViewPagerAdapter);
mViewPager.setPageTransformer(true, new DepthPageTransformer());
}
}
这样,我们的代码就完成了,上图的效果就出来了...
接下来我们简单介绍一下ViewPager的setPageTransformer方法。
setPageTransformer(boolean reverseDrawingOrder, PageTransformer transformer)
方法作用:允许应用程序为每一个页面自定义属性转换,重写默认的滑动外观。(注:API>=11才可使用)
第2个参数(transformer):传入自定义PageTransformer,修改每一个页面的动画属性。
第1个参数(reverseDrawingOrder):是否反转绘制顺序。
false(正常顺序 - first to last)从第一页开始绘制至最后一页
true(反转顺序 - last to first)从最后一页开始绘制至第一页
是不是好奇我们传true或false有何区别?
如果传入false,即mViewPager.setPageTransformer(false, new DepthPageTransformer());后面页面是后绘制的,所以后页面的View悬浮在前一页面的View之上,直白点讲,前面的视图无法遮住后面的视图,滑动效果如下图所示:
如果传入true,即mViewPager.setPageTransformer(true, new DepthPageTransformer());前面页面是后绘制的,所以前面页面的View悬浮在后一页面的View之上,直白点讲,前面的视图可以遮住后面的视图,效果如下图所示
2.自定义自己的PageTransformer
我们仿照Google提供的样例,写一个旋转的视图切换效果,这次先上代码,再给大家看效果。
1.定义旋转页面转换器RotatePageTransformer
/**
* @ClassName: RotatePageTransformer
* @Description: 旋转页面转换器
* @Author Wangnan
* @Date 2016/8/25
*/
public class RotatePageTransformer implements ViewPager.PageTransformer {
private float maxRotate = 90f; // 最大旋转角度
@Override
public void transformPage(View page, float position) {
if (position < -1){
page.setPivotX(page.getWidth());
page.setPivotY(page.getHeight() / 2);
page.setRotationY(-maxRotate);
}else if(position < 0){
page.setPivotX(page.getWidth() * (0.5f + 0.5f * (- position))); // X轴支点坐标变化范围[page.getWidth()/2, page.getWidth()]
page.setPivotY(page.getHeight() / 2);
page.setRotationY(maxRotate * position);
}else if(position <= 1){
page.setPivotX(page.getWidth() * 0.5f * (1 - position)); // // X轴支点坐标变化范围[0, page.getWidth()/2]
page.setPivotY(page.getHeight() / 2);
page.setRotationY(maxRotate * position);
}else{
page.setPivotX(0);
page.setPivotY(page.getHeight() / 2);
page.setRotationY(maxRotate);
}
}
}
2.在GuideActivity中使用RotatePageTransformer。
public class GuideActivity extends AppCompatActivity {
......
/**
* 初始化数据
*/
private void initData() {
images = new int[]{R.mipmap.guide_page_one, R.mipmap.guide_page_two, R.mipmap.guide_page_three, R.mipmap.guide_page_four};
mViewPagerAdapter = new ViewPagerAdapter(GuideActivity.this, images);
mViewPager.setAdapter(mViewPagerAdapter);
mViewPager.setPageTransformer(false, new RotatePageTransformer());
}
}
然后我们看下视图效果:
最后解释下RotatePageTransformer中出现的3个方法:
- page.setPivotX(float pivotX); 设置View的X轴支点,影响视图的旋转和缩放效果。
- page.setPivotY(float pivotY); 设置View的Y轴支点,影响视图的旋转和缩放效果。
- page.setRotationY(float rotationY); 设置View绕Y轴旋转的角度。
支点是一个很神奇的属性,大家可以尝试改变它的值看下新的视图效果。
我们的设置Y轴支点始终保持为当前View高度的一半:page.setPivotY(page.getHeight() / 2);
现在,我们改变下Y轴支点的值,使Y轴支点始终保持为当前View的高度:page.setPivotY(page.getHeight()),运行后再来看下效果:
看来这种场景下,旋转效果没有之前的好看,但如果是水平方向的矩形图片,效果就绚丽多了...
还有一些其他效果,简单展示一下,代码实现相对简单就不再贴源码了...
折叠效果(前一页的滑动速度是后一页的两倍)
限于篇幅原因,ViewPager的简单使用我们就写到这了,后续小编还准备出几篇ViewPager的进阶使用,请各位敬请期待。