手把手教你封装属于自己的分段滚动视图

大家好,今天我来教大家封装一个滚动视图,额,其实我也不确定它应该叫什么名字,所以我就起名字为YCSegment了。看下图大家应该就能明白是神马。。
(还望各位高手指出不足)

依然推荐新手学习,这次的代码为Objective-C。

在本文中你将会学习到:

  • 封装
  • 懒加载
  • 协议/代理
  • KVO(键值观察者)
  • Target – Action 模式
  • 通过文本内容和字体计算Label的宽度或高度

结构如下:

图片大小: 167KB

首先我们从 item 开始:

图片大小: 30KB

不包括下面橘黄色的杠杠!!

上代码。
首先新建一个类,继承自UIView。我命名为:YCSegmentViewTitleItem
自定义一个初始化方法:

意图是给它一个需要显示的字符串和它的位置,然后让它自己去搞定。

大家有没有发现,在这里进行了一些赋值,但是我们没有初始化titleLabel啊!
而且为毛线我们要给 self.title 赋值为title !
其实是这样的:

我们实现了title属性的setter方法,在里面给实例变量_title赋值用来保存值,然后我们给self.titleLabel.text赋值为title, 最后希望它从新布局,因为可能会改变宽度啊。

那么titleLabel在哪初始化?

这里我用了懒加载的方法来初始化这个titleLabel

包括了初始化、颜色、字体、居中、添加为self的子视图等。。

!小贴士:


Objective-C中的懒加载的写法是重写某一个属性的getter。因为有些情况下我们并不能够确定什么时候初始化一个数组或者字典。多数用在网络请求之后保存结果等。。万一这个数组或者字典你用不到呢?给它个内存空间多浪费呀。所以什么时候用什么时候初始化。
注意!在getter中不要用self.titleLabel!会产生递归的。。。因为self.titleLabel实际上就是[self titleLabel][self setTitleLabel:_]~
懒加载节省了系统响应时间,提升了系统性能,非常具有利用价值。( 虽然在本项目中没什么体现。。以后有机会详细讲解喽 )


这样,一旦调用初始化方法,就完成了label的赋值操作等。接下来我们还需要布局:

然后我们希望在外界可以知道他应该具有的宽度,而且想要方便调用:

然后希望它被选中时候改变个颜色

然后我们还需要他能够触发点击事件:

好了,我们已经保存了targetaction,但是什么时候触发?!
我们希望点击内部并在内部抬起的时候让target去执行action,所以我们需要一个实例变量来记录是不是在内部点击……

这样子主要接口实现就ok了~(半个UIButton的感觉有没有!但是UIButton并不是怎么写的)


接下来是itemContent:

图片大小:45KB

图片大小:27KB

这个itemContent实际上我命名为:YCSegmentItemsContentView。
它是承载item的容器,并且来布局item。
它来负责控制高亮哪一个item,或者传递出点击了哪个一个item的消息。

首先我们先自定义初始化方法:

我们希望告诉它它应该显示在什么位置,并且显示多少个标题。剩下的让他自己去解决。

保存所有item的宽度和宽度和是为了我们希望item的宽度跟随内容,并且item之间的距离是等宽的。(item有space属性,是不是没有用到?- – 确实没啥子用哈~)

接下来是布局

布局完成了。。接下来呢我们想要通过外接知道当前应该选中哪一个item,并且也希望告诉外接主动选择了哪一个item,怎么告诉?!用代理或者block都可以。在这里我们选择代理:

外界设置代理之后,就可以让代理去执行我们想要让他执行的协议方法,但在这之前,需要确定代理是否存在,代理有没有实现协议方法。否则会崩溃哦。

好了,现在这个控件也可以实现和其他控件的交互了。


接下来是segmentView

图片大小:110KB

这个黑色可部分是collectionView,因为他自由度比较高,简单易用~
segmentViewitemitemContent结合在一起:

以下是初始化以及布局:

还有重写KVO发现属性变化后会调用的方法:

在类的延展中有这样一些属性和变量:

剩下的就是实现collectionView的协议方法,以及itemContent的协议方法:

接下来我们看一下YCSegmentViewUnit类的代码:

当我们为cell的view属性赋值的时候,需要考虑当前的_view是否存在,如果存在就从contentView上移除,然后将新传入的view添加到contentView上,然后设置view的位置和大小贴合contentView
最后千万不要忘了,_view = view,因为我们需要实力变量保存当前的view!

这样这个控件的封装就搞定啦~

不!还有非常重要的一点!
我们使用了KVO对collectionView进行了属性观察,但是如果观察着被释放了,肯定会出现问题,所以我们需要在YCSegmentView中重写- (void)dealloc方法,在dealloc中移除对collectionView的观察:

恩,这样子就大功告成了,我们实例化一个看一看~~

没错,就是这个样子~

源码:https://github.com/ilakeYC/YCSegment

1 5 收藏 评论

可能感兴趣的话题



直接登录
跳到底部
返回顶部