code小生 一个专注大前端领域的技术平台公众号回复Android加入安卓技术群

作者:史蒂芬诺夫斯基链接:https://www.jianshu.com/p/2954f2ef8ea5声明:本文已获史蒂芬诺夫斯基授权发表,转发等请联系原作者授权

好久没写View了,最近恰巧遇到一个八大行星绕太阳旋转的假3D效果,写完之后感觉效果还不错。能玩十分钟的那种。
本篇将一步步带您实现这样的一个效果,ps:我是用kotlin实现的,介于您可能还不太熟悉kotlin或者不像熟悉java那样,所以本篇使用java语言(写的过程中老是忘记写new和分号报错)。
先上最终效果图(录制的比较渣)

太阳系.gif

本文目的

  • 巩固/练习 自定义View
  • 分析解决问题的思路

需要解决的问题

1.行星的整体布局,3D的视觉效果

2.行星转到太阳后面时,会被太阳挡住,转到太阳前面时,会挡住太阳

3.行星自动旋转,并且可以根据手势滑动,滑动完之后继续自动旋转

4.中间的太阳有照射的旋转动画

分析问题

1.行星的整体布局,3D的视觉效果

如果我们draw()的之前通过Camera将Canvas绕x轴旋转60°是不是就可以搞定?这种方式实则是不可行的。因为draw()之前Canvas的变化会作用于子View,从效果图可以看出,子View并没有rotateX的变换,只有缩放变换。所以我们通过子View layout时变化其位置,即计算子View的left、top、right、bottom四个值

行星绕太阳旋转其轨迹实际上就是圆形,如下图:

平面.png

我们看手机,其实是沿着z轴方向。想象一下,如果让坐标系沿着x轴旋转60°,不就能达到我们想要的效果了嘛。

旋转60°,我们再沿着x轴方向看,如下图:

round_x.png

图中蓝色是旋转前的轨迹,紫色是旋转之后的轨迹。假设P点是地球,P旋转前的y坐标是y0,则旋转之后地球的y坐标是:

y0 * 旋转角度的余切值,即:

y1 = y0* cos(60°)

好了。现在的结论是,只需要把图1的所有行星的y 坐标 * cos60°,就能达到效果了。

而图1中,计算各个行星旋转之前的x 、y坐标比较简单。

x0 = Radius * cos60°

y0 = Radius * sin60°

2.行星转到太阳后面时,会被太阳挡住,转到太阳前面时,会挡住太阳

3.png

刚看到这个效果,觉得这个问题是个比较难的点,如果所有行星的父容器和太阳是平级关系,结果就是要么所有的行星都会挡住太阳,要么就是太阳都会挡住行星。不能达到行星转到太阳后面时,会被太阳挡住,转到太阳前面时,会挡住太阳 * 的这种效果

但是如果所有的行星和太阳是平级关系,即他们是同一个父容器下的子View,那么我们就可以达到这个效果,方法有三种:

1、重写父容器dispatchDraw()方法,改变子View的绘制顺序(图3中先draw土星,再draw太阳,再draw地球);

2、在子View draw之前依次调用bringToFront()方法(图3中先调用土星的bringToFront()方法,再调用太阳的bringToFront()方法,最后调用地球的bringToFront()方法);

3、通过改变所有子View的z值(高度)以改变View的绘制顺序。

这三种方法理论是都可以实现,但是方法1 成本太高、风险也高,重新dispatchDraw()可能会发生未知问题,至于方法2,细心的朋友可能发现,每次调用bringToFront()方法,都会出发requestLayout(),降低了测量布局绘制效率,更重要的原因是在layout(问题1的解决需要重新layout方法)之后再调用requestLayout()方法,会导致循环layout-draw-layout-draw-layout-draw....

综上,我们选择方法3。简单,风险小。

3.行星自动旋转,并且可以根据手势滑动,滑动完之后继续自动旋转

自动滑动:在父容器中设置一个成员变量:角度偏移量sweepAngle,计算子View的位置时将偏移量也考虑进去。然后定时不断增加或者减小sweepAngle(增加或减小 将决定子View是顺时针or逆时针旋转)

手势:用的比较多,从后面的代码中体现。

4.中间的太阳有照射的旋转动画

效果图中的太阳由两张图片组成,一张是前景,一张是背景带亮光,让背景图绕着z轴无限旋转即可。

开始编码

开始愉快的编码

核心就是行星的父容器

/** * 行星和太阳的父容器 * * @author guolong * @since 2019/8/20 */

然后再xml中配置View

