云零售技术 关注
手机版
  1. 云栖社区>
  2. 云零售技术>
  3. 博客>
  4. 正文

mac、iOS端支持自定义布局的collection控件的实现与设计

constling 2017-12-06 13:51:41 浏览1852 评论0 发表于: 云零售技术 >> Object-C

云栖社区 ios mac 布局 code 容器 void index

摘要: 介绍 collection控件用来实现界面的各种自定义布局,最常用其作为横向、竖向的布局控件。很早之前,系统对于collection的支持并不是很好。所以自己实现了支持自定义布局、自定义cell的collection控件。

介绍

collection控件用来实现界面的各种自定义布局,最常用其作为横向、竖向的布局控件。很早之前,系统对于collection的支持并不是很好。所以自己实现了支持自定义布局、自定义cell的collection控件。自定义的collection可以满足所有的产品特殊需求及动态效果,例如在某些特殊情况下可能需要除选中cell之外的其它cell执行布局动画等。在collection的基础之上,我又实现了支持cell拖动、拖离窗体的tabview控件。本文主要介绍自定义collection的设计与实现,后续持续更新多tab的tabview控件。

产品中的一些实现效果

8e10cfb039b894c9d4b8b2e7f0921a2d.png

mac旺旺表情面板,实现grid与横向布局

d4af338b6438da160c7d8fb6555c5ff9.png

mac千牛工作台用作横向布局

39e70d0a53d8e25b511a94daca7aa2ea.png

iOS千牛历史登录页面实现当前选中cell变大并且选中cell总中最中位置校准动效的效果

collection

collection主要包括:继承scrollview的collectionView,数据源协议collectionViewDataSource,事件响应协议collectoinViewDelegate,布局基类collectoinLayout以及展示单元collectionCellView。

模块图如下:

c35e08cb7d460773d512bd651172bd53.png

collectionView

collection容器包含指实现collectionViewDataSource、collectoinViewDelegate协议的指针以及collectoinLayout成员,同时维护collectoinCellView的控件重用。


@interface WWCollectionView : NSScrollView
// 布局对象
@property (retain) WWCollectionViewLayout *layout;
// 数据源
@property (weak) id dataSource;
// 事件响应
@property (weak) id delegate;
// 重加载数据
(void)reloadData;
// 重排布
(void)invalidateLayout;
// 取消返回选中
(void)unSelectedAll;
// 注册重用对象
(void)registerClass:(Class)cellClass forCellWithReuseIdentifier:(NSString *)identifier;
// 对象重用
(id)dequeueReusableCellWithReuseIdentifier:(NSString )identifier forIndexPath:(NSIndexPath )indexPath;
// 设置选中对象
(void)selectItemAtIndexPath:(NSIndexPath *)indexPath animated:(BOOL)animated;
// 当前选中对象
(NSIndexPath *)selectedItem;
// 重加载indexPath item
(void)reloadItemsAtIndexPath:(NSIndexPath *)indexPath;
// 插入
(void)insertItemsAtIndexPath:(NSIndexPath *)indexPath withAnimate:(BOOL)animate;
// 删除
(void)deleteItemsAtIndexPath:(NSIndexPath *)indexPath withAnimate:(BOOL)animate;
// 重新排列
(void)relayoutWithAnimation:(BOOL)animated completion:(void (^)(BOOL finished))completion;
// 滚动到aPoint
(void)scrollToPoint:(NSPoint)aPoint withAnimate:(BOOL)animate;
@end

collectionViewDataSource

collection展示的数据源,由宿主实现。


@protocol WWCollectionViewDataSource
// 返回indexPath下标的cell
(WWCollectionCellView )collectView:(WWCollectionView )collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath;
// 总cell个数
(NSInteger)numberOfItemInCollectionView:(WWCollectionView *)collectionView;
// cell的数据
(id)collectionView:(WWCollectionView )colletionView objectValueAtIndexPath:(NSIndexPath )indexPath;
@end

