您的位置:首页 > 移动开发 > Android开发

安卓自定义view,实现页面切换的位置指示动画

2017-01-13 15:12 459 查看

实现效果

360手机桌面的页面切换效果看上去好像蛮酷炫的,大致效果如下(细节略有些不同)



于是研究了一下怎么在安卓上实现。

大致思路

这玩意儿的难点在于,如何用平滑曲线,把两个圆连接起来。

网上有一些文章,介绍了一些方法,比如这里,但是看上去不是很平滑,视觉效果貌似差一些。

个人认为更加好看一点的平滑方法是这样:



取两圆圆心连线上的一点A,此点离两圆心距离与两圆各自半径成正比。

找到此点到两圆的外切点。

以两圆圆心连线一侧的两个切点(分别在两个圆上的)为端点,以步骤1中的点A为控制点,做二阶贝塞尔曲线。

二阶贝塞尔曲线,画起来很麻烦吧?。。。No no, 安卓sdk里面画贝塞尔曲线的函数(Path类下quadTo())都写好了,调用一下就行。

下一步就是要确定两个圆的位置和大小。ViewPager的 OnPageChangeListener的回调 onPageScrolled(int position, float positionOffset, int positionOffsetPixels) 给出了当前的position(位置的index)和positionOffset(滑动切换的进度,在0到1之间),所以我们需要根据这两个参数来确定两个圆的位置。

背景上不变的有几个圆,等间距分布,它们的半径就是最大半径R_max。很显然:背景圆的圆心,和这两个园的圆心都应该在一条水平线上。一下简称第一个圆形C1(circle1),第二个圆形 C2.

1 当positionOffset是0的时候,C1应该和第position个背景圆重和(半径=R_max),C2半径是0,位置可以放在C1的圆周上。

2 当positionOffset是0.5的时候,C1的圆心在第position个背景圆的圆心上,C2的圆心在第position+1个背景圆的圆心上,同时两圆半径都是R_max/2.

3 当positionOffset是0到0.5之间的时候,两圆的圆心和半径分别根据positionOffset做线性变化,使得 1,2满足。也就是C1圆心一直不变,半径变小;C2在水平移动,同时半径变大。

4 当positionOffset是0.1的时候,C1半径为0,位置在C2圆周上,C2和第position+1个背景圆重和(半径=R_max)。

这样就基本实现了从一个位置到下一个位置的滑动:



show me the code

源码地址: https://github.com/nanyi5452/viewpagerDotIndicator

或者使用gradle直接引入:

allprojects {
repositories {
jcenter()
maven { url "https://jitpack.io" }
}
}
compile 'com.github.nanyi5452:viewpagerDotIndicator:4c0a7bcf83'


简单解释:

PointF p1,p2; 存储C1,C2的圆心位置。

float r1,r2; 存储C1,C2的半径。

Path path; 存储连接C1,C2的平滑曲线。

PointF[] fixedLabels; 存储背景圆的位置

update(final int position, final float progress) 函数根据 position, 和 positionOffset来计算C1,C2以及平滑曲线。注意这些计算放到后台线程执行,计算完毕后通知postInvalid()来绘制。

如何使用:

VpIndicator indicator= (VpIndicator) findViewById(R.id.vp_indicator);
indicator.resetTotalCounts(4);  // 设置页面个数

viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
indicator.update(position,positionOffset);
}
...
});
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