前言

在现在的婚恋交友app源码设计中,轮播基本成为了每个应用的“标配”,有了轮播,就自然需要有对应的指示器,代表当前轮播的进度,现在市面上指示器的样式大部分都是基于小圆点的形式,实现这个基本的效果网上也有很多轮子,本文主要是在实现基本效果的基础上,在切换圆点之间添加一个粘性过渡的动画效果。

实现思路

绘制圆点

圆点的话基于画笔绘制,将控件宽度平分为N等份,且选中的圆点半径稍大。

圆点之间的联动滚动

支持设置最多显示N个圆点,当圆点总数超过N个时,暂时不显示在婚恋交友app源码控件可见范围内,直到左/右滚动到靠近边界时,自动平移所有圆点,从而让最新选中的圆点再次回到居中的位置。使用属性动画结合横坐标偏移实现。

圆点过渡动画

圆点与圆点之间,如果单纯切换选中,会显得有些生硬,所以要为这个过程添加一些过渡的动画效果,这里采用当下常见的一种“粘性”效果,类似于我们在QQ联系人列表长按拖动未读消息数的效果:

这里婚恋交友app源码基于贝塞尔曲线来实现,通过计算准备过渡的两个圆点的位置,以及它们之间的中心点,可以绘制出上下两条贝塞尔曲线,再闭合起来即可。然后结合属性动画进行移动,完成最终的过渡效果。

实现步骤

1.计算控件宽高

按照设计的效果,控件的宽高取决于小圆点的排列:

控件宽度 = 屏幕中可见的所有小圆点的宽度 * 可见小圆点的数量 + 小圆点之间的间距 * (可见小圆点的数量 - 1)

控件高度 = 最大的小圆点的高度

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);int count = Math.min(totalCount, showCount);int width = (int) ((count - 1) * smallDotWidth + (count - 1) * dotPadding + bigDotWidth);int height = (int) bigDotWidth;final int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);final int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);final int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);final int heightSpecSize = MeasureSpec.getMode(heightMeasureSpec);if (widthSpecMode == MeasureSpec.AT_MOST && heightSpecMode == MeasureSpec.AT_MOST) {setMeasuredDimension(width, height);} else if (widthSpecMode == MeasureSpec.AT_MOST) {setMeasuredDimension(width, heightSpecSize);} else if (heightSpecMode == MeasureSpec.AT_MOST) {setMeasuredDimension(widthSpecSize, height);} else {setMeasuredDimension(width, height);}
}

另外注意婚恋交友app源码最大显示数量的控制,即 int count = Math.min(totalCount, showCount); 如果当前圆点总数超过屏幕可见数,则基于最大可见数来计算控件的宽度。

2.绘制小圆点

在知道小圆点的数量之后,只需要遍历依次绘制即可。考虑到选中的圆点与其他圆点样式上的区别,因此针对当前选中圆点单独设置宽度 bigDotWidth,单独设置颜色 selectColor,如下:

