/   今日科技快讯   /

近日微信支付分正式全面开放,用户可以直接查询并通过支付分来获得免押服务。目前,微信用户直接打开微信>我>钱包,就可以查看自己的支付分。与支付宝的芝麻信用类似,每月初,微信会根据身份特质、支付行为、信用历史这三重标准,来对每位用户的支付分进行新一轮评估。

/   作者简介   /

周五了,终于又可以放松和休息一下了,祝大家周末愉快。

本篇文章转自 明朗__ 的博客,分享了一个炫酷的动画效果,希望对大家有所帮助!

原文地址:

https://www.jianshu.com/p/dd29f1ae5239

/   前言   /

当pm制定完下一版本需求打开马蜂窝旅游app准备出去嗨一圈的时候 看到了马蜂窝旅游app的一个用户头像动画后。。。(=@__@=) 先看看效果图

效果分析:

  1. 涉及到有多个view在做动画操作 这里需要继承FrameLayout来左父布局 供图片做动画操作

  2. 每个子view的动画路径类似于S型 我这里采用的是三阶贝塞尔曲线和PathMeasure来完成动画运动路径的封装

  3. 每个子view动画执行完后 是移除添加新的view进来 还是回收重新利用 本案例是直接移除再添加新的(回收重新利用还没来得及去考虑该怎么写)

  4. 动画是循环不停的播放 我采用的是RxJava timer()操作符 不断的发送随机延迟消息去通知动画的执行

  5. 最后就剩下一些停止动画操作的开关设定

/   实现步骤   /

1. 一些基本的初始化工作

