为什么要写今天这篇博客那就说来话长了,那是在一个大雪纷飞的冬天……然后……。好了,不扯淡了,直接进入今天的主题吧,这篇博客是关于iOS自定义组件的东西。一些UI效果看起来似乎是这个样子,其实本质不是这个样子。在做一些UI效果时我们可以利用视错觉的一些东西,让用户看到的是一个东西,其实你实现的又是一个东西。原则是想方设法骗过用户的眼睛。视错觉如果和UI实现结合起来,有时会产生意想不到的效果。
另一篇使用Mask实现同样效果的博客地址如下:http://www.cnblogs.com/ludashi/p/5671133.html
一.视错觉的概述
引用--“视错觉就是当人观察物体时,基于经验主义或不当的参照形成的错误的判断和感知。视错:是指 观察者在客观因素干扰下或者自身的心理因素支配下,对图形产生的与客观事实不相符的错误的感觉。”
看上面这个解释似乎有点复杂,其实说白了就是欺骗你自己的眼睛。眼见不一定为实。视错觉的常用例子:矮中见高、虚中见实、冷调降温、粗中见细、曲中见直等等常用的手法。说这么多,接下来我想用一组图来直观的感受一下视错觉。(图片来源与网络)
1.这里不是起点,那里也不是终点。

2.平衡?别想了。

3.一个非常经典的幻觉。

上面是在网上找的视错觉的图片,像上面这些视错觉的经典案例还有很多呢,请大家自行百度吧。上面算是今天博客的引子吧,接下来就和开发有关了。
二、一个利用视错觉的自定义组件
当第一次看到这个组件效果时,感觉没有什么特别之处,就是一个普通在普通不过的组件。可是再仔细看就感觉不一样了,一些细节处理的非常好。看到组件效果时,因为没有源码,所以当时也不知道如何实现的。就想呗,然后就想到了用“视错觉”这个高大上的东西来实现。当然这个实现方案是我自己想出来的,我不知道原作者是如何实现的,下面给出了我自己的实现方案。 说这么多,先来看一下运行效果吧。
1. 该组件的运行效果如下,其实就是一个自定义的SegmentControl。看到该组件的时候,我的第一印象是:“这个组件应该挺好做的”。当时感觉就是几个Button, 然后红色的是一个UIView, 点击那个Button时,就把UIView通过动画的形式移动到当前点击的Button。顶多就是封装一下,成为一个自定义组件,然后给别人使用。

2. 在仔细看效果,感觉自己还是太年轻,太单纯了。这个组件远远不是我想的那样,上面组件的实现的重点与难点不在于如何去运动,如何去封装它。而在于下面这个截图中的东西。如果把动画放慢,你会发现一个细节,这个细节处理的非常的巧妙,也是这个组件的亮点与难点所在。下方是切换时放慢的一个效果。看到这个细节时,瞬间颠覆了我之前单纯的想法。这个组件远远没有我想的这么简单。
在切换时,有一个细节,就是在红色区域中的文字(或文字的一部分)随着红色区域的移动,文字的颜色也会随之部分改变。当红色区域移动过后,字体颜色又变为原来的了。看到这个效果,对这个组件的崇拜感就油然而生了。瞬间也蒙圈了,一时没有解决思路。大脑中充满了无数的问号。这究竟用了什么黑科技!?实现了这么NX的效果。晚上做地铁回家的时候也一直在想其解决方案。果然在地铁上灵光一现,应该就是用它:“视错觉”。于是乎就回家晚饭都没吃,就拿出笔记本开始按着自己的思路去实现。功夫不负有心人呢,所以才有了今天的博客。当然实现上述效果是我自己的思路,如果还有其他更好的实现方式欢迎交流。

三、实现原理
1.原理介绍
实现上述效果时,如果按着我看到的就是看到的来实现的话,估计会无从下手的。一个原则:“眼见为虚”,就OK了。今天这篇博客,我不想往上粘贴过多的代码,还是把我的思路给大家分享一下就好。其实编程这东西,有时候思路比代码更为重要。下方我想用在Reveal工具上的分析层次来给大家聊一下实现原理。
通过Reveal上面的UI层次我们很容易看出,这个组件远比我们想象的要复杂的多。我的实现方式如下:
(1) 先在View上加上一层的Label, 这些Label用来显示常规的字体颜色(未选中时的颜色)(黑色的字)
(2) 在之前的Label上添加一层View , 动画元素,高亮显示的字体,点击的按钮都在这个View上
(3) 在这个View上添加一层高亮的Label(白色的字), Label的字体,大小,位置等要和底层的Label一致(除了颜色除外)
(4) 上层的View的大小要和一个Label的大小一致,并且设置超出View的子视图不显示。
(5) 移动View(红色部分)时,也要移动View上白色的字。要保持移动的过程中,白色Label和黑色label完全重合。
这样View移动到那个label上时,就会把后边的黑色Label给挡上,显示的是上面白色的Label.原理大概就是这个原理,原理一旦知道怎么回事了,至于实现起来就简单许多了。

