在使用Twitter的APP后,我已开发者的视觉并注意到整体与部分之间相互协调是件极其有意思的事情。这引起了我的好奇心:这是怎么做到的?

让我们具体地讨论下这个视图布局:此效果不优雅吗?它看起开就像本应如此,但你仔细的观察后就会发现更多。随着Scrollview的偏移,图层的覆盖,动作和比例缩放是那么的平滑连贯… … 实在是太喜欢这个效果了。

So,就让我们立刻实现这个效果吧。

首先,先看下最终效果:

结构描述


在写代码之前,我想给你一个关于如何构建UI的简单意见。

打开Main.storyboard文件,在这个控制器里面你会发现2个主要的对象。第一个是一个呈现Header的视图,第二个是Scrollview,它包含了Avatar和账号相关的其他信息,如:username标签和Follow按钮。还有一个被叫做Sizer的视图,它是为了确保Scrollview拥有足够大的垂直滑动的空间。

就像你看到的那样,这个结构非常的简单。稍微注意一下就可发现Header的外部放置了一个Scrollview,而不是与其他元素放置在一起。虽然没必严格如此,但这样会使它的结构变动更加灵活。

编码


如果你仔细的看了最后的动画,将会注意到你要管理2个不同的动作:

  1. 向下拉(当Scrollview已经停靠在屏幕的顶部的时候)
  2. 上下滑动

第二个动作可以细分为4个小步骤:

  • 向上滑动,一直到导航条默认的大小并停靠在屏幕的顶部。
  • 向上滑动,Avatar开始逐渐变小。
  • Header被固定后,Avatar会移动到它的下边。
  • username标签抵达Header的顶部时,一个新的白色Label将会从Header中心的底部展现。这时Header的背景图片将会用高斯模糊渲染。

打开ViewController让我们一个一个的实现这些步骤。

构建管理者


首先要做的事情很明显,就是获取关于Scrollview的偏移量offset。我们可以通过UIScrollViewDelegate协议实现scrollViewDidScroll方法。

在一个View上执行最简单地动画方式是使用Core Animation逐渐的进行三维变换,并给layer.transform赋予新值。

关于Core Animation可以参考这篇文章

http://www.thinkandbuild.it/playing-around-with-core-graphics-core-animation-and-touch-events-part-1/

这些是scrollViewDidScroll:方法的第一部分

    CGFloat offset = scrollView.contentOffset.y;CATransform3D avatarTransform = CATransform3DIdentity;CATransform3D headerTransform = CATransform3DIdentity;

在这里我们获取一个当前垂直偏移量`offset`,并初始化2个`CATransform3D`变量。

下拉


下拉动作的管理:

if (offset < 0) {CGFloat headerScaleFactor = -(offset) / header.bounds.size.height;CGFloat headerSizevariation = (header.bounds.size.height * (1.0 + headerScaleFactor) - header.bounds.size.height) / 2.0;headerTransform = CATransform3DTranslate(headerTransform, 0, headerSizevariation, 0);headerTransform = CATransform3DScale(headerTransform, 1.0 + headerScaleFactor, 1.0 + headerScaleFactor, 0);header.layer.transform = headerTransform;}

首先,我们检查offset是否为负数:用户在下拉的过程中,将会进入Scrollview的弹性区域。

剩下的代码就是简单的数学逻辑。

Header的扩大是因为它的上边缘固定于屏幕的顶部,而底部的图片在等比缩放。

the transformation is made by scaling and subsequently translating to the top for a value equal to the size variation of the view.实际上,移动ImageView图层的中点到顶部并同时缩放它,你可以获得相同的效果。

headerScaleFactor是用来被计算的一部分。我们想用offset适当的对Header进行缩放。换句话说,当offsetHeader高度的2倍时,headerScaleFactor必须是2.0。

我们需要管理的第二个动作是上下滑动。让我们看看,如何一步步通过UI的主要元素完成变换的。

头部(第一阶段)


当前的offset应该大于0。Header应该随offset进行垂直变换,直到它期望的高度(我们后面将会讲解Header的高斯模糊)。

headerTransform = CATransform3DTranslate(headerTransform, 0, MAX(-offset_HeaderStop, -offset), 0);

这句代码非常简单。我们只需定义一个让`Header`在此停止移动的最小值。 让我感到羞愧的是我比较懒!所以我写死了一些数值,像`offset_HeaderStop`。其实,我们可以通过计算UI元素的位置来获取相同的效果。下次有空再改吧。

