Android打造不一样的新手引导页面(二)


本系列主要分为两篇博客

打造不一样的新手引导页面(一)

Android打造不一样的新手引导页面(二)

关于页面导航器的,可以查看我的这一篇博客仿网易新闻的顶部导航指示器

上一篇博客主要讲解怎样自定义一个CirclePageIndicator控件

这篇博客主要讲解怎样更改ViewPager切换的效果。

首先我们先来看一下默认的ViewPager的切换效果,感觉是不是很普通,因为大多数时候我们经常没有用到ViewPager的动画切换效果 ,这种想过见多了,也就觉得平淡了

下面我们来看一下我们自己实现的ViewPager页面的 切换效果,总共有 四种不同的样式

实现原理说明

其实要实现上述的 效果非常简单,只需要以下几行代码,就搞定了。

viewpager.setPageTransformer(true, new  ViewPager.PageTransformer() {@Overridepublic void transformPage(View page, float position) {// do transformation here}
});

Google官方关于两个参数的解释是

reverseDrawingOrder boolean: true if the supplied PageTransformer requires page views to be drawn from last to first instead of first to last.

transformer ViewPager.PageTransformer: PageTransformer that will modify each page’s animation properties

第一个布尔型参数表示的意思就是在两个页面切换产生动画效果时候是否要反转一下让下一个页面在上一个页面底下,因为ViewPager默认下一个页面是绘制在上一个页面的上面,这里一般传入true。

第二次参数才是重点,这里实现了PageTransformer接口,然后我们所有需要的动画效果都在transformPage这个接口方法里面实现,现在我们来看看这个方法。

transformPage void transformPage (View page, float position)

page View: Apply the transformation to this page
position

float: Position of page relative to the current front-and-center position of the pager. 0 is front and center. 1 is one full page position to the right, and -1 is one page position to the left.

下面我们借用一张图片来解释position的变化

假设当前我们屏幕中的页面是B:

  • 那么该页面的position是1,A页面的position是-1,C页面的position是1.
  • 当我们从B页面滑到c页面的时候,B页面的变化是从0减少到-1,C页面的 变化是从1减少到0,A页面的变化是从从-1向负无穷变化。当我们切好滑动到一半的时候B页面的position是-0.5,c页面的position是0.5。
  • 当我们从B页面滑动到A页面的时候,B页面的变化是【0,1】,A页面的变化是【-1,0】,c页面的变化是从1向正无穷变化

解释完这些参数是什么意思,下面让我们来看一下我们是怎样实现的

Google的两个例子

首先我们先来看一下官方的两个例子,地址是:http://developer.android.com/training/animation/screen-slide.html

ZoomOutPageTransformer

public class ZoomOutPageTransformer implements ViewPager.PageTransformer {private static final float MIN_SCALE = 0.85f;private static final float MIN_ALPHA = 0.5f;public void transformPage(View view, float position) {int pageWidth = view.getWidth();int pageHeight = view.getHeight();if (position < -1) { // [-Infinity,-1)// This page is way off-screen to the left.view.setAlpha(0);} else if (position <= 1) { // [-1,1]// Modify the default slide transition to shrink the page as wellfloat scaleFactor = Math.max(MIN_SCALE, 1 - Math.abs(position));float vertMargin = pageHeight * (1 - scaleFactor) / 2;float horzMargin = pageWidth * (1 - scaleFactor) / 2;if (position < 0) {view.setTranslationX(horzMargin - vertMargin / 2);} else {view.setTranslationX(-horzMargin + vertMargin / 2);}// Scale the page down (between MIN_SCALE and 1)view.setScaleX(scaleFactor);view.setScaleY(scaleFactor);// Fade the page relative to its size.view.setAlpha(MIN_ALPHA +(scaleFactor - MIN_SCALE) /(1 - MIN_SCALE) * (1 - MIN_ALPHA));} else { // (1,+Infinity]// This page is way off-screen to the right.view.setAlpha(0);}}
}

运行到上述的代码,效果图如下

从上述效果图可以看到,页面切换的时候,主要是页面大小的 变化,水平移动距离的变化以及透明度的变化,这些也可以从代码中体现回来,我们主要关心[-1,1]的时候就OK,因为在[-Infinity,-1)和(1,+Infinity]的时候是不可见的。

if (position < -1) { // [-Infinity,-1)// This page is way off-screen to the left.page.setAlpha(0);} else if (position <= 1) { // [-1,1]// Modify the default slide transition to shrink the page as wellfloat scaleFactor = Math.max(MIN_SCALE, 1 - Math.abs(position));float vertMargin = pageHeight * (1 - scaleFactor) / 2;float horzMargin = pageWidth * (1 - scaleFactor) / 2;if (position < 0) {page.setTranslationX(horzMargin - vertMargin / 2);} else {page.setTranslationX(-horzMargin + vertMargin / 2);}// Scale the page down (between MIN_SCALE and 1)page.setScaleX(scaleFactor);page.setScaleY(scaleFactor);// Fade the page relative to its size.page.setAlpha(MIN_ALPHA +(scaleFactor - MIN_SCALE) /(1 - MIN_SCALE) * (1 - MIN_ALPHA));} else { // (1,+Infinity]// This page is way off-screen to the right.page.setAlpha(0);
}

DepthPageTransformer

public class DepthPageTransformer implements ViewPager.PageTransformer {private static final float MIN_SCALE = 0.75f;public void transformPage(View view, float position) {int pageWidth = view.getWidth();if (position < -1) { // [-Infinity,-1)// This page is way off-screen to the left.view.setAlpha(0);} else if (position <= 0) { // [-1,0]// Use the default slide transition when moving to the left pageview.setAlpha(1);view.setTranslationX(0);view.setScaleX(1);view.setScaleY(1);} else if (position <= 1) { // (0,1]// Fade the page out.view.setAlpha(1 - position);// Counteract the default slide transitionview.setTranslationX(pageWidth * -position);// Scale the page down (between MIN_SCALE and 1)float scaleFactor = MIN_SCALE+ (1 - MIN_SCALE) * (1 - Math.abs(position));view.setScaleX(scaleFactor);view.setScaleY(scaleFactor);} else { // (1,+Infinity]// This page is way off-screen to the right.view.setAlpha(0);}}
}

运行上述代码以后,可以看到的变化是


下面来看一下我们自己实现的两个例子

看到上述图以后,仔细分析可以看到在我们滑动的时候主要是旋转角度的 变化,并且Y轴旋转中心是页面的中心点,当position<0的时候,X轴的中心是view.getWidth,当position>0的时候,x轴的中心是0,代码如下。

public class CubeOutTransformer extends BaseTransformer {@Overrideprotected void onTransform(View view, float position) {view.setPivotX(position < 0f ? view.getWidth() : 0f);view.setPivotY(view.getHeight() * 0.5f);view.setRotationY(90f * position);}@Overridepublic boolean isPagingEnabled() {return true;}}

TableTransformer

public class TableTransformer extends BaseTransformer {private static final Matrix OFFSET_MATRIX = new Matrix();private static final Camera OFFSET_CAMERA = new Camera();private static final float[] OFFSET_TEMP_FLOAT = new float[2];private static final float  minScale=0.6f;@Overrideprotected void onTransform(View view, float position) {final float rotation = (position < 0 ? 30f : -30f) * Math.abs(position);view.setTranslationX(getOffsetXForRotation(rotation, view.getWidth(), view.getHeight()));view.setPivotX(view.getWidth() * 0.5f);view.setPivotY(0);view.setRotationY(rotation);float scaleX=Math.max(1-Math.abs(position),minScale);view.setScaleX(scaleX);}protected static final float getOffsetXForRotation(float degrees, int width, int height) {OFFSET_MATRIX.reset();OFFSET_CAMERA.save();OFFSET_CAMERA.rotateY(Math.abs(degrees));OFFSET_CAMERA.getMatrix(OFFSET_MATRIX);OFFSET_CAMERA.restore();OFFSET_MATRIX.preTranslate(-width * 0.5f, -height * 0.5f);OFFSET_MATRIX.postTranslate(width * 0.5f, height * 0.5f);OFFSET_TEMP_FLOAT[0] = width;OFFSET_TEMP_FLOAT[1] = height;OFFSET_MATRIX.mapPoints(OFFSET_TEMP_FLOAT);return (width - OFFSET_TEMP_FLOAT[0]) * (degrees > 0.0f ? 1.0f : -1.0f);}
}

到此我们的源码分析为止


题外话

如果各位觉得还行的话,欢迎在github上面 star或者 fork,谢谢 ,github项目地址ViewPagerTabIndicator

转载请注明原博客地址

源码下载地址:

Android打造不一样的新手引导页面(二)相关推荐

  1. Android 仿当乐游戏详情页面(二)

    写在前面 在上一篇文章里面,基本上算是实现了该效果的布局,有了布局,接下来就要对布局进行移动处理. android 仿当乐游戏详情页面(一) 对于移动的分析 通过第一篇文章的分析,在所有控件里面,能移 ...

  2. 微信扫描二维码和浏览器扫描二维码 ios和Android 分别进入不用的提示页面

    实现微信扫描二维码和浏览器扫描二维码 ios和Android 分别进入不用的提示页面 而进入商城下载该项目 详情地址:gitee.com/DuJiaHui123- 1.创建完之后 替换文件里面的ios ...

  3. 树莓派 + Home Assistant + HomeKit 从零开始打造个人智能家居系统 篇二:初步配置 Home Assistant 并连接小米设备与 HomeKit

    树莓派 + Home Assistant + HomeKit 从零开始打造个人智能家居系统 篇二:初步配置 Home Assistant 并连接小米设备与 HomeKit 通过本篇教程,你将完成对 H ...

  4. 【Android 组件化】路由组件 ( 页面跳转参数依赖注入 )

    文章目录 一.参数自动注入 二.自定义注解 三.使用 @Extra 自定义注解 四.注解处理器解析 @Extra 自定义注解 并生成相应 Activity 对应代码 五.博客资源 组件化系列博客 : ...

  5. Android 打造完美的侧滑菜单/侧滑View控件

    概述 Android 打造完美的侧滑菜单/侧滑View控件,完全自定义实现,支持左右两个方向弹出,代码高度简洁流畅,兼容性高,控件实用方便. 详细 代码下载:http://www.demodashi. ...

  6. Android学习之登陆界面设计(二)基本界面设计

    Android学习之登陆界面设计(二)基本界面设计 前提 绘图样式 - drawable bg_login_btn_submit.xml bg_login_panel_slide.xml bg_log ...

  7. Android开发日志打卡APP(二)

    Android开发日志打卡APP(二) 文章目录 Android开发日志打卡APP(二) 前言 开发过程 一.背景和标题 二.日志图标 三.日志弹框 前言 在之前的文章中,准备工作已经完成,现在我们将 ...

  8. 【Android项目实战 | 从零开始写app(十二)】实现app首页智慧服务热门推荐热门主题、新闻

    说在前面,由于各种adapter,xml布局,bean实体类,Activity,也为了让看懂,代码基本都是"简单粗暴直接不好看",没啥okhttp和util工具类之类的封装,本篇幅 ...

  9. Django+xadmin 打造线上教育平台(二)登录-注册(重制)

    Django+xadmin 打造线上教育平台(二) 一.首页 1)views.py/index函数: def index(request):"""首页"&quo ...

最新文章

  1. 如何通过抓包实战来学习Web协议?
  2. vs 设置调试路径为exe所在的路径
  3. SQL Server2019数据库查询所有数据库名、表名、表结构、表字段、主键方法演示,执行sql提示对象名‘user_tab_columns‘、 ‘user_cons_columns‘ 无效问题解决
  4. Angular应用i18n - internationalization翻译的实现单步调试
  5. POJ - 3734 Blocks 指数生成函数
  6. Maven 系列 2:Maven 本地仓库与远程仓库配置完整步骤以及修改 settings.xml 后的完整内容(配置非私服,远程仓储镜像强力推荐阿里云)
  7. python复数的实部和虚部都是整数嘛_Python学习笔记:从入门到放弃(2)基本语法...
  8. linux grep awk head 的使用
  9. java解析XML【转载】
  10. CSS综合案例——淘宝焦点图(轮播图)布局及网页布局总结
  11. pe_xscan做了几个改动
  12. 迈达斯cdn安装_PSC桥梁跟随例题-CDN
  13. Kafka报错:Couldn't find leaders for Set
  14. 漫画:如何给女朋友解释灭霸的指响并不是真随机消灭半数宇宙人口的?
  15. DPDKVPP关键技术文档总结
  16. linux5关闭apic服务,Linux中断 - APIC
  17. 【JavaScript 逆向】极验三代无感验证码逆向分析
  18. 使用composer开发dfc程序
  19. FFT快速傅立叶变换在示波器中的用法
  20. 机器人的「语料」,如何获取?

热门文章

  1. PanGu STM32MP开发板更新固件
  2. NIUSHOP商城系统短信宝短信插件
  3. 通用权限管理系统组件 (GPM - General Permissions Manager) 不需要任何配置文件,程序都可以正常运行...
  4. 网页安全之页面禁用复制粘贴
  5. GIS在线学堂开课招生了
  6. 财报解读:赢了利润的京东不想打恶性“价格战”
  7. 你见过哪些好用到爆的 Java 代码技巧?
  8. 《龙虎门》--动作电影新希望
  9. Apache Beam中python常用函数(二):聚合函数
  10. 极限竞速地平线4 没声音_极限竞速:地平线是汽车爱好者的食物