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

实现效果

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

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

大致思路

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

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

个人认为更加好看一点的平滑方法是这样:
这里写图片描述

  1. 取两圆圆心连线上的一点A,此点离两圆心距离与两圆各自半径成正比。
  2. 找到此点到两圆的外切点。
  3. 以两圆圆心连线一侧的两个切点(分别在两个圆上的)为端点,以步骤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);
        }
    ...
    });
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值