头像


Avatar的缩放与我们处理下拉的逻辑一样,只是在这种情况下,图片是到达底部而不是顶部。这段代码和上边的比较相似,除了减小缩放的比例为1.4。

        // Avatar -----------CGFloat avatarScaleFactor = MIN(offset_HeaderStop, offset) / avatarImage.bounds.size.height / 1.4;CGFloat avatarSizevariation = (avatarImage.bounds.size.height * (1.0 + avatarScaleFactor) - avatarImage.bounds.size.height) / 2.0;avatarTransform = CATransform3DTranslate(avatarTransform, 0, avatarSizevariation, 0);avatarTransform = CATransform3DScale(avatarTransform, 1.0-avatarScaleFactor, 1.0-avatarScaleFactor, 0);

就像你看到的,当`Header`停止变化时,我们用`MIN`函数来使`Avatar`的缩放停止。 此时,我们根据当前`offset`设置最顶层的图层。除非`offset`小于等于`offset_HeaderStop`,最顶层的图层是`Avatar`,否则是`Header`。

if (offset <= offset_HeaderStop) {if (avatarImage.layer.zPosition < header.layer.zPosition) {header.layer.zPosition = 0;}} else {if (avatarImage.layer.zPosition >= header.layer.zPosition) {header.layer.zPosition = 2;}}}

白色Label


这段代码是白色Label的动画:

        //  ------------ LabelCATransform3D labelTransform = CATransform3DMakeTranslation(0, MAX(-distance_W_LabelHeader, offset_B_LabelHeader - offset), 0);headerLabel.layer.transform = labelTransform;

这里有2个令我感到羞愧的变量值:当`offset`等于`offset_B_LabelHeader`时,黑色的`username`标签刚到触碰到`Header`的底部。

distance_W_LabelHeaderHeader底部与白色Label终点之间的距离。

这个变换是通过此逻辑计算:黑色Label触碰到Header,白色Label就会立即出现,并且到达Header中点位置就停止移动。所以我们使用下面代码创建Y值:

MAX(-distance_W_LabelHeader, offset_B_LabelHeader - offset)

高斯模糊


最后一个效果是Header的模糊。为了得到合适的解决方案,我用了3个不同的库… … 我也尝试过用OpenGL ES创建基类,但实时更新模糊总是非常缓慢。

然后我意识到我可以对模糊仅仅计算一次,将不模糊和模糊的图片进行重叠,只是改变alpha值。我非常确信,Twitter就是这样做的。

viewDidAppear中,我们计算Header的模糊值并隐藏它,设置alpha值为0。

    // Header - Blurred ImageheaderBlurImageView = [[UIImageView alloc] initWithFrame:header.bounds];headerBlurImageView.image = [[UIImage imageNamed:@"header_bg"] blurredImageWithRadius:10 iterations:20 tintColor:[UIColor clearColor]];headerBlurImageView.contentMode = UIViewContentModeScaleAspectFill;headerBlurImageView.alpha = 0.0;[header insertSubview:headerBlurImageView belowSubview:headerLabel];header.clipsToBounds = YES;

模糊视图是用过FXBlurView实现的。

scrollViewDidScroll:方法中,我们只需根据offset设置alpha:

//  ------------ BlurheaderBlurImageView.alpha = MIN(1.0, (offset - offset_B_LabelHeader) / distance_W_LabelHeader);

这个计算的背后逻辑是:alpha最大值是1,当黑色Label触碰到Header时模糊效果开始出现,当白色到达最终位置时,也将停止继续模糊。

就这样!

我希望你喜欢这个教程。学习如何重现这种很棒的动画效果对我来说是很大的乐趣。

Swift代码:Download Source
OC代码:Download Source


原版:IMPLEMENTING THE TWITTER IOS APP UI