<?xml version="1.0" encoding="utf-8"?>

运行,效果如下:

上述代码正如前面分析的,计算所有子View的left 、top 、right 、bottom,注释写的也详细。说明两点:

1、其中,64行

double angle = (START_ANGLE - averageAngle * index + sweepAngle) * Math.PI / 180;

公式中- averageAngle * index代表逆时针添加,如果是+ averageAngle * index则是顺时针添加。

2、78到80行,计算子View的scale,这里说明下角度和scale的计算公司

float scale = (float) ((1 - 0.3f) / 2 * (1 - Math.sin(angle)) + 0.3f);

假如View的最小scale是0.3f,最大scale是1。按照效果View在270°时scale最大,在90°时scale最小,并且从270°到90°scale越来越小。正玄曲线如下:


正玄曲线中,270°最小,90°时最大,我们把正玄值取反然后再加1,那么[90°,270°]对应的值就是[0,1]

即,设z = -sin(angle) + 1当angle在90°到270°变化时 ,z将在0到1之间变化

z在0~1之间变化时,scale 要在0.3~1之间变化,如下图:

5.png

显然,

scale = (1 - 0.3) * z + 0.3 = (1-0.3)*(-sin(angle) + 1)+0.3

接下来,再把中间的太阳加进去

太阳也是StarGroupView的子View,但是和其他子View 不同的是,太阳在最中间,不参与类似行星的位置计算

简单期间我们使用tag=“center"来标识子View是中间的太阳。

修改xml文件

<com.glong.demo.view.StarGroupViewandroid:layout_width="match_parent"android:layout_height="match_parent">

修改StarGroupView.java

public 

代码注释写的很全面,不做过多解释了,这个时候我们把PADDING改大一点,改成160,运行如下:

20190820184234.jpg

问题很明显,3应该在4的上面, 2 应该在3的上面,中间的View应该在5,6的上面。

这是因为系统默认按照View的添加顺序画View的,即我们xml文件里面的顺序。xml里面我们centerView在第一个,所以就先画centerView,导致centerView被其他View覆盖。按照上面的分析,动态改变View的z值以改变View的draw顺序。

修改StarGroupView.java代码

public 

我们先给所有子View根据他的scaleY排序,由于centerView的scaleY 在layoutChildren()时并没有改变,我们把centerView的scaleY设置为0.5f,最后再还原回去。现在运行,效果如下:

微信截图_20190820231253.png

到这里基本已经达到了我们想要的效果啦,接下来让其自动旋转和响应手势,肯定就难不倒我们啦。

加入自动旋转

子StarGroupView中循环postDelayed(runnable,16)即可,这里为什么是16ms,大家都懂

修改StarGroupView.java

public 

这样就开始自动旋转了,调节AUTO_SWEEP_ANGLE的值 改变旋转速度

加入手势

老写法,先上代码

在StarGroupView.java中增加

public 

手势处理的代码比较简单,这里就不再赘述了,需要注意的是

1.ACTION_DOWN需返回true,不然收不到后续的ACTION_MOVE事件;

2.ACTION_DOWN时需要暂停动画和自动旋转

3.这里根据手指离开屏幕时的速度做Animator动画,当然你也可以用scroller实现。

4.第59行,我们给dx * SCALE_PX_ANGLE代表一个像素可以转换成SCALE_PX_ANGLE角度

最后,加上中间太阳旋转的动画

res/anim/sun_anim.xml

<?xml version="1.0" encoding="utf-8"?>

在Activity中

public 

最终不到算上注释260代码搞定!

最终效果

demo.gif

我把完整的Demo代码和星球效果代码放在github上了https://github.com/glongdev/Demos

相关阅读

Android 仿抖音实现动态壁纸

Android 如何优雅地实现@人功能?——仿微博、仿QQ、仿微信、零入侵、高扩展性

长图片自动循环滚动效果 (仿小红书)

仿房产销冠 APP 销控表界面-多 RecyclerView 同步滚动

Android 仿微信朋友圈,缩放归位功能详细解析

如果你想要跟大家分享你的文章

欢迎投稿