@Override
protected void onDraw(Canvas canvas) {super.onDraw(canvas);float startX = curX;float selectX = 0;for (int i = 0; i < totalCount; i++) {if (curIndex == i) {//绘制选中圆点paint.setColor(selectColor);paint.setStyle(Paint.Style.FILL);selectRectF.left = startX;selectRectF.top = getHeight() / 2f - bigDotWidth / 2;selectRectF.right = startX + bigDotWidth;selectRectF.bottom = getHeight() / 2f + bigDotWidth / 2;canvas.drawCircle(startX + (bigDotWidth) / 2, bigDotWidth / 2, (bigDotWidth) / 2, paint);selectX = startX + bigDotWidth / 2;startX += (bigDotWidth + dotPadding);} else {//绘制其它圆点paint.setColor(defaultColor);paint.setStyle(Paint.Style.FILL);startX += smallDotWidth / 2;canvas.drawCircle(startX, bigDotWidth / 2, (smallDotWidth) / 2, paint);startX += (smallDotWidth / 2 + dotPadding);}}
}

3.左右平移动画

从效果图可以看出,婚恋交友app源码指示器平移的触发时机在于每一次的左右切换,具体需要满足如下条件:

1.当前圆点总数超过最大可见数
2.当前准备切换的下一个圆点在屏幕非中间的位置

第一个条件,圆点总数超过最大可见数才可平移,这个很好理解。第二个是切换的下一个圆点在屏幕非中间位置,这个是平移的一个规则,比如下面的例子:

上图在切换之前,选中的是3,准备切换到4的过程中,由于当前总数为7个,超过最大可见数5个,满足第一个条件,同时由于在切换之前4是处在非屏幕中间的位置,因此满足第二个条件,需要整体向左平移一个单位,使得切换之后,4变成了屏幕中心的位置,逻辑如下:

public void setCurIndex(int index) {if (index == curIndex) {return;}//当前圆点总数超过最大可见数if (totalCount > showCount) {if (index > curIndex) {//往左边滑动int start = showCount % 2 == 0 ? showCount/2 - 1 : showCount / 2;int end = totalCount - showCount / 2;//判断是否需要先滚动if (index > start && index < end) {startScrollAnim(Duration.LEFT, () -> invalidateIndex(index));} else {invalidateIndex(index);}} else {//往右边滑动int start = showCount / 2;int end = showCount % 2 == 0 ? totalCount - showCount / 2 + 1 : totalCount - showCount / 2;//判断是否需要先滚动if (index > start - 1 && index < end - 1) {startScrollAnim(Duration.RIGHT, () -> invalidateIndex(index));} else {invalidateIndex(index);}}} else {invalidateIndex(index);}
}

4.圆点过渡动画

圆点之间的粘性动画,本质上是以前一个圆点作为基准位置,然后平移另外一个圆点的水平位置,使得它们之间的闭合曲线逐渐变化,直到平移到与下一个圆点位置重合,如下:

由红色圆点切换到绿色圆点的过程中,以A点为起始点,连接A点与C点绘制一条贝塞尔曲线,同样,底部B点和D点之间也绘制一条贝塞尔曲线,然后再把AB和CD也连接起来,四条路径形成一条闭合的曲线绘制出来,形成基本的形状。 然后再结合属性动画,使得C点和D点不断向右移动,直到与绿色圆完全重合。 如下:

设置粘性属性动画的起始和结束值:

//当前选中的圆点的水平中心 作为粘性动画起始点
float startValues = getCurIndexX() + bigDotWidth / 2;
//根据方向设置动画的结束值
if (index > curIndex) {stickAnimator.setFloatValues(startValues, startValues + dotPadding + smallDotWidth);
} else {stickAnimator.setFloatValues(startValues, startValues - dotPadding - smallDotWidth);
}

监听动画不断刷新粘性过渡的动画值:

ValueAnimator stickAnimator = new ValueAnimator();
stickAnimator.setDuration(animTime);
stickAnimator.addUpdateListener(animation -> {stickAnimX = (float) animation.getAnimatedValue();invalidate();
});
stickAnimator.removeAllListeners();
stickAnimator.addListener(new AnimatorListenerAdapter() {@Overridepublic void onAnimationEnd(Animator animation) {isSwitchFinish = true;invalidate();}
});
stickAnimator.start();

绘制粘性曲线:

@Override
protected void onDraw(Canvas canvas) {super.onDraw(canvas);if (isSwitchFinish) {//切换完成记得重置路径stickPath.reset();} else {paint.setColor(selectColor);//以当前选中的圆点为绘制起始点float quadStartX = selectX;float quadStartY = getHeight() / 2f - bigDotWidth / 2;stickPath.reset();//连接4个点stickPath.moveTo(quadStartX, quadStartY);stickPath.quadTo(quadStartX + (stickAnimX - quadStartX) / 2, bigDotWidth / 2, stickAnimX, quadStartY);stickPath.lineTo(stickAnimX, quadStartY + bigDotWidth);stickPath.quadTo(quadStartX + (stickAnimX - quadStartX) / 2, bigDotWidth / 2, quadStartX, quadStartY + bigDotWidth);//形成闭合曲线stickPath.close();//绘制过渡过程中的圆canvas.drawCircle(stickAnimX, bigDotWidth / 2, (bigDotWidth) / 2, paint);canvas.drawPath(stickPath, paint);}
}

结语

如果指定了婚恋交友app源码最多显示多少个圆点,则当总数超过时会左右滚动,如果想要非滚动的形式也可以设置为最大圆点数。本控件主要还是通过贝塞尔曲线来制作粘性效果,让动画更为生动,支持设置是否开启粘性效果、粘性动画时长、小圆点选中与非选中时的样式等,后续会再根据需求扩充其它细节。
声明:本文由云豹科技转发自JJ_Yang博客,如有侵权请联系作者删除

婚恋交友app源码,实现一个不一样的轮播指示器相关推荐

  1. 实现婚恋交友app源码,开发一个数字气泡的效果

    简介: 最近婚恋交友app源码中需要展示一个气泡效果,当界面中数量发生变化时,会有一个数量+1的气泡动画,如下图所示: 动效说明: 首先位移起始点是在与数字居中的位置,开始透明度为0%,然后开始向上位 ...

  2. 婚恋交友app源码,搭建一个流媒体服务

    写在前面 最近几年,直播行业比较火,无论是传统行业的直播,还是购物.游戏.教育.婚恋交友app源码,都在涉及直播.作为在互联网行业奋斗了多年的小伙伴,你有没有想过如果使用Nginx搭建一套婚恋交友ap ...

  3. 实现婚恋交友app源码的屏幕适配,需要知道哪些

    大家在开发Android端的婚恋交友app源码时,肯定会觉得屏幕适配是个尤其痛苦的事,各种屏幕尺寸适配起来巨烦无比.如果我们换个角度我们看下这个问题,不知道大家有没有了解过web前端开发,或者说大家对 ...

  4. 婚恋交友app源码,实现数据一致性的方案

    什么是缓存? 缓存就是数据交换的缓冲区,针对服务对象的不同(本质就是不同的硬件)都可以构建缓存. 婚恋交友app源码使用缓存目的是,把读写速度慢的介质的数据保存在读写速度快的介质中,从而提高读写速度, ...

  5. 婚恋交友app源码,你要了解数据结构

    1.介绍链栈 所谓链栈,就是用链表存储结构实现的栈.采用链栈,可以不事先估计栈的最大容量,只要婚恋交友app源码有足够的空间,链栈就不会溢出,在使用完后,应与链表一样,给予相应的内存释放. 2.代码实 ...

  6. 婚恋交友app源码,如何自定义线程池

    自定义线程池是婚恋交友app源码开发会用到的,那么婚恋交友app源码是怎样实现的呢? 1.任务队列 2.拒绝策略(抛出异常.直接丢弃.阻塞.临时队列) 3.init( min ) 4.active 5 ...

  7. java社交婚恋交友app源码 安卓原生app+后台Spri ngMVC+Mybatis+mysql

    java社交婚恋交友app源码 安卓原生app+后台Spri ngMVC+Mybatis+mysql

  8. 婚恋交友app源码,如何进行代码优化

    安卓平台的手持设备是嵌入式设备,我们考虑内存.电池使用的问题,所以在编写婚恋交友app源码时应尽可能的优化,提高效率. 延迟使用对象 我们应该减少不要对象的创建,理论上创建的对象越少就意味着越少的垃圾 ...

  9. 婚恋交友app源码,礼物功能如何实现

    礼物功能是婚恋交友app源码比较重要的功能,接下来就让我们一起看看婚恋交友app源码是怎么实现的. ​ public function index(){$touid = I("get.uid ...

最新文章

  1. fmincon函数求解过程中出现无解的情况
  2. Linux Crontab 设置的定时任务没有启动的排查
  3. 如何有效地管理测试用例
  4. tensorflow官方posenet模型解析
  5. 文本过滤后返回空值_利用Fiddler来Mock接口返回值
  6. 拼多多前端岗位笔试试题 问答题部分 2017/8/1
  7. 阿里天池大赛实战记录之菜鸟-需求预测与分仓规划
  8. 利用OpenCV将图片反色
  9. 贴上AI标签的综艺,未来的模样你敢想象吗?
  10. LeetCode知识点总结 - 868
  11. mysql error 1_mysql 启动错误(InnoDB: Operating system error number 1
  12. 硬件茶谈(B站up主爱上半导体)
  13. 随机密码生成(Python编程)
  14. UUID简介以及java代码获取UUID示例
  15. kindeditor 自定义上传图片
  16. 测试评审方法---验证与确认
  17. POJ前面的题目算法思路【转】
  18. linux之tomcat安装及前端部署
  19. MAGSAC:Marginalizing Sample Consensus
  20. 广州数据中心机房机柜安装施工

热门文章

  1. 软银暂停投资中国,随后“秒删”!孙正义不和中国玩了?
  2. BGP之IBGP和EBGP基本配置详解,理论+实战,两分钟快速掌握
  3. 电表远程抄表在配电房内的使用
  4. 数据建模基础知识——实体关系图
  5. 成功不难,改变习惯而已!
  6. 身份证号码前六位备份
  7. Python入门基础学习笔记
  8. MacBook Pro M1 Parallels Desktop 安装Win11
  9. 【移动手游UI设计】笔记
  10. (XK01/XK02/XK03/MK01/MK02/MK03)供应商主数据增强