实现Twitter-UI效果相关推荐

  1. 【Android源代码下载】收集整理android界面UI效果源码

    在Android开发中,Android界面UI效果设计一直都是很多童鞋关注的问题,今天给大家分享下大神收集整理的多个android界面UI效果,都是源码,都是干货,贡献给各位网友! 话不多说,直接上效 ...

  2. 【Python】PyCharm中Matplotlib绘图不能显示UI效果的问题解决

    问题描述 我们利用了Matplotlib的类Cursor,向图形添加一组纵横交叉的直线,从而实现图形界面中任何位置的数值定位的可视化效果. 但使用PyCharm,绘图结果在右侧的部分: 这固然是需要绘 ...

  3. python画图为什么运行不出来_PyCharm中Matplotlib绘图不能显示UI效果的问题解决

    问题描述 我们利用了Matplotlib的类Cursor,向图形添加一组纵横交叉的直线,从而实现图形界面中任何位置的数值定位的可视化效果. 但使用PyCharm,绘图结果在右侧的部分: 这固然是需要绘 ...

  4. Android开源库集合(UI效果)

    动画效果 粒子动画效果 https://github.com/glomadrian/Grav 水波式loading等待动画 https://github.com/race604/WaveLoading ...

  5. Android 11.0 自定义仿小米全面屏手势导航左右手势滑动返回UI效果

    目录 1.概述 2.自定义仿小米全面屏手势导航返回ui布局的核心代码 3.自定义左右手势返回UI样式的核心代码功能分析 3.1 NavigationBarView手势导航布局左右手势返回的相关代码 3 ...

  6. css三实现ui,纯CSS实现常见的UI效果

    原标题:纯CSS实现常见的UI效果 转自:掘金 - alphardex 前言 切图仔,是大多数前端用来自嘲的称呼.相信很多人平时写页面的时候,大部分时间是在切图和排图,如此往复.这里并不是要否定切图本 ...

  7. 仿网易云音乐均衡器调节UI效果

    介绍 转载请说明出处!网易云音乐大家都很熟悉,今天主要是来模仿以下他的音效均衡器的调节UI 效果如图:                    若想实现这个效果我们需要做什么呢?我们现分析一下: 1. ...

  8. 高仿小米盒子UI效果实现

    高仿小米盒子UI效果实现.不多说什么,注释我代码写得比较清楚了. 不懂的看代码.效果图如下:

  9. c++Qt简单实现金融软件部分界面以及ui效果

    1.开发环境 qt5.9.9以及自带的Qt Creator,并且导入qcustomplot库以实现图表效果. 2.效果展示 原软件截图: qt程序截图: 新手通过本程序的学习,可初步掌握qt部分控件使 ...

  10. BottomSheetDialog仿抖音评论区的UI效果

    大家好!我国著名数学家华罗庚曾说:聪明在于勤奋,天才出于积累. 一.问题背景 当下抖音成为了人们平常生活消遣娱乐必不可少的视频软件,它评论区的UI具有良好的用户交互性,其动画效果非常人性化,滑动出现的 ...

最新文章

  1. html5考试总结300字,期中考心得300字5
  2. 6 OC 中的isa 指针
  3. 基础知识——if语句和字典(四)
  4. 微信小程序 java 传值_微信小程序传值获取值的实例方法
  5. mysql 查看主从_什么参数可以查看mysql主从复制是否正常
  6. 通用多表分页存储过程
  7. mysql+server+80_Windows Server 2019 IIS10.0+PHP(FastCGI)+MySQL环境搭建教程
  8. 程序员过关斩将--领导说我的类的职责不单一
  9. WEB前端面试题汇总整理01
  10. redis 6.0 redis-proxy搭建
  11. Jmeter java协议配置文件导入
  12. 先说一下JS的获取方法,其要比JQUERY的方法麻烦很多,后面以JQUERY的方法作对比。...
  13. Redis常用数据结构
  14. 管理感悟:主管加班,员工才会加班
  15. Java常用的设计模式是什么?
  16. 【文献阅读】2004 Goktekin NS方程加弹性 A Method for Animating Viscoelastic Fluids
  17. Java qq登录界面设计
  18. 内存超频时序怎么调_超频讲解:内存时序设置一
  19. poj3764解题报告
  20. 华为S7706升级到S7700-V200R008C00SPC500版本快速配置记录

热门文章

  1. 【数据结构-链表】链表的相关算法
  2. PVS-Vdisk升级tools
  3. 2010年消费电子技术20个最大失败:Buzz居首
  4. DELMIA软件弧焊仿真:机器人焊接起始点与结束点姿态调整方法
  5. irfanview没法设置文件关联怎么办,jpg格式关联到IrfanView操作步骤
  6. 百个增量配电PPP项目将公布 千亿投资逐鹿电改工业园试点
  7. 微信多开消息防撤回工具让你的电脑登录多个微信账户
  8. echarts实现河南各省市区县地图(河南省各省市区县地图json文件可以在我博客里下载)
  9. iphone已经信任anyproxy证书,还是提示无效
  10. JavaScript实现圆周运动