android立体3D效果_Android实现八大行星绕太阳3D旋转效果相关推荐

  1. 仿八大行星绕太阳3D旋转效果

    android实现八大行星绕太阳3D旋转效果 仿上面效果,采用kotlin实现,逻辑要简单些,注释在源码中,一看就懂 <com.example.androidxdemo.star.StarGro ...

  2. android fragment中引入自定义view_厉害了,用Android自定义View实现八大行星绕太阳3D旋转效果...

    作者:史蒂芬诺夫斯基 链接:https://www.jianshu.com/p/2954f2ef8ea5 好久没写View了,最近恰巧遇到一个八大行星绕太阳旋转的假3D效果,写完之后感觉效果还不错.能 ...

  3. 实现八大行星绕太阳3D旋转效果,这波操作不来喊个666?

    /   今日科技快讯   / 针对媒体报道的关于法拉第未来进行重组以及贾跃亭或辞去CEO职务的内容,FF发布声明称,已正式进入公司顶层治理架构变革的执行阶段,近期会公布相关细节.对于贾跃亭的债务问题, ...

  4. Android实现八大行星绕太阳3D旋转效果

    效果图: 本文目的: 巩固/练习 自定义View 分析解决问题的思路 需要解决的问题: 1.行星的整体布局,3D的视觉效果 2.行星转到太阳后面时,会被太阳挡住,转到太阳前面时,会挡住太阳 3.行星自 ...

  5. android立体3D效果_怀化400T吨龙门剪图纸3d模型_临沂1500T吨剪图纸原理图-皇宏液压...

    皇宏液压为您详细解读yddYIm怀化400T龙门剪图纸3d模型的相关知识与详情,   接触过超影3D印刷的伴侣们,想必必然对陈某们有所理解,超影3D印刷服务商拥有强大的3D印刷经历的团队,不单正在3D ...

  6. Android激光投影3d效果,激光那些事③:影院看3D大片其实被坑?

    13D影片的亮度不够是为省钱 自己买3D电视看大片不太靠谱,因为普通消费者没有丰富的片源.很多人还是选择去了电影院看3D大片.现在不管什么时候去电影院,你几乎都可以找到一部3D电影在上映,但是3D效果 ...

  7. android 三维动画效果,9款令人惊叹的HTML5 3D动画应用

    原标题:9款令人惊叹的HTML5 3D动画应用 之前我们已经向大家分享了很多HTML5动画应用了,大部分都非常炫酷,也有一小部分是很实用的.今天我们要向各位HTML5动画爱好者介绍更多的HTML5 3 ...

  8. android 实现磨砂效果_Android 5.0 下毛玻璃(磨砂)效果如何实现?

    刚刚做技术调研,可以给一些优缺点的对比. 目前主流实现毛玻璃效果(高斯模糊)分大致三种方法: 一 利用RenderScript接口 利用现有Android结构,通过RenderScript调用底层接口 ...

  9. android 按钮顶级效果_Android 源码之button高亮效果

    android默认的button在点击以后有默认的高亮效果,但是默认的button比较丑,要替换成自己的按钮背景,采用的方法是: button.setBackgroundDrawable(drawab ...

最新文章

  1. C 编程异常 — double free or corruption (fasttop)
  2. Java instanceof运算符
  3. 王者荣耀(01背包)
  4. ssl 的jks 生成工具
  5. PyTorch学习笔记:torch.optim---Optimizer以及lr_scheduler
  6. easyswoole事务mysql_easyswoole ORM 事务操作管理
  7. Linux音频驱动-ASOC(ALSA System on Chip)
  8. 基于PlayTennis数据集的决策树决策分析
  9. JavaScript事件委托的技术原理
  10. 《普林斯顿微积分》读书笔记
  11. U盘用USBOOT做引导盘后,导致无法格式化U盘
  12. key_beep按键控制蜂鸣器程序及流程图
  13. JAVA计算机毕业设计大学生旅游拼团网站计算机(附源码、数据库)
  14. V4L2框架-media device
  15. Guava---Splitter
  16. 005-浅谈SSDT
  17. nvme固态硬盘开机慢_解决nvme固态开机慢
  18. excel里的一个单元格怎样拆分成几个单元格?
  19. 从服务业开始创业,该怎么起步?
  20. [转]Clion2019破解-Jetbrains系列产品2019.1.1最新激活方法[持续更新]

热门文章

  1. 数据平台开发是做什么的?需要具备哪些能力
  2. C++中fstream 的使用一
  3. 生物信息学之抗癌药物反应论文阅读五:L1000+DTI
  4. python键盘键值表_Python怎么记录键盘鼠标敲击次数|Python统计鼠标点击次数 - PS下...
  5. 关于forward(转发)和redirect(重定向)的区别
  6. 学习Nginx看这篇就够了
  7. 涛思数据加入龙蜥社区,携手共建时序数据库生态
  8. RAP2开发环境部署
  9. 「自控原理」5.1 频率特性及其图示
  10. RTSP基础之RTSP/RTP推流协议流程