public class HeadBubbleView extends FrameLayout {//这个position很重要 不断的取出图片资源 靠它累加完成的private int position = 0;public HeadBubbleView(@NonNull Context context) {this(context,null);}public HeadBubbleView(Context context, AttributeSet attrs) {super(context, attrs);mContext = context;setFocusable(false);//三阶贝塞尔曲线控制点一controlPointOne = new Point();//三阶贝塞尔曲线控制点二controlPointTwo = new Point();//每个子view的宽高是固定的viewWidth = viewHeight = SizeUtils.dp2px(context, 22);marginLeft = SizeUtils.dp2px(context, 15);marginBot = SizeUtils.dp2px(context, 21);//父View的高度也是固定的height = SizeUtils.dp2px(context, 130);//用于从PathMeasure 中不断的取出 曲线的路径值pos = new float[2];tan = new float[2];initView();}

2. 初始化的时候数据的加载状态

private void initView() {//这个ImageView将不执行动画 用于底部不断切换图片展示tempImageView = getImageView();textView = getTextView();initData(tempImageView);}
//创建执行动画的具体角色
private ImageView getImageView() {LayoutParams layoutParams = new LayoutParams(viewWidth, viewHeight);ImageView roundedImageView = new ImageView(getContext());roundedImageView.setScaleType(ImageView.ScaleType.FIT_XY);layoutParams.gravity = Gravity.BOTTOM | Gravity.END;layoutParams.setMargins(0, 0, marginLeft, marginBot);addView(roundedImageView, layoutParams);return roundedImageView;}
//创建用于显示坐标xx来过的TextView
private TextView getTextView() {int bottom = SizeUtils.dp2px(mContext, 23);int right = SizeUtils.dp2px(mContext, 41);LayoutParams layoutParams = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);layoutParams.gravity = Gravity.END | Gravity.BOTTOM;layoutParams.setMargins(0, 0, right, bottom);TextView tv_name = new TextView(mContext);tv_name.setTextSize(12);tv_name.setTextColor(Color.WHITE);addView(tv_name, layoutParams);return tv_name;}
//第一次加载数据
private void initData(ImageView roundedImageView) {if (null != browseEntities && browseEntities.size() > 0) {//第一次去第0个数据BrowseEntity browseEntity = browseEntities.get(position);if (null != browseEntity) {roundedImageView.setBackgroundResource(browseEntity.drawableId);String username = browseEntity.name;if (!TextUtils.isEmpty(username)) {textView.setText(username + "来过");}}}}

由上面的操作就完成基础显示

3. 接下来完成第一阶段动画 由最小缩放到最大

private boolean createAnimView() {if (!isStop) {return true;}ImageView imageView = getImageView();//创建好后 设置缩放到最小imageView.setScaleX(0);imageView.setScaleY(0);initData(imageView);startScaleAnim(imageView);return false;}
//执行缩放动画
private void startScaleAnim(final ImageView imageView) {ValueAnimator valueAnimator = ValueAnimator.ofFloat(0.0f, 1.0f);valueAnimator.setDuration(800);valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {@Overridepublic void onAnimationUpdate(ValueAnimator animation) {float animatedValue = (float) animation.getAnimatedValue();imageView.setScaleX(0.1f + animatedValue);imageView.setScaleY(0.1f + animatedValue);}});valueAnimator.addListener(new AnimatorListenerAdapter() {@Overridepublic void onAnimationEnd(Animator animation) {if (position == browseEntities.size() - 1) {position = 0;} else {position++;}BrowseEntity browseEntity = browseEntities.get(position);//动画执行完后要立马取出下一个图片 把底部的图片显示更新tempImageView.setBackgroundResource(browseEntity.drawableId);//动画执行完执行平移动画startTranslationAnimator(imageView);}});valueAnimator.start();}

4. 第二阶段的曲线运动缩小动画

private void startTranslationAnimator(final ImageView imageView) {Path path;int seed = (int) (Math.random() * 100);//根据随机数来确定是走左边曲线还是右边曲线if (seed % 2 == 0) {//曲线路径的封装path = createRightPath();} else {//曲线路径的封装path = createLeftPath();}//通过PathMeasure 和ValueAnimator结合 在不同的阶段取出运动路径的x,y值final PathMeasure pathMeasure = new PathMeasure(path, false);final ValueAnimator valueAnimator = ValueAnimator.ofFloat(1.0f, 0.0f);valueAnimator.setDuration(riseDuration);valueAnimator.setInterpolator(new LinearInterpolator());valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {@Overridepublic void onAnimationUpdate(ValueAnimator animation) {float animatedValue = (float) animation.getAnimatedValue();int length = (int) (pathMeasure.getLength() * animatedValue);//在不同的阶段取出运动路径的x,y值pathMeasure.getPosTan(length, pos, tan);imageView.setTranslationX(pos[0]);imageView.setTranslationY(pos[1]);//同时做透明度动画imageView.setAlpha(animatedValue);if (animatedValue >= 0.5f) {imageView.setScaleX(0.2f + animatedValue);imageView.setScaleY(0.2f + animatedValue);}}});valueAnimator.addListener(new AnimatorListenerAdapter() {@Overridepublic void onAnimationEnd(Animator animation) {//动画执行完就移除ViewremoveView(imageView);}});valueAnimator.start();}

5. 三阶赛贝尔曲线的计算

下面以左边的为例

这里我也没有更好的办法去计算 是通过不断预估尝试出来的 如果有大佬在这里有很好的计算方法 请务必告知下

private Path createLeftPath() {Path path = new Path();float nextFloat = new Random().nextFloat();path.moveTo(nextFloat, -height * 1.0f / 1.8f);//曲线控制点一controlPointOne.x = -(viewWidth);controlPointOne.y = -height / 5;//曲线控制点二controlPointTwo.x = -(viewWidth + marginLeft / 2);controlPointTwo.y = (int) (-height * 0.15);//生成三阶贝塞尔曲线path.cubicTo(controlPointOne.x, controlPointOne.y, controlPointTwo.x, controlPointTwo.y, 0, 0);return path;}

最后连贯起来看看效

6. 最后使用RxJava 的timer()操作符 发延迟消息来让整个动画循环执行起来

这里也可以用 handler 来发消息处理

public void startAnimation(int innerDelay) {subscribe = Observable.timer(innerDelay, TimeUnit.MILLISECONDS).observeOn(AndroidSchedulers.mainThread()).subscribe(new Consumer<Long>() {@Overridepublic void accept(Long aLong) throws Exception {if (createAnimView()) return;int duration = (int) (1500 * Math.random());if (duration < 500) {duration = 500;}//循环调用startAnimation(500 + duration);}});}//动画执行的一些开关操作
public void stopAnimator() {isStop = false;if (null != subscribe) {subscribe.dispose();}}

到这里整个动画流程到这里就结束了,当然在内存的管理上还没有做到极致 大家可以去自由发挥, 希望这篇水文能帮助到那些有类似需求的同学,我们应该把时间拿去做一些更有用的事情,不过截止到目前 马蜂窝最新版 已经没有该头像的泡泡动画,想必他们也改了吧!

推荐阅读:

我新开发了一个特别好用的开源库

这么炫酷的动画效果,你还在等什么?

什么?这个天天使用的API竟然被废弃了?

欢迎关注我的公众号

学习技术或投稿

长按上图,识别图中二维码即可关注

高仿马蜂窝旅游头像泡泡动画相关推荐

  1. 短视频程序源码高仿马蜂窝旅游头像泡泡动画

    涉及到有多个view在做动画操作 这里需要继承FrameLayout来左父布局 供图片做动画操作 每个子view的动画路径类似于S型 我这里采用的是三阶贝塞尔曲线和PathMeasure来完成动画运动 ...

  2. 实现马蜂窝旅游头像泡泡动画

    当pm制定完下一版本需求,打开马蜂窝旅游app准备出去嗨一圈的时候 ,看到了马蜂窝旅游app的一个用户头像动画后...(=@__@=) 先看看效果图: 效果分析: 1.涉及到有多个view在做动画操作 ...

  3. 实现马蜂窝旅游头像泡泡动画,安卓面试项目经验

    if (null != browseEntity) { roundedImageView.setBackgroundResource(browseEntity.drawableId); String ...

  4. Android高仿马蜂窝Tabbar波浪线

    文章目录 简介 效果 思路 关键代码 先画完整的弧线,图中红色曲线 再画指示器部分的弧线,图中深蓝色弧线 不足 源码[github](https://github.com/Super-Bin/Horn ...

  5. 今日力推: Android 高仿哔哩哔哩动画客户端 / Android MD版的花瓣网App

    一.CardSwipeLayout 仿探探卡片滑动效果的布局 链接: http://pan.baidu.com/s/1qYApDfQ 密码: fz3q 二.Android高仿哔哩哔哩动画客户端bili ...

  6. android 今日头条加载动画,高仿今日头条加载动画

    01 每每浏览手机app时,发现有的效果体验不错,作为一位程序员,总想要是自己来做,怎么实现. 今天我们来模仿今日头条的加载动画. 首先我们来看一下我们这个demo最终效果,有图有真相. 高仿今日头条 ...

  7. CSS3高仿百度外卖头像波浪效果

    好Q啼的头像,说好的波浪捏,浪到哪里去了,别急,静静欣赏动态效果:链接:https://pan.baidu.com/s/1gfAM3y7 密码:wxn6 技术: 1.css water wave 实现 ...

  8. 高仿马蜂窝头像泡泡动画

    当pm制定完下一版本需求打开马蜂窝旅游app准备出去嗨一圈的时候 看到了马蜂窝旅游app的一个用户头像动画后...(=@__@=) 先看看效果图 效果分析: 涉及到有多个view在做动画操作 这里需要 ...

  9. Android开发笔记(一百四十四)高仿支付宝的头部伸缩动画

    Android5.0推出的MaterialDesign库包含了处理头部工具栏的多个控件,不但允许自定义顶部导航栏,而且导航栏高度是可以伸缩的.如此一来,一方面导航栏能够放得下更多控件,另一方面在用户想 ...

最新文章

  1. 计算机动画制作 实验要求,A074计算机动画制作实验——动画制作初步
  2. 【Linux 】使用 Shell 批量重命名文件名称
  3. Go进阶(2): 变量+数据类型
  4. 投屏画面尺寸拉伸怎么办_手机投屏转换器设置方法图文教程
  5. hadoop27---netty中handler的执行顺序
  6. 洛谷——P2018 消息传递
  7. mysql事务隔离级别 花_mysql事务隔离级别
  8. 在Win7系统下, 使用VS2015 打开带有日文注释程序出现乱码的解决方案
  9. [debug] you are on Ubuntu or Debian, install libgtk2.0-dev and pkg-config, then re-run cmake ……
  10. 【转】数据库范式(1NF 2NF 3NF BCNF)详解二
  11. html颜色混搭的插件,Color by Fardos,网页取色配色插件,查找近似颜色,提供渐变配色...
  12. js代码前面的分号是什么意思?
  13. 微信小程序系列4——传值详解
  14. python请输入一个人的名字_print('曾经有一份真挚的爱情放在我面前,那个人的名字是' + goddess),Python旅程开始的地方!...
  15. ISCC 2018 PWN WriteUp
  16. duplicate复制数据库(rac-单实例)
  17. 模型预测控制(MPC)+逻辑控制(相平面分区控制)--matlab例程介绍
  18. python3-输入摄氏度转化为华氏度
  19. 《缠中说禅108课》85:逗庄家玩的一些杂史 3
  20. 西门子S7-1200小练手之电机星三角启动

热门文章

  1. 重新回到Fcitx5的怀抱
  2. 数据库的“读写分离”
  3. 天津杨柳青十八天“传销”经历
  4. 截止2016年5月之前双色球数据统计
  5. 调用函数用new申请空间的释放方法
  6. python百度、必应、搜狗根据关键字爬取图片
  7. Windows 上帝模式「完全控制面板」的介绍和使用
  8. matlab子图怎么分别legend,Matlab:带有sublegend的子图
  9. c++课设 _ 保卫萝卜
  10. 【Eelectron-vue】构建桌面应用(20)-electron的退出quit和exit