2.该自定组件可配置项如下:
1 // 2 // ZLCustomeSegmentControlView.h 3 // CustomeSegmentControl 4 // 5 // Created by ZeluLi on 15/11/19. 6 // Copyright © 2015年 zeluli. All rights reserved. 7 // 8 9 #import <UIKit/UIKit.h> 10 11 typedef void(^ButtonOnClickBlock)(NSInteger tag, NSString * title); 12 13 @interface ZLCustomeSegmentControlView : UIView 14 15 @property (nonatomic, strong) NSArray *titles; //标题数组 16 @property (nonatomic, strong) UIColor *titlesCustomeColor; //标题的常规颜色 17 @property (nonatomic, strong) UIColor *titlesHeightLightColor; //标题高亮颜色 18 @property (nonatomic, strong) UIColor *backgroundHeightLightColor; //高亮时的颜色 19 @property (nonatomic, strong) UIFont *titlesFont; //标题的字号 20 @property (nonatomic, assign) CGFloat duration; //运动时间 21 22 /** 23 * 点击按钮的回调 24 * 25 * @param block 点击按钮的Block 26 */ 27 -(void) setButtonOnClickBlock: (ButtonOnClickBlock) block; 28 29 @end
3.该自定义组件的调用方式
1 ZLCustomeSegmentControlView *v = [[ZLCustomeSegmentControlView alloc] initWithFrame:CGRectMake(30, 100, SCREEN_WIDTH - 60, 50)]; 2 3 v.titles = @[@"Hello", @"Apple", @"Swift", @"Objc"]; 4 v.duration = 0.7f; 5 6 [v setButtonOnClickBlock:^(NSInteger tag, NSString *title) { 7 NSLog(@"index = %ld, title = %@", (long)tag, title); 8 }]; 9 10 [self.view addSubview:v];
由于某些原因呢,今天博客中就不一一往上粘贴代码了。有好的思路欢迎交流~
上述Demo在GitHub上分享链接如下:https://github.com/lizelu/ZLCustomeSegmentControlView
总浏览量
15,460次
博客园历史 12,330 腾讯云 1,136 阿里云 1,992 本站新增 2
本站阅读按浏览器在 15 分钟内去重;禁用浏览器存储时按网络地址去重。推荐按浏览器一年内去重。仅使用站内随机标识,不采集浏览器指纹。
分享这篇文章
原创内容,未经授权禁止转载。
欢迎分享原文链接。除另有署名或许可说明外,本站原创文章的著作权由青玉伏案享有;未经书面授权,禁止整篇转载、复制发布、改编传播或建立内容镜像。
版权与使用条款
- 依法属于合理使用、法定许可等情形的,按法律规定执行;引用时应注明作者、作品名称和原文链接,不得歪曲、篡改或隐去署名。
- 经书面授权使用的,请遵守约定的用途、范围与署名要求。注明出处不等同于已经取得整篇转载或其他使用授权。
- 第三方图片、引用内容和书籍封面等权利归相应权利人所有;开源代码与 Demo 按其各自许可证使用,本声明不改变已有许可。
- 本声明参考《中华人民共和国著作权法》第十条、第二十四条、第五十二条等。对侵权使用,权利人保留依法要求停止侵害并追究相应责任的权利。

MARK~
mark
值得学习的思路!
mark
也就是flash中常用的遮罩
@
无边华幕
+10086
6666666666666666666666
mark~
支持一下~谢谢分享~赞+1
@
小飞人BayMax
THX~
666666666
当空间模型无法再平面上展示时就出现幻觉了~~
@
胡双挺
分析的到位~赞一个~
请问这是xcode?
@
清新剂
Reveal
@
青玉伏案
好高大~~~O(∩_∩)O谢谢
@
清新剂
不客气~可以使用一下呢,挺好的工具~
最上层的白色字不会挡住最下面的黑色字吗?我在wpf里面好像不行诶
@
本无所谓有无
在iOS是不会的,因为白色的字是放在红色的View上的,超出红色View部分的字设置成不显示即可。iOS上是这么做的,WPF就不知道了。
iOS上没有滤镜一类的东西吗? 需要这么麻烦
M
希望大神再多多分享这种好顶赞的实用东西!!!
@
小邱哥
哈哈~小邱哥,大神不敢当呢~一直在学习,一直在路上。争取多分享点干货呗~
挺有意思的哦, 继续发扬
努力学习跟进ing
支持一下~谢谢分享~赞+1
mark ,思路很重要
mark,思路有了才能实现,赞!