新UI马甲包

FSSegmentTitleView.m 10KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  1. //
  2. // FSSegmentTitleView.m
  3. // FSScrollContentViewDemo
  4. //
  5. // Created by huim on 2017/5/3.
  6. // Copyright © 2017年 fengshun. All rights reserved.
  7. //
  8. #import "FSSegmentTitleView.h"
  9. @interface FSSegmentTitleView ()
  10. @property (nonatomic, strong) UIScrollView *scrollView;
  11. @property (nonatomic, strong) NSMutableArray<UIButton *> *itemBtnArr;
  12. @property (nonatomic, strong) UIView *indicatorView;
  13. @property (nonatomic, assign) FSIndicatorType indicatorType;
  14. @property (nonatomic, strong) NSArray *titlesArr;
  15. @end
  16. @implementation FSSegmentTitleView
  17. - (instancetype)initWithFrame:(CGRect)frame titles:(NSArray *)titlesArr delegate:(id<FSSegmentTitleViewDelegate>)delegate indicatorType:(FSIndicatorType)incatorType
  18. {
  19. self = [super initWithFrame:frame];
  20. if (self) {
  21. [self initWithProperty];
  22. self.titlesArr = titlesArr;
  23. self.delegate = delegate;
  24. self.indicatorType = incatorType;
  25. }
  26. return self;
  27. }
  28. //初始化默认属性值
  29. - (void)initWithProperty
  30. {
  31. self.itemMargin = 30;
  32. self.selectIndex = 0;
  33. self.titleNormalColor = [UIColor YHColorWithHex:0x4A4A4A];
  34. self.titleSelectColor = [UIColor YHColorWithHex:0xEBB189];
  35. self.titleFont = [UIFont systemFontOfSize:15];
  36. self.indicatorColor = self.titleSelectColor;
  37. self.indicatorExtension = 5.f;
  38. self.titleSelectFont = self.titleFont;
  39. }
  40. //重新布局frame
  41. - (void)layoutSubviews
  42. {
  43. [super layoutSubviews];
  44. self.scrollView.frame = self.bounds;
  45. if (self.itemBtnArr.count == 0) {
  46. return;
  47. }
  48. CGFloat totalBtnWidth = 0.0;
  49. UIFont *titleFont = _titleFont;
  50. if (_titleFont != _titleSelectFont) {
  51. for (int idx = 0; idx < self.titlesArr.count; idx++) {
  52. UIButton *btn = self.itemBtnArr[idx];
  53. titleFont = btn.isSelected?_titleSelectFont:_titleFont;
  54. CGFloat itemBtnWidth = [FSSegmentTitleView getWidthWithString:self.titlesArr[idx] font:titleFont] + self.itemMargin;
  55. totalBtnWidth += itemBtnWidth;
  56. }
  57. }
  58. else
  59. {
  60. for (NSString *title in self.titlesArr) {
  61. CGFloat itemBtnWidth = [FSSegmentTitleView getWidthWithString:title font:titleFont] + self.itemMargin;
  62. totalBtnWidth += itemBtnWidth;
  63. }
  64. }
  65. if (totalBtnWidth <= CGRectGetWidth(self.bounds)) {//不能滑动
  66. CGFloat itemBtnWidth = CGRectGetWidth(self.bounds)/self.itemBtnArr.count;
  67. CGFloat itemBtnHeight = CGRectGetHeight(self.bounds);
  68. [self.itemBtnArr enumerateObjectsUsingBlock:^(UIButton * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
  69. obj.frame = CGRectMake(idx * itemBtnWidth, 0, itemBtnWidth, itemBtnHeight);
  70. }];
  71. self.scrollView.contentSize = CGSizeMake(CGRectGetWidth(self.bounds), CGRectGetHeight(self.scrollView.bounds));
  72. }else{//超出屏幕 可以滑动
  73. CGFloat currentX = 0;
  74. for (int idx = 0; idx < self.titlesArr.count; idx++) {
  75. UIButton *btn = self.itemBtnArr[idx];
  76. titleFont = btn.isSelected?_titleSelectFont:_titleFont;
  77. CGFloat itemBtnWidth = [FSSegmentTitleView getWidthWithString:self.titlesArr[idx] font:titleFont] + self.itemMargin;
  78. CGFloat itemBtnHeight = CGRectGetHeight(self.bounds);
  79. btn.frame = CGRectMake(currentX, 0, itemBtnWidth, itemBtnHeight);
  80. currentX += itemBtnWidth;
  81. }
  82. self.scrollView.contentSize = CGSizeMake(currentX, CGRectGetHeight(self.scrollView.bounds));
  83. }
  84. [self moveIndicatorView:YES];
  85. }
  86. - (void)moveIndicatorView:(BOOL)animated
  87. {
  88. UIFont *titleFont = _titleFont;
  89. UIButton *selectBtn = self.itemBtnArr[self.selectIndex];
  90. titleFont = selectBtn.isSelected?_titleSelectFont:_titleFont;
  91. CGFloat indicatorWidth = [FSSegmentTitleView getWidthWithString:self.titlesArr[self.selectIndex] font:titleFont];
  92. [UIView animateWithDuration:(animated?0.05:0) animations:^{
  93. switch (_indicatorType) {
  94. case FSIndicatorTypeDefault:
  95. self.indicatorView.center = CGPointMake(selectBtn.center.x, CGRectGetHeight(self.scrollView.bounds) - 1);
  96. self.indicatorView.bounds = CGRectMake(0, 0, indicatorWidth, 2);
  97. break;
  98. case FSIndicatorTypeEqualTitle:
  99. self.indicatorView.center = CGPointMake(selectBtn.center.x, CGRectGetHeight(self.scrollView.bounds) - 1);
  100. self.indicatorView.bounds = CGRectMake(0, 0, indicatorWidth, 2);
  101. break;
  102. case FSIndicatorTypeCustom:
  103. self.indicatorView.center = CGPointMake(selectBtn.center.x, CGRectGetHeight(self.scrollView.bounds) - 1);
  104. self.indicatorView.bounds = CGRectMake(0, 0, indicatorWidth + _indicatorExtension*2, 2);
  105. break;
  106. case FSIndicatorTypeNone:
  107. self.indicatorView.frame = CGRectZero;
  108. break;
  109. default:
  110. break;
  111. }
  112. } completion:^(BOOL finished) {
  113. [self scrollSelectBtnCenter:animated];
  114. }];
  115. }
  116. - (void)scrollSelectBtnCenter:(BOOL)animated
  117. {
  118. UIButton *selectBtn = self.itemBtnArr[self.selectIndex];
  119. CGRect centerRect = CGRectMake(selectBtn.center.x - CGRectGetWidth(self.scrollView.bounds)/2, 0, CGRectGetWidth(self.scrollView.bounds), CGRectGetHeight(self.scrollView.bounds));
  120. [self.scrollView scrollRectToVisible:centerRect animated:animated];
  121. }
  122. #pragma mark --LazyLoad
  123. - (UIScrollView *)scrollView {
  124. if (!_scrollView) {
  125. _scrollView = [[UIScrollView alloc] init];
  126. _scrollView.showsHorizontalScrollIndicator = NO;
  127. _scrollView.showsVerticalScrollIndicator = NO;
  128. _scrollView.scrollsToTop = NO;
  129. [self addSubview:_scrollView];
  130. }
  131. return _scrollView;
  132. }
  133. - (NSMutableArray<UIButton *>*)itemBtnArr
  134. {
  135. if (!_itemBtnArr) {
  136. _itemBtnArr = [[NSMutableArray alloc]init];
  137. }
  138. return _itemBtnArr;
  139. }
  140. - (UIView *)indicatorView
  141. {
  142. if (!_indicatorView) {
  143. _indicatorView = [[UIView alloc]init];
  144. [self.scrollView addSubview:_indicatorView];
  145. }
  146. return _indicatorView;
  147. }
  148. #pragma mark --Setter
  149. - (void)setTitlesArr:(NSArray *)titlesArr
  150. {
  151. _titlesArr = titlesArr;
  152. [self.itemBtnArr makeObjectsPerformSelector:@selector(removeFromSuperview)];
  153. self.itemBtnArr = nil;
  154. for (NSString *title in titlesArr) {
  155. UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
  156. btn.tag = self.itemBtnArr.count + 666;
  157. [btn setTitle:title forState:UIControlStateNormal];
  158. [btn setTitleColor:_titleNormalColor forState:UIControlStateNormal];
  159. [btn setTitleColor:_titleSelectColor forState:UIControlStateSelected];
  160. btn.titleLabel.font = _titleFont;
  161. [self.scrollView addSubview:btn];
  162. [btn addTarget:self action:@selector(btnClick:) forControlEvents:UIControlEventTouchUpInside];
  163. if (self.itemBtnArr.count == self.selectIndex) {
  164. btn.selected = YES;
  165. }
  166. [self.itemBtnArr addObject:btn];
  167. }
  168. [self setNeedsLayout];
  169. [self layoutIfNeeded];
  170. }
  171. - (void)setItemMargin:(CGFloat)itemMargin
  172. {
  173. _itemMargin = itemMargin;
  174. [self setNeedsLayout];
  175. [self layoutIfNeeded];
  176. }
  177. - (void)setSelectIndex:(NSInteger)selectIndex
  178. {
  179. if (_selectIndex == selectIndex||_selectIndex < 0||_selectIndex > self.itemBtnArr.count - 1) {
  180. return;
  181. }
  182. UIButton *lastBtn = [self.scrollView viewWithTag:_selectIndex + 666];
  183. lastBtn.selected = NO;
  184. lastBtn.titleLabel.font = _titleFont;
  185. _selectIndex = selectIndex;
  186. UIButton *currentBtn = [self.scrollView viewWithTag:_selectIndex + 666];
  187. currentBtn.selected = YES;
  188. currentBtn.titleLabel.font = _titleSelectFont;
  189. // [self moveIndicatorView:YES];
  190. [self setNeedsLayout];
  191. [self layoutIfNeeded];
  192. }
  193. - (void)setTitleFont:(UIFont *)titleFont
  194. {
  195. _titleFont = titleFont;
  196. for (UIButton *btn in self.itemBtnArr) {
  197. btn.titleLabel.font = titleFont;
  198. }
  199. [self setNeedsLayout];
  200. [self layoutIfNeeded];
  201. }
  202. - (void)setTitleSelectFont:(UIFont *)titleSelectFont
  203. {
  204. if (_titleFont == titleSelectFont) {
  205. _titleSelectFont = _titleFont;
  206. return;
  207. }
  208. _titleSelectFont = titleSelectFont;
  209. for (UIButton *btn in self.itemBtnArr) {
  210. btn.titleLabel.font = btn.isSelected?titleSelectFont:_titleFont;
  211. }
  212. [self setNeedsLayout];
  213. [self layoutIfNeeded];
  214. }
  215. - (void)setTitleNormalColor:(UIColor *)titleNormalColor
  216. {
  217. _titleNormalColor = titleNormalColor;
  218. for (UIButton *btn in self.itemBtnArr) {
  219. [btn setTitleColor:titleNormalColor forState:UIControlStateNormal];
  220. }
  221. }
  222. - (void)setTitleSelectColor:(UIColor *)titleSelectColor
  223. {
  224. _titleSelectColor = titleSelectColor;
  225. for (UIButton *btn in self.itemBtnArr) {
  226. [btn setTitleColor:titleSelectColor forState:UIControlStateSelected];
  227. }
  228. }
  229. - (void)setIndicatorColor:(UIColor *)indicatorColor
  230. {
  231. _indicatorColor = indicatorColor;
  232. self.indicatorView.backgroundColor = indicatorColor;
  233. }
  234. - (void)setIndicatorExtension:(CGFloat)indicatorExtension
  235. {
  236. _indicatorExtension = indicatorExtension;
  237. [self setNeedsLayout];
  238. [self layoutIfNeeded];
  239. }
  240. #pragma mark --Btn
  241. - (void)btnClick:(UIButton *)btn
  242. {
  243. NSInteger index = btn.tag - 666;
  244. if (index == self.selectIndex) {
  245. return;
  246. }
  247. if (self.delegate&&[self.delegate respondsToSelector:@selector(FSSegmentTitleView:startIndex:endIndex:)]) {
  248. [self.delegate FSSegmentTitleView:self startIndex:self.selectIndex endIndex:index];
  249. }
  250. self.selectIndex = index;
  251. }
  252. #pragma mark Private
  253. /**
  254. 计算字符串长度
  255. @param string string
  256. @param font font
  257. @return 字符串长度
  258. */
  259. + (CGFloat)getWidthWithString:(NSString *)string font:(UIFont *)font {
  260. NSDictionary *attrs = @{NSFontAttributeName : font};
  261. return [string boundingRectWithSize:CGSizeMake(0, 0) options:NSStringDrawingUsesLineFragmentOrigin attributes:attrs context:nil].size.width;
  262. }
  263. /**
  264. 随机色
  265. @return 调试用
  266. */
  267. + (UIColor*) randomColor{
  268. NSInteger r = arc4random() % 255;
  269. NSInteger g = arc4random() % 255;
  270. NSInteger b = arc4random() % 255;
  271. return [UIColor colorWithRed:r/255.0 green:g/255.0 blue:b/255.0 alpha:1];
  272. }
  273. @end