collectoinViewDelegate

collection事件的回调响应,由宿主实现。


@protocol WWCollectionViewDelegate
// indexPath元素被选中
(void)collectionView:(WWCollectionView )collectionView didSelectItemAtIndexPath:(NSIndexPath )indexPath;
// 是否支持选中
(BOOL)collectionView:(WWCollectionView )collectionView shouldSelectItemsAtIndexPaths:(NSIndexPath )indexPath;
@end

collectoinLayout

collectionCellView的布局方案。


@interface WWCollectionViewLayout : NSObject
// 布局基类
@property (weak) WWCollectionView *collectionView;
// 每个cell元素大小
@property (assign) NSSize itemSize;
// edgeInsets
@property (assign) NSEdgeInsets edgeInsets;
// scrollview使用,表示整个画布大小
@property (assign) NSSize viewContentSize;
(instancetype)initWithCollectionView:(WWCollectionView *)collectionView;
(void)invalidateLayout;
// 返回index的cell大小
(NSRect)frameForIndexPath:(NSIndexPath *)index total:(NSInteger)total;
(NSSize)collectionViewContentSize;
@end
// 横向布局控件
@interface WWFlowCollectionViewLayout : WWCollectionViewLayout
@property (assign) CGFloat headMargin;
@property (assign) CGFloat tailMargin;
@end
// grid布局控件
@interface WWGridCollectionViewLayout : WWCollectionViewLayout
// 每行多少个
@property (assign) NSInteger numberPerRow;
@property (assign) CGFloat headMargin;
@property (assign) CGFloat tailMargin;
@end


@implementation WWFlowCollectionViewLayout
// 横向布局的实现

(void)invalidateLayout {
NSInteger cellCount = [self.collectionView.dataSource numberOfItemInCollectionView:self.collectionView];
CGRect bounds = self.collectionView.bounds;
// 画布宽度
CGFloat width = _headMargin + _tailMargin + (cellCount - 1) (self.edgeInsets.left + self.edgeInsets.right) + self.itemSize.width cellCount;
if (width < bounds.size.width) {

width = bounds.size.width;

}
self.viewContentSize = NSMakeSize(width, bounds.size.height);
[super invalidateLayout];
}

(NSRect)frameForIndexPath:(NSIndexPath *)index total:(NSInteger)total {
CGFloat leftPos = self.headMargin + [index indexAtPosition:0] * (self.itemSize.width + self.edgeInsets.left + self.edgeInsets.right);
// 返回cell的rect
return NSMakeRect(leftPos, self.edgeInsets.top, self.itemSize.width, self.itemSize.height);
}

@end

collectoinCellView

collection展示的cell控件。


@interface WWCollectionCellView : NSView
// 当前cell被选中
@property (nonatomic, assign) BOOL selected;
// 数据
@property (nonatomic, retain) id dataValue;
// 使用前重置展示效果
(void)reset;
@end
本文为云栖社区原创内容,未经允许不得转载,如需转载请发送邮件至yqeditor@list.alibaba-inc.com;如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件至:yqgroup@service.aliyun.com 进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容。

用云栖社区APP,舒服~

【云栖快讯】2017互联网超级工程阿里双11完美落幕,交易额突破1682亿,但阿里工程师如何玩转“超级工程”,背后黑科技又是如何?12月13-14日,12位大咖直播分享揭秘1682亿背后技术实践,马上预约  详情请点击

网友评论

关注
constling
技术深挖与分享
1篇文章|30关注

移动测试(Mobile Testing)是为广大企业客户和移动开发者提供真机测试服务的云平台,拥有大量热门机型,...

阿里云移动APP解决方案,助力开发者轻松应对移动app中随时可能出现的用户数量的爆发式增长、复杂的移动安全挑战等...

为您提供简单高效、处理能力可弹性伸缩的计算服务,帮助您快速构建更稳定、安全的应用,提升运维效率,降低 IT 成本...