经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 移动开发 » iOS » 查看文章
iOS-关于自定义分段选择器的一些小事(Segmented)
来源:cnblogs  作者:macro小K  时间:2019/7/10 11:31:03  对本文有异议

系统自带的分段选择就是 UISegmentedControl ,也有一些大佬自定义的 Segmented ,比如Git上的 HMSegmentedControl ,我以前最初的项目中,也有用到过,如果自己写,或者想自定义一些UI,该从哪里出发,其实在用过 HMSegmentedControl 之后,大致就有思路了,如果想简单的实现下,可以利用 UICollectionView 来实现,下面是我利用 UICollectionView 写的一个简单的小栗子,效果图

 

设计思路

 

首先利用 UICollectionView 处理每个item的大小,确切的说是宽度,那么就要每次选中一个item后,重新计算所有的item的宽度,同时计算 UICollectionView 的 contentSize.width;

计算每个item宽度分为两种情况,一种是选中的字体的显示,一种是未选中的字体显示,比如字体大小,颜色等,然后根据自己大小,计算出字体需要展示的宽度,并计算对应的item宽度,最后把每个item的宽度保存起来,用于在 UICollectionView 代理方法中做处理;

计算 contentSize.width 由上图可知,是由两边的间距,item之间的间距和每个item的综合,目的是利用 contentSize.width 计算下划线的位置;

具体实现

  1. #import "XKCollectionView.h"
  2.  
  3. ///四周边距
  4. const static CGFloat _margin_left = 5;
  5. const static CGFloat _margin_right = 5;
  6. const static CGFloat _margin_top = 0;
  7. const static CGFloat _margin_bottom = 2;
  8. const static CGFloat _margin_space = 15;
  9. const static CGFloat _line_width = 30.0;
  10. const static CGFloat _line_height = 3.0;
  11. @interface XKCollectionView ()<UICollectionViewDataSource,UICollectionViewDelegateFlowLayout>
  12. ///临时数据
  13. @property (nonatomic,strong) NSArray<NSString *> *titleArray;
  14. ///每个item的宽度
  15. @property (nonatomic,strong) NSMutableArray *widthsArray;
  16. ///底部线条
  17. @property (nonatomic,strong) UIView *lineView;
  18. ///选中的item索引
  19. @property (nonatomic,assign) NSInteger selectIndex;
  20. ///选中的item string
  21. @property (nonatomic,strong) NSString *selectString;
  22. ////计算出来的总宽度,用于设置 UICollectionView.contentSize.width
  23. @property (nonatomic,assign) CGFloat totalContentWidth;
  24. @end
  25. @implementation XKCollectionView
  26. - (instancetype)initWithFrame:(CGRect)frame collectionViewLayout:(UICollectionViewLayout *)layout{
  27. self = [super initWithFrame:frame collectionViewLayout:layout];
  28. if (self) {
  29. [self setup];
  30. }
  31. return self;
  32. }
  33. - (void)setup{
  34. _selectIndex = 0;
  35. self.widthsArray = [NSMutableArray array];
  36. [self addSubview:self.lineView];
  37. self.backgroundColor = [UIColor whiteColor];
  38. self.showsHorizontalScrollIndicator = NO;
  39. self.delegate = self;
  40. self.dataSource = self;
  41. [self registerClass:[XKCollectionViewCell class] forCellWithReuseIdentifier:@"XKCollectionViewCell"];
  42. _titleArray = @[@"一级建造师",@"二级建造师",@"造价工程师",@"咨询工程师",@"注册安全工程师",@"监理工程师",@"注册电气工程师",@"环境影响评价工程师",@"注册城乡规划师",@"注册消防工程师"];
  43. [self storeSegmentedWidth];
  44. [self reloadData];
  45. CGRect lineRext = [self measureLineFrame];
  46. self.lineView.frame = lineRext;
  47. ///设置偏移量
  48. [self setContentOffset:CGPointMake([self measureContentOffsetX], 0)];
  49. }
  50. - (void)updateSelectSeg{
  51. [self storeSegmentedWidth];
  52. [self reloadData];
  53. [UIView animateWithDuration:0.3 animations:^{
  54. CGRect lineRext = [self measureLineFrame];
  55. self.lineView.frame = lineRext;
  56. }];
  57. [self setContentOffset:CGPointMake([self measureContentOffsetX], 0) animated:YES];
  58. }
  59. #pragma mark ========== 储存计算好的item宽度 ==========
  60. ///每次切换时更新
  61. - (void)storeSegmentedWidth{
  62. _selectIndex = 0;
  63. _totalContentWidth = 0;
  64. [self.widthsArray removeAllObjects];
  65. if (_selectString) {
  66. for (int i = 0; i < _titleArray.count; i ++) {
  67. NSString *title = _titleArray[i];
  68. if ([title isEqualToString:_selectString]) {
  69. _selectIndex = i;
  70. break;
  71. }
  72. }
  73. }
  74. for (int i = 0; i < _titleArray.count; i ++) {
  75. CGSize size = [self measureTitleIndex:i];
  76. NSNumber *value = [NSNumber numberWithFloat:size.width];
  77. [self.widthsArray addObject:value];
  78. _totalContentWidth = _totalContentWidth + size.width;
  79. if (i < _titleArray.count - 1) {
  80. _totalContentWidth = _totalContentWidth + _margin_space;
  81. }
  82. }
  83. _totalContentWidth = _totalContentWidth + _margin_left + _margin_right;
  84. }
  85. - (CGSize)measureTitleIndex:(NSUInteger)index {
  86. if (index >= _titleArray.count) {
  87. return CGSizeZero;
  88. }
  89. id title = _titleArray[index];
  90. CGSize size = CGSizeZero;
  91. BOOL selected = (index == _selectIndex);
  92. NSDictionary *titleAttrs = selected ? [self resultingSelectedTitleTextAttributes] : [self resultingTitleTextAttributes];
  93. size = [(NSString *)title sizeWithAttributes:titleAttrs];
  94. UIFont *font = titleAttrs[@"NSFont"];
  95. size = CGSizeMake(ceil(size.width), ceil(size.height - font.descender));
  96. CGSize resault = CGRectIntegral((CGRect){CGPointZero, size}).size;
  97. return resault;
  98. }
  99. - (NSDictionary *)resultingSelectedTitleTextAttributes {
  100. NSDictionary *resultingAttrs = @{NSForegroundColorAttributeName : [UIColor blackColor] ,NSFontAttributeName:[UIFont fontWithName:@"Helvetica-Bold" size:18.0]};
  101. return resultingAttrs;
  102. }
  103. - (NSDictionary *)resultingTitleTextAttributes {
  104. NSDictionary *resultingAttrs = @{NSForegroundColorAttributeName : [UIColor lightGrayColor],NSFontAttributeName:[UIFont systemFontOfSize:14.0]};
  105. return resultingAttrs;
  106. }
  107. #pragma mark ========== 计算下划线位置 ==========
  108. - (CGRect)measureLineFrame{
  109. CGRect lineRect = CGRectZero;
  110. CGFloat lineRectX = 0;
  111. for (int i = 0; i < _selectIndex; i ++) {
  112. NSNumber *number = self.widthsArray[i];
  113. lineRectX = lineRectX + [number floatValue] + _margin_space;
  114. }
  115. CGFloat widthSelect = [self.widthsArray[_selectIndex] floatValue];
  116. CGFloat lastLocation = widthSelect >= _line_width ? (widthSelect - _line_width)/2 : (_line_width - widthSelect)/2;
  117. lineRectX = lineRectX + _margin_left + lastLocation;
  118. lineRect = CGRectMake(lineRectX, self.bounds.size.height - _line_height - 2, _line_width, _line_height);
  119. return lineRect;
  120. }
  121. #pragma mark ========== 计算偏移量 ==========
  122. - (CGFloat)measureContentOffsetX{
  123. CGFloat selfWidth = self.bounds.size.width;
  124. ///先计算点击的item中心点
  125. CGFloat selectedCenterX = 0;
  126. for (int i = 0; i < _selectIndex; i ++) {
  127. NSNumber *number = self.widthsArray[i];
  128. selectedCenterX = selectedCenterX + [number floatValue] + _margin_space;
  129. }
  130. CGFloat widthSelect = [self.widthsArray[_selectIndex] floatValue];
  131. selectedCenterX = selectedCenterX + widthSelect/2;
  132. if (_totalContentWidth <= selfWidth) {///充满内部不做偏移
  133. return 0;
  134. }
  135. if (selectedCenterX <= selfWidth/2) {
  136. return 0;
  137. }
  138. else if (selectedCenterX >= _totalContentWidth - selfWidth/2){
  139. return _totalContentWidth - selfWidth;
  140. }
  141. else{
  142. return selectedCenterX - selfWidth/2;
  143. }
  144. }
  145. #pragma mark ========== 代理 ==========
  146. - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{
  147. return _titleArray.count;
  148. }
  149. - (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section{
  150. return _margin_space;
  151. }
  152. - (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section{
  153. return UIEdgeInsetsMake(_margin_top, _margin_left, _margin_bottom, _margin_right);
  154. }
  155. //item大小
  156. - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath{
  157. NSNumber *number = self.widthsArray[indexPath.row];
  158. return CGSizeMake([number floatValue],30);
  159. }
  160. - (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
  161. XKCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"XKCollectionViewCell" forIndexPath:indexPath];
  162. NSString *title = _titleArray[indexPath.row];
  163. cell.title = title;
  164. if (indexPath.row == _selectIndex) {
  165. cell.isSelectd = YES;
  166. }
  167. else{
  168. cell.isSelectd = NO;
  169. }
  170. return cell;
  171. }
  172. - (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{
  173. _selectString = _titleArray[indexPath.row];
  174. [self updateSelectSeg];
  175. }
  176. #pragma mark ========== 变量 ==========
  177.  
  178. - (UIView *)lineView{
  179. if(!_lineView){
  180. _lineView = [[UIView alloc]init];
  181. _lineView.backgroundColor = [UIColor purpleColor];
  182. _lineView.layer.masksToBounds = YES;
  183. _lineView.layer.cornerRadius = _line_height/2;
  184. }
  185. return _lineView;
  186. }
  187. @end

 

原文链接:http://www.cnblogs.com/wangkejia/p/11158051.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号