实现Twitter-UI效果

在使用`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`进行缩放。换句话说,当`offset`是`Header`高度的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`的动画:

        //  ------------ Label
        CATransform3D 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 Image
    headerBlurImageView = [[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:

//  ------------ Blur
        headerBlurImageView.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

时间: 2024-10-13 00:16:18

实现Twitter-UI效果的相关文章

50个Android开发人员必备UI效果源码[转载]

50个Android开发人员必备UI效果源码[转载] http://blog.csdn.net/qq1059458376/article/details/8145497 Android 仿微信之主页面实现篇Android 仿微信之界面导航篇Android 高仿QQ 好友分组列表Android 高仿QQ 界面滑动效果Android 高仿QQ 登陆界面Android 对Path的旋转效果的拓展Android高仿360安全卫士布局源码Android SlidingDrawer 滑动抽屉效果Androi

用户中心上线 采用全新简约式UI效果

继JSPGenSDF第四版发布,默认管理中心功能模块之后又一重量级功能模块开发完毕,用户中心功能模块上线,采用全新简约式UI效果,欢迎预定! 点击查看百科更多截图 包含功能:用户登录.用户注册.密码找回.基本信息.邮箱认证.手机认证.头像设置.意见反馈.在线统计等与用户相关的关键功能模块. 此功能模块,均可用于各种互动型.服务型门户网站平台,客户可根据自身业务发展需要在此基础上实现快速业务整合. 用户中心上线 采用全新简约式UI效果,布布扣,bubuko.com

我收集了多个android界面UI效果,深感大哥们的分享啊

初到oschina,看到很多大哥们分享了很好好的代码,近段时间,我收集了多个android界面UI效果,深感大哥们的分享啊.后来我将这些界面效果整合拢来,形成一个大的特效集合,一来为了查看方便,二来也为拷贝复制便捷.今日,将其共享出来,也算是为资源共享出一分力嘛. 直接上效果图: 可以看到上图中几个效果图,最上面九宫格图.左边一个是图书翻页效果图,都是比较经典的UI效果,当然还有很多,这些都是来源于oschina上的分享. 不过想说明一下,有部分地方小弟私自改动了,还请原作者原谅.例如,水波纹的

Android UI效果实现——Activity滑动退出效果

更新说明: 1.在QQ网友北京-旭的提醒下,在SlideFrame的initilize方法中添加了focusable.focusableInTouch.clickable的状态设置,否则会导致部分情况下无法滑动,感谢! 一.使用说明 使用方法很简单,只有一个类HorizontalActivity,继承自FragmentActivity类,实现了contentView的滑动事件触发和动画效果,要在自己的代码里实现,方法两种: 1.如果对Activity没特殊要求,直接继承HorizontalAct

Android UI效果实现——滑动模糊渐变效果实现

前言: 大家应该都看到过iOS7解锁屏幕的滑动模糊渐变效果,好了,现在可以把手纸收起来了,今天黄老师就给大家讲一下如何在Android平台上 实现类似的滑动模糊渐变效果,其实方式远比你想像的简单. 目标效果展示: 第一部分:几个前提 说到模糊效果,我们先要了解几个前提 1.原图,指需要被模糊的一张位图 2.模糊,通常是采用指将一个位图的每个像素RGB值都取周围像素的RGB值的平均值,这样就可以产生模糊效果,一般通过高斯函数来实现, 至于Java中的实现方式黄老师就不给大家细讲了,我也不是搞图形算

锋利的jQuery-7--query ui效果库--拖动排序插件sortable

一个简单的拖动排序效果,具体请参看jQuery ui官网demo. jquery ui :http://jqueryui.com/ sortable例子:http://jqueryui.com/sortable/#portlets 效果如图: html代码: <style type="text/css"> #myList{width: 80px;background: #EEE;padding: 5px;list-style: none;} #myList a{text-d

WPF实现Twitter按钮效果

最近上网看到这个CSS3实现的Twitter按钮,感觉很漂亮,于是想用WPF来实现下. 实现这个效果,参考了CSS3 原文地址:http://www.html5tricks.com/css3-twitter-3d-button.html 我并不知道这是不是原文的出处,我仅仅是在这里看到的.如果原文作者看到,这并不是原文出处,请留言给我. 首先声明:这个效果属于Twitter,本文仅仅是WPF技术交流,看看WPF怎么实现这样的效果,如果用于其他用途,人家来找你麻烦的话,自己负责,与本文无关. 效果

iOS 自定义滑动切换TabbarItem 觉得设计丑也要做出来的UI效果。。。

UI丑却要继续做的感言: 对UI不满意的时候,就会觉得丑爆了,时间长了,却丑习惯了. 论前一阵子Tabbar 多丑,丑得最后不要tabbar了...但是自定义tabbar 和遇到的问题解决的过程可以记录一下 目标效果: 并有切换效果,但是并没说清楚,具体切换效果,比如粘滞,弹性? 于是我做了一个弹性的. 看实现效果 一. 原理: (1)普通切换选择效果,直接贴在了tabbar上,tabbar再自定义处理图层 (2)触发事件是tabbar上的,没有图片而已.这么处理也是取巧了,降低了整体自定义难度

android UI效果相关-ListView(一)

方法一 通过反射: 代码:         Class clsClass = listView.getClass().getSuperclass();         if(clsClass == null){             Log.d("tag", "null");         }else {             Log.d("tag", "not null");             if(clsCla

android高仿微信UI点击头像显示大图片效果

转自:http://www.cnblogs.com/Jaylong/archive/2012/09/27/androidUI.html 用过微信的朋友朋友都见过微信中点击对方头像显示会加载大图,先贴两张图片说明下: 这种UI效果对用户的体验不错,今天突然有了灵感,试着去实现,结果就出来了.. 下面说说我的思路: 1.点击图片时跳转到另一个activity,然后显示加载的效果,即progressbar 2.显示图片的之前先弹出自定义dialog,然后模拟加载一段时间后,显示整张大图片,要全屏显示,