react-native-navigation的迁移库

HMSegmentedControl.m 43KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959
  1. //
  2. // HMSegmentedControl.m
  3. // HMSegmentedControl
  4. //
  5. // Created by Hesham Abd-Elmegid on 23/12/12.
  6. // Copyright (c) 2012-2015 Hesham Abd-Elmegid. All rights reserved.
  7. //
  8. #import "HMSegmentedControl.h"
  9. #import <QuartzCore/QuartzCore.h>
  10. #import <math.h>
  11. @interface HMScrollView : UIScrollView
  12. @end
  13. @interface HMSegmentedControl ()
  14. @property (nonatomic, strong) CALayer *selectionIndicatorStripLayer;
  15. @property (nonatomic, strong) CALayer *selectionIndicatorBoxLayer;
  16. @property (nonatomic, strong) CALayer *selectionIndicatorArrowLayer;
  17. @property (nonatomic, readwrite) CGFloat segmentWidth;
  18. @property (nonatomic, readwrite) NSArray<NSNumber *> *segmentWidthsArray;
  19. @property (nonatomic, strong) HMScrollView *scrollView;
  20. @end
  21. @implementation HMScrollView
  22. - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
  23. if (!self.dragging) {
  24. [self.nextResponder touchesBegan:touches withEvent:event];
  25. } else {
  26. [super touchesBegan:touches withEvent:event];
  27. }
  28. }
  29. - (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
  30. if (!self.dragging) {
  31. [self.nextResponder touchesMoved:touches withEvent:event];
  32. } else{
  33. [super touchesMoved:touches withEvent:event];
  34. }
  35. }
  36. - (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
  37. if (!self.dragging) {
  38. [self.nextResponder touchesEnded:touches withEvent:event];
  39. } else {
  40. [super touchesEnded:touches withEvent:event];
  41. }
  42. }
  43. @end
  44. @implementation HMSegmentedControl
  45. - (id)initWithCoder:(NSCoder *)aDecoder {
  46. self = [super initWithCoder:aDecoder];
  47. if (self) {
  48. [self commonInit];
  49. }
  50. return self;
  51. }
  52. - (id)initWithFrame:(CGRect)frame {
  53. self = [super initWithFrame:frame];
  54. if (self) {
  55. [self commonInit];
  56. }
  57. return self;
  58. }
  59. - (id)initWithSectionTitles:(NSArray<NSString *> *)sectiontitles {
  60. self = [super initWithFrame:CGRectZero];
  61. if (self) {
  62. [self commonInit];
  63. self.sectionTitles = sectiontitles;
  64. self.type = HMSegmentedControlTypeText;
  65. }
  66. return self;
  67. }
  68. - (id)initWithSectionImages:(NSArray<UIImage *> *)sectionImages sectionSelectedImages:(NSArray<UIImage *> *)sectionSelectedImages {
  69. self = [super initWithFrame:CGRectZero];
  70. if (self) {
  71. [self commonInit];
  72. self.sectionImages = sectionImages;
  73. self.sectionSelectedImages = sectionSelectedImages;
  74. self.type = HMSegmentedControlTypeImages;
  75. }
  76. return self;
  77. }
  78. - (instancetype)initWithSectionImages:(NSArray<UIImage *> *)sectionImages sectionSelectedImages:(NSArray<UIImage *> *)sectionSelectedImages titlesForSections:(NSArray<NSString *> *)sectiontitles {
  79. self = [super initWithFrame:CGRectZero];
  80. if (self) {
  81. [self commonInit];
  82. if (sectionImages.count != sectiontitles.count) {
  83. [NSException raise:NSRangeException format:@"***%s: Images bounds (%ld) Don't match Title bounds (%ld)", sel_getName(_cmd), (unsigned long)sectionImages.count, (unsigned long)sectiontitles.count];
  84. }
  85. self.sectionImages = sectionImages;
  86. self.sectionSelectedImages = sectionSelectedImages;
  87. self.sectionTitles = sectiontitles;
  88. self.type = HMSegmentedControlTypeTextImages;
  89. }
  90. return self;
  91. }
  92. - (void)awakeFromNib {
  93. [super awakeFromNib];
  94. self.segmentWidth = 0.0f;
  95. }
  96. - (void)commonInit {
  97. self.scrollView = [[HMScrollView alloc] init];
  98. self.scrollView.scrollsToTop = NO;
  99. self.scrollView.showsVerticalScrollIndicator = NO;
  100. self.scrollView.showsHorizontalScrollIndicator = NO;
  101. [self addSubview:self.scrollView];
  102. _backgroundColor = [UIColor whiteColor];
  103. self.opaque = NO;
  104. _selectionIndicatorColor = [UIColor colorWithRed:52.0f/255.0f green:181.0f/255.0f blue:229.0f/255.0f alpha:1.0f];
  105. _selectionIndicatorBoxColor = _selectionIndicatorColor;
  106. self.selectedSegmentIndex = 0;
  107. self.segmentEdgeInset = UIEdgeInsetsMake(0, 5, 0, 5);
  108. self.selectionIndicatorHeight = 5.0f;
  109. self.selectionIndicatorEdgeInsets = UIEdgeInsetsMake(0.0f, 0.0f, 0.0f, 0.0f);
  110. self.selectionStyle = HMSegmentedControlSelectionStyleTextWidthStripe;
  111. self.selectionIndicatorLocation = HMSegmentedControlSelectionIndicatorLocationUp;
  112. self.segmentWidthStyle = HMSegmentedControlSegmentWidthStyleFixed;
  113. self.userDraggable = YES;
  114. self.touchEnabled = YES;
  115. self.verticalDividerEnabled = NO;
  116. self.type = HMSegmentedControlTypeText;
  117. self.verticalDividerWidth = 1.0f;
  118. _verticalDividerColor = [UIColor blackColor];
  119. self.borderColor = [UIColor blackColor];
  120. self.borderWidth = 1.0f;
  121. self.shouldAnimateUserSelection = YES;
  122. self.selectionIndicatorArrowLayer = [CALayer layer];
  123. self.selectionIndicatorStripLayer = [CALayer layer];
  124. self.selectionIndicatorBoxLayer = [CALayer layer];
  125. self.selectionIndicatorBoxLayer.opacity = self.selectionIndicatorBoxOpacity;
  126. self.selectionIndicatorBoxLayer.borderWidth = 1.0f;
  127. self.selectionIndicatorBoxOpacity = 0.2;
  128. self.contentMode = UIViewContentModeRedraw;
  129. }
  130. - (void)layoutSubviews {
  131. [super layoutSubviews];
  132. [self updateSegmentsRects];
  133. }
  134. - (void)setFrame:(CGRect)frame {
  135. [super setFrame:frame];
  136. [self updateSegmentsRects];
  137. }
  138. - (void)setSectionTitles:(NSArray<NSString *> *)sectionTitles {
  139. _sectionTitles = sectionTitles;
  140. [self setNeedsLayout];
  141. [self setNeedsDisplay];
  142. }
  143. - (void)setSectionImages:(NSArray<UIImage *> *)sectionImages {
  144. _sectionImages = sectionImages;
  145. [self setNeedsLayout];
  146. [self setNeedsDisplay];
  147. }
  148. - (void)setSelectionIndicatorLocation:(HMSegmentedControlSelectionIndicatorLocation)selectionIndicatorLocation {
  149. _selectionIndicatorLocation = selectionIndicatorLocation;
  150. if (selectionIndicatorLocation == HMSegmentedControlSelectionIndicatorLocationNone) {
  151. self.selectionIndicatorHeight = 0.0f;
  152. }
  153. }
  154. - (void)setSelectionIndicatorBoxOpacity:(CGFloat)selectionIndicatorBoxOpacity {
  155. _selectionIndicatorBoxOpacity = selectionIndicatorBoxOpacity;
  156. self.selectionIndicatorBoxLayer.opacity = _selectionIndicatorBoxOpacity;
  157. }
  158. - (void)setSegmentWidthStyle:(HMSegmentedControlSegmentWidthStyle)segmentWidthStyle {
  159. // Force HMSegmentedControlSegmentWidthStyleFixed when type is HMSegmentedControlTypeImages.
  160. if (self.type == HMSegmentedControlTypeImages) {
  161. _segmentWidthStyle = HMSegmentedControlSegmentWidthStyleFixed;
  162. } else {
  163. _segmentWidthStyle = segmentWidthStyle;
  164. }
  165. }
  166. - (void)setBorderType:(HMSegmentedControlBorderType)borderType {
  167. _borderType = borderType;
  168. [self setNeedsDisplay];
  169. }
  170. #pragma mark - Drawing
  171. - (CGSize)measureTitleAtIndex:(NSUInteger)index {
  172. if (index >= self.sectionTitles.count) {
  173. return CGSizeZero;
  174. }
  175. id title = self.sectionTitles[index];
  176. CGSize size = CGSizeZero;
  177. BOOL selected = (index == self.selectedSegmentIndex) ? YES : NO;
  178. if ([title isKindOfClass:[NSString class]] && !self.titleFormatter) {
  179. NSDictionary *titleAttrs = selected ? [self resultingSelectedTitleTextAttributes] : [self resultingTitleTextAttributes];
  180. size = [(NSString *)title sizeWithAttributes:titleAttrs];
  181. } else if ([title isKindOfClass:[NSString class]] && self.titleFormatter) {
  182. size = [self.titleFormatter(self, title, index, selected) size];
  183. } else if ([title isKindOfClass:[NSAttributedString class]]) {
  184. size = [(NSAttributedString *)title size];
  185. } else {
  186. NSAssert(title == nil, @"Unexpected type of segment title: %@", [title class]);
  187. size = CGSizeZero;
  188. }
  189. return CGRectIntegral((CGRect){CGPointZero, size}).size;
  190. }
  191. - (NSAttributedString *)attributedTitleAtIndex:(NSUInteger)index {
  192. id title = self.sectionTitles[index];
  193. BOOL selected = (index == self.selectedSegmentIndex) ? YES : NO;
  194. if ([title isKindOfClass:[NSAttributedString class]]) {
  195. return (NSAttributedString *)title;
  196. } else if (!self.titleFormatter) {
  197. NSDictionary *titleAttrs = selected ? [self resultingSelectedTitleTextAttributes] : [self resultingTitleTextAttributes];
  198. // the color should be cast to CGColor in order to avoid invalid context on iOS7
  199. UIColor *titleColor = titleAttrs[NSForegroundColorAttributeName];
  200. if (titleColor) {
  201. NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithDictionary:titleAttrs];
  202. dict[NSForegroundColorAttributeName] = (id)titleColor.CGColor;
  203. titleAttrs = [NSDictionary dictionaryWithDictionary:dict];
  204. }
  205. return [[NSAttributedString alloc] initWithString:(NSString *)title attributes:titleAttrs];
  206. } else {
  207. return self.titleFormatter(self, title, index, selected);
  208. }
  209. }
  210. - (void)drawRect:(CGRect)rect {
  211. [self.backgroundColor setFill];
  212. UIRectFill([self bounds]);
  213. self.selectionIndicatorArrowLayer.backgroundColor = self.selectionIndicatorColor.CGColor;
  214. self.selectionIndicatorStripLayer.backgroundColor = self.selectionIndicatorColor.CGColor;
  215. self.selectionIndicatorBoxLayer.backgroundColor = self.selectionIndicatorBoxColor.CGColor;
  216. self.selectionIndicatorBoxLayer.borderColor = self.selectionIndicatorBoxColor.CGColor;
  217. // Remove all sublayers to avoid drawing images over existing ones
  218. self.scrollView.layer.sublayers = nil;
  219. CGRect oldRect = rect;
  220. if (self.type == HMSegmentedControlTypeText) {
  221. [self.sectionTitles enumerateObjectsUsingBlock:^(id titleString, NSUInteger idx, BOOL *stop) {
  222. CGFloat stringWidth = 0;
  223. CGFloat stringHeight = 0;
  224. CGSize size = [self measureTitleAtIndex:idx];
  225. stringWidth = size.width;
  226. stringHeight = size.height;
  227. CGRect rectDiv = CGRectZero;
  228. CGRect fullRect = CGRectZero;
  229. // Text inside the CATextLayer will appear blurry unless the rect values are rounded
  230. BOOL locationUp = (self.selectionIndicatorLocation == HMSegmentedControlSelectionIndicatorLocationUp);
  231. BOOL selectionStyleNotBox = (self.selectionStyle != HMSegmentedControlSelectionStyleBox);
  232. CGFloat y = roundf((CGRectGetHeight(self.frame) - selectionStyleNotBox * self.selectionIndicatorHeight) / 2 - stringHeight / 2 + self.selectionIndicatorHeight * locationUp);
  233. CGRect rect;
  234. if (self.segmentWidthStyle == HMSegmentedControlSegmentWidthStyleFixed) {
  235. rect = CGRectMake((self.segmentWidth * idx) + (self.segmentWidth - stringWidth) / 2, y, stringWidth, stringHeight);
  236. rectDiv = CGRectMake((self.segmentWidth * idx) - (self.verticalDividerWidth / 2), self.selectionIndicatorHeight * 2, self.verticalDividerWidth, self.frame.size.height - (self.selectionIndicatorHeight * 4));
  237. fullRect = CGRectMake(self.segmentWidth * idx, 0, self.segmentWidth, oldRect.size.height);
  238. } else {
  239. // When we are drawing dynamic widths, we need to loop the widths array to calculate the xOffset
  240. CGFloat xOffset = 0;
  241. NSInteger i = 0;
  242. for (NSNumber *width in self.segmentWidthsArray) {
  243. if (idx == i)
  244. break;
  245. xOffset = xOffset + [width floatValue];
  246. i++;
  247. }
  248. CGFloat widthForIndex = [[self.segmentWidthsArray objectAtIndex:idx] floatValue];
  249. rect = CGRectMake(xOffset, y, widthForIndex, stringHeight);
  250. fullRect = CGRectMake(self.segmentWidth * idx, 0, widthForIndex, oldRect.size.height);
  251. rectDiv = CGRectMake(xOffset - (self.verticalDividerWidth / 2), self.selectionIndicatorHeight * 2, self.verticalDividerWidth, self.frame.size.height - (self.selectionIndicatorHeight * 4));
  252. }
  253. // Fix rect position/size to avoid blurry labels
  254. rect = CGRectMake(ceilf(rect.origin.x), ceilf(rect.origin.y), ceilf(rect.size.width), ceilf(rect.size.height));
  255. CATextLayer *titleLayer = [CATextLayer layer];
  256. titleLayer.frame = rect;
  257. titleLayer.alignmentMode = kCAAlignmentCenter;
  258. if ([UIDevice currentDevice].systemVersion.floatValue < 10.0 ) {
  259. titleLayer.truncationMode = kCATruncationEnd;
  260. }
  261. titleLayer.string = [self attributedTitleAtIndex:idx];
  262. titleLayer.contentsScale = [[UIScreen mainScreen] scale];
  263. [self.scrollView.layer addSublayer:titleLayer];
  264. // Vertical Divider
  265. if (self.isVerticalDividerEnabled && idx > 0) {
  266. CALayer *verticalDividerLayer = [CALayer layer];
  267. verticalDividerLayer.frame = rectDiv;
  268. verticalDividerLayer.backgroundColor = self.verticalDividerColor.CGColor;
  269. [self.scrollView.layer addSublayer:verticalDividerLayer];
  270. }
  271. [self addBackgroundAndBorderLayerWithRect:fullRect];
  272. }];
  273. } else if (self.type == HMSegmentedControlTypeImages) {
  274. [self.sectionImages enumerateObjectsUsingBlock:^(id iconImage, NSUInteger idx, BOOL *stop) {
  275. UIImage *icon = iconImage;
  276. CGFloat imageWidth = icon.size.width;
  277. CGFloat imageHeight = icon.size.height;
  278. CGFloat y = roundf(CGRectGetHeight(self.frame) - self.selectionIndicatorHeight) / 2 - imageHeight / 2 + ((self.selectionIndicatorLocation == HMSegmentedControlSelectionIndicatorLocationUp) ? self.selectionIndicatorHeight : 0);
  279. CGFloat x = self.segmentWidth * idx + (self.segmentWidth - imageWidth)/2.0f;
  280. CGRect rect = CGRectMake(x, y, imageWidth, imageHeight);
  281. CALayer *imageLayer = [CALayer layer];
  282. imageLayer.frame = rect;
  283. if (self.selectedSegmentIndex == idx) {
  284. if (self.sectionSelectedImages) {
  285. UIImage *highlightIcon = [self.sectionSelectedImages objectAtIndex:idx];
  286. imageLayer.contents = (id)highlightIcon.CGImage;
  287. } else {
  288. imageLayer.contents = (id)icon.CGImage;
  289. }
  290. } else {
  291. imageLayer.contents = (id)icon.CGImage;
  292. }
  293. [self.scrollView.layer addSublayer:imageLayer];
  294. // Vertical Divider
  295. if (self.isVerticalDividerEnabled && idx>0) {
  296. CALayer *verticalDividerLayer = [CALayer layer];
  297. verticalDividerLayer.frame = CGRectMake((self.segmentWidth * idx) - (self.verticalDividerWidth / 2), self.selectionIndicatorHeight * 2, self.verticalDividerWidth, self.frame.size.height-(self.selectionIndicatorHeight * 4));
  298. verticalDividerLayer.backgroundColor = self.verticalDividerColor.CGColor;
  299. [self.scrollView.layer addSublayer:verticalDividerLayer];
  300. }
  301. [self addBackgroundAndBorderLayerWithRect:rect];
  302. }];
  303. } else if (self.type == HMSegmentedControlTypeTextImages){
  304. [self.sectionImages enumerateObjectsUsingBlock:^(id iconImage, NSUInteger idx, BOOL *stop) {
  305. UIImage *icon = iconImage;
  306. CGFloat imageWidth = icon.size.width;
  307. CGFloat imageHeight = icon.size.height;
  308. CGSize stringSize = [self measureTitleAtIndex:idx];
  309. CGFloat stringHeight = stringSize.height;
  310. CGFloat stringWidth = stringSize.width;
  311. CGFloat imageXOffset = self.segmentWidth * idx; // Start with edge inset
  312. CGFloat textXOffset = self.segmentWidth * idx;
  313. CGFloat imageYOffset = ceilf((self.frame.size.height - imageHeight) / 2.0); // Start in center
  314. CGFloat textYOffset = ceilf((self.frame.size.height - stringHeight) / 2.0);
  315. if (self.segmentWidthStyle == HMSegmentedControlSegmentWidthStyleFixed) {
  316. BOOL isImageInLineWidthText = self.imagePosition == HMSegmentedControlImagePositionLeftOfText || self.imagePosition == HMSegmentedControlImagePositionRightOfText;
  317. if (isImageInLineWidthText) {
  318. CGFloat whitespace = self.segmentWidth - stringSize.width - imageWidth - self.textImageSpacing;
  319. if (self.imagePosition == HMSegmentedControlImagePositionLeftOfText) {
  320. imageXOffset += whitespace / 2.0;
  321. textXOffset = imageXOffset + imageWidth + self.textImageSpacing;
  322. } else {
  323. textXOffset += whitespace / 2.0;
  324. imageXOffset = textXOffset + stringWidth + self.textImageSpacing;
  325. }
  326. } else {
  327. imageXOffset = self.segmentWidth * idx + (self.segmentWidth - imageWidth) / 2.0f; // Start with edge inset
  328. textXOffset = self.segmentWidth * idx + (self.segmentWidth - stringWidth) / 2.0f;
  329. CGFloat whitespace = CGRectGetHeight(self.frame) - imageHeight - stringHeight - self.textImageSpacing;
  330. if (self.imagePosition == HMSegmentedControlImagePositionAboveText) {
  331. imageYOffset = ceilf(whitespace / 2.0);
  332. textYOffset = imageYOffset + imageHeight + self.textImageSpacing;
  333. } else if (self.imagePosition == HMSegmentedControlImagePositionBelowText) {
  334. textYOffset = ceilf(whitespace / 2.0);
  335. imageYOffset = textYOffset + stringHeight + self.textImageSpacing;
  336. }
  337. }
  338. } else if (self.segmentWidthStyle == HMSegmentedControlSegmentWidthStyleDynamic) {
  339. // When we are drawing dynamic widths, we need to loop the widths array to calculate the xOffset
  340. CGFloat xOffset = 0;
  341. NSInteger i = 0;
  342. for (NSNumber *width in self.segmentWidthsArray) {
  343. if (idx == i) {
  344. break;
  345. }
  346. xOffset = xOffset + [width floatValue];
  347. i++;
  348. }
  349. BOOL isImageInLineWidthText = self.imagePosition == HMSegmentedControlImagePositionLeftOfText || self.imagePosition == HMSegmentedControlImagePositionRightOfText;
  350. if (isImageInLineWidthText) {
  351. if (self.imagePosition == HMSegmentedControlImagePositionLeftOfText) {
  352. imageXOffset = xOffset;
  353. textXOffset = imageXOffset + imageWidth + self.textImageSpacing;
  354. } else {
  355. textXOffset = xOffset;
  356. imageXOffset = textXOffset + stringWidth + self.textImageSpacing;
  357. }
  358. } else {
  359. imageXOffset = xOffset + ([self.segmentWidthsArray[i] floatValue] - imageWidth) / 2.0f; // Start with edge inset
  360. textXOffset = xOffset + ([self.segmentWidthsArray[i] floatValue] - stringWidth) / 2.0f;
  361. CGFloat whitespace = CGRectGetHeight(self.frame) - imageHeight - stringHeight - self.textImageSpacing;
  362. if (self.imagePosition == HMSegmentedControlImagePositionAboveText) {
  363. imageYOffset = ceilf(whitespace / 2.0);
  364. textYOffset = imageYOffset + imageHeight + self.textImageSpacing;
  365. } else if (self.imagePosition == HMSegmentedControlImagePositionBelowText) {
  366. textYOffset = ceilf(whitespace / 2.0);
  367. imageYOffset = textYOffset + stringHeight + self.textImageSpacing;
  368. }
  369. }
  370. }
  371. CGRect imageRect = CGRectMake(imageXOffset, imageYOffset, imageWidth, imageHeight);
  372. CGRect textRect = CGRectMake(ceilf(textXOffset), ceilf(textYOffset), ceilf(stringWidth), ceilf(stringHeight));
  373. CATextLayer *titleLayer = [CATextLayer layer];
  374. titleLayer.frame = textRect;
  375. titleLayer.alignmentMode = kCAAlignmentCenter;
  376. titleLayer.string = [self attributedTitleAtIndex:idx];
  377. if ([UIDevice currentDevice].systemVersion.floatValue < 10.0 ) {
  378. titleLayer.truncationMode = kCATruncationEnd;
  379. }
  380. CALayer *imageLayer = [CALayer layer];
  381. imageLayer.frame = imageRect;
  382. if (self.selectedSegmentIndex == idx) {
  383. if (self.sectionSelectedImages) {
  384. UIImage *highlightIcon = [self.sectionSelectedImages objectAtIndex:idx];
  385. imageLayer.contents = (id)highlightIcon.CGImage;
  386. } else {
  387. imageLayer.contents = (id)icon.CGImage;
  388. }
  389. } else {
  390. imageLayer.contents = (id)icon.CGImage;
  391. }
  392. [self.scrollView.layer addSublayer:imageLayer];
  393. titleLayer.contentsScale = [[UIScreen mainScreen] scale];
  394. [self.scrollView.layer addSublayer:titleLayer];
  395. [self addBackgroundAndBorderLayerWithRect:imageRect];
  396. }];
  397. }
  398. // Add the selection indicators
  399. if (self.selectedSegmentIndex != HMSegmentedControlNoSegment) {
  400. if (self.selectionStyle == HMSegmentedControlSelectionStyleArrow) {
  401. if (!self.selectionIndicatorArrowLayer.superlayer) {
  402. [self setArrowFrame];
  403. [self.scrollView.layer addSublayer:self.selectionIndicatorArrowLayer];
  404. }
  405. } else {
  406. if (!self.selectionIndicatorStripLayer.superlayer) {
  407. self.selectionIndicatorStripLayer.frame = [self frameForSelectionIndicator];
  408. [self.scrollView.layer addSublayer:self.selectionIndicatorStripLayer];
  409. if (self.selectionStyle == HMSegmentedControlSelectionStyleBox && !self.selectionIndicatorBoxLayer.superlayer) {
  410. self.selectionIndicatorBoxLayer.frame = [self frameForFillerSelectionIndicator];
  411. [self.scrollView.layer insertSublayer:self.selectionIndicatorBoxLayer atIndex:0];
  412. }
  413. }
  414. }
  415. }
  416. }
  417. - (void)addBackgroundAndBorderLayerWithRect:(CGRect)fullRect {
  418. // Background layer
  419. CALayer *backgroundLayer = [CALayer layer];
  420. backgroundLayer.frame = fullRect;
  421. [self.layer insertSublayer:backgroundLayer atIndex:0];
  422. // Border layer
  423. if (self.borderType & HMSegmentedControlBorderTypeTop) {
  424. CALayer *borderLayer = [CALayer layer];
  425. borderLayer.frame = CGRectMake(0, 0, fullRect.size.width, self.borderWidth);
  426. borderLayer.backgroundColor = self.borderColor.CGColor;
  427. [backgroundLayer addSublayer: borderLayer];
  428. }
  429. if (self.borderType & HMSegmentedControlBorderTypeLeft) {
  430. CALayer *borderLayer = [CALayer layer];
  431. borderLayer.frame = CGRectMake(0, 0, self.borderWidth, fullRect.size.height);
  432. borderLayer.backgroundColor = self.borderColor.CGColor;
  433. [backgroundLayer addSublayer: borderLayer];
  434. }
  435. if (self.borderType & HMSegmentedControlBorderTypeBottom) {
  436. CALayer *borderLayer = [CALayer layer];
  437. borderLayer.frame = CGRectMake(0, fullRect.size.height - self.borderWidth, fullRect.size.width, self.borderWidth);
  438. borderLayer.backgroundColor = self.borderColor.CGColor;
  439. [backgroundLayer addSublayer: borderLayer];
  440. }
  441. if (self.borderType & HMSegmentedControlBorderTypeRight) {
  442. CALayer *borderLayer = [CALayer layer];
  443. borderLayer.frame = CGRectMake(fullRect.size.width - self.borderWidth, 0, self.borderWidth, fullRect.size.height);
  444. borderLayer.backgroundColor = self.borderColor.CGColor;
  445. [backgroundLayer addSublayer: borderLayer];
  446. }
  447. }
  448. - (void)setArrowFrame {
  449. self.selectionIndicatorArrowLayer.frame = [self frameForSelectionIndicator];
  450. self.selectionIndicatorArrowLayer.mask = nil;
  451. UIBezierPath *arrowPath = [UIBezierPath bezierPath];
  452. CGPoint p1 = CGPointZero;
  453. CGPoint p2 = CGPointZero;
  454. CGPoint p3 = CGPointZero;
  455. if (self.selectionIndicatorLocation == HMSegmentedControlSelectionIndicatorLocationDown) {
  456. p1 = CGPointMake(self.selectionIndicatorArrowLayer.bounds.size.width / 2, 0);
  457. p2 = CGPointMake(0, self.selectionIndicatorArrowLayer.bounds.size.height);
  458. p3 = CGPointMake(self.selectionIndicatorArrowLayer.bounds.size.width, self.selectionIndicatorArrowLayer.bounds.size.height);
  459. }
  460. if (self.selectionIndicatorLocation == HMSegmentedControlSelectionIndicatorLocationUp) {
  461. p1 = CGPointMake(self.selectionIndicatorArrowLayer.bounds.size.width / 2, self.selectionIndicatorArrowLayer.bounds.size.height);
  462. p2 = CGPointMake(self.selectionIndicatorArrowLayer.bounds.size.width, 0);
  463. p3 = CGPointMake(0, 0);
  464. }
  465. [arrowPath moveToPoint:p1];
  466. [arrowPath addLineToPoint:p2];
  467. [arrowPath addLineToPoint:p3];
  468. [arrowPath closePath];
  469. CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init];
  470. maskLayer.frame = self.selectionIndicatorArrowLayer.bounds;
  471. maskLayer.path = arrowPath.CGPath;
  472. self.selectionIndicatorArrowLayer.mask = maskLayer;
  473. }
  474. - (CGRect)frameForSelectionIndicator {
  475. CGFloat indicatorYOffset = 0.0f;
  476. if (self.selectionIndicatorLocation == HMSegmentedControlSelectionIndicatorLocationDown) {
  477. indicatorYOffset = self.bounds.size.height - self.selectionIndicatorHeight + self.selectionIndicatorEdgeInsets.bottom;
  478. }
  479. if (self.selectionIndicatorLocation == HMSegmentedControlSelectionIndicatorLocationUp) {
  480. indicatorYOffset = self.selectionIndicatorEdgeInsets.top;
  481. }
  482. CGFloat sectionWidth = 0.0f;
  483. if (self.type == HMSegmentedControlTypeText) {
  484. CGFloat stringWidth = [self measureTitleAtIndex:self.selectedSegmentIndex].width;
  485. sectionWidth = stringWidth;
  486. } else if (self.type == HMSegmentedControlTypeImages) {
  487. UIImage *sectionImage = [self.sectionImages objectAtIndex:self.selectedSegmentIndex];
  488. CGFloat imageWidth = sectionImage.size.width;
  489. sectionWidth = imageWidth;
  490. } else if (self.type == HMSegmentedControlTypeTextImages) {
  491. CGFloat stringWidth = [self measureTitleAtIndex:self.selectedSegmentIndex].width;
  492. UIImage *sectionImage = [self.sectionImages objectAtIndex:self.selectedSegmentIndex];
  493. CGFloat imageWidth = sectionImage.size.width;
  494. sectionWidth = MAX(stringWidth, imageWidth);
  495. }
  496. if (self.selectionStyle == HMSegmentedControlSelectionStyleArrow) {
  497. CGFloat widthToEndOfSelectedSegment = (self.segmentWidth * self.selectedSegmentIndex) + self.segmentWidth;
  498. CGFloat widthToStartOfSelectedIndex = (self.segmentWidth * self.selectedSegmentIndex);
  499. CGFloat x = widthToStartOfSelectedIndex + ((widthToEndOfSelectedSegment - widthToStartOfSelectedIndex) / 2) - (self.selectionIndicatorHeight/2);
  500. return CGRectMake(x - (self.selectionIndicatorHeight / 2), indicatorYOffset, self.selectionIndicatorHeight * 2, self.selectionIndicatorHeight);
  501. } else {
  502. if (self.selectionStyle == HMSegmentedControlSelectionStyleTextWidthStripe &&
  503. sectionWidth <= self.segmentWidth &&
  504. self.segmentWidthStyle != HMSegmentedControlSegmentWidthStyleDynamic) {
  505. CGFloat widthToEndOfSelectedSegment = (self.segmentWidth * self.selectedSegmentIndex) + self.segmentWidth;
  506. CGFloat widthToStartOfSelectedIndex = (self.segmentWidth * self.selectedSegmentIndex);
  507. CGFloat x = ((widthToEndOfSelectedSegment - widthToStartOfSelectedIndex) / 2) + (widthToStartOfSelectedIndex - sectionWidth / 2);
  508. return CGRectMake(x + self.selectionIndicatorEdgeInsets.left, indicatorYOffset, sectionWidth - self.selectionIndicatorEdgeInsets.right, self.selectionIndicatorHeight);
  509. } else {
  510. if (self.segmentWidthStyle == HMSegmentedControlSegmentWidthStyleDynamic) {
  511. CGFloat selectedSegmentOffset = 0.0f;
  512. NSInteger i = 0;
  513. for (NSNumber *width in self.segmentWidthsArray) {
  514. if (self.selectedSegmentIndex == i)
  515. break;
  516. selectedSegmentOffset = selectedSegmentOffset + [width floatValue];
  517. i++;
  518. }
  519. return CGRectMake(selectedSegmentOffset + self.selectionIndicatorEdgeInsets.left, indicatorYOffset, [[self.segmentWidthsArray objectAtIndex:self.selectedSegmentIndex] floatValue] - self.selectionIndicatorEdgeInsets.right, self.selectionIndicatorHeight + self.selectionIndicatorEdgeInsets.bottom);
  520. }
  521. return CGRectMake((self.segmentWidth + self.selectionIndicatorEdgeInsets.left) * self.selectedSegmentIndex, indicatorYOffset, self.segmentWidth - self.selectionIndicatorEdgeInsets.right, self.selectionIndicatorHeight);
  522. }
  523. }
  524. }
  525. - (CGRect)frameForFillerSelectionIndicator {
  526. if (self.segmentWidthStyle == HMSegmentedControlSegmentWidthStyleDynamic) {
  527. CGFloat selectedSegmentOffset = 0.0f;
  528. NSInteger i = 0;
  529. for (NSNumber *width in self.segmentWidthsArray) {
  530. if (self.selectedSegmentIndex == i) {
  531. break;
  532. }
  533. selectedSegmentOffset = selectedSegmentOffset + [width floatValue];
  534. i++;
  535. }
  536. return CGRectMake(selectedSegmentOffset, 0, [[self.segmentWidthsArray objectAtIndex:self.selectedSegmentIndex] floatValue], CGRectGetHeight(self.frame));
  537. }
  538. return CGRectMake(self.segmentWidth * self.selectedSegmentIndex, 0, self.segmentWidth, CGRectGetHeight(self.frame));
  539. }
  540. - (void)updateSegmentsRects {
  541. self.scrollView.contentInset = UIEdgeInsetsZero;
  542. self.scrollView.frame = CGRectMake(0, 0, CGRectGetWidth(self.frame), CGRectGetHeight(self.frame));
  543. if ([self sectionCount] > 0) {
  544. self.segmentWidth = self.frame.size.width / [self sectionCount];
  545. }
  546. if (self.type == HMSegmentedControlTypeText && self.segmentWidthStyle == HMSegmentedControlSegmentWidthStyleFixed) {
  547. [self.sectionTitles enumerateObjectsUsingBlock:^(id titleString, NSUInteger idx, BOOL *stop) {
  548. CGFloat stringWidth = [self measureTitleAtIndex:idx].width + self.segmentEdgeInset.left + self.segmentEdgeInset.right;
  549. self.segmentWidth = MAX(stringWidth, self.segmentWidth);
  550. }];
  551. } else if (self.type == HMSegmentedControlTypeText && self.segmentWidthStyle == HMSegmentedControlSegmentWidthStyleDynamic) {
  552. NSMutableArray *mutableSegmentWidths = [NSMutableArray array];
  553. [self.sectionTitles enumerateObjectsUsingBlock:^(id titleString, NSUInteger idx, BOOL *stop) {
  554. CGFloat stringWidth = [self measureTitleAtIndex:idx].width + self.segmentEdgeInset.left + self.segmentEdgeInset.right;
  555. [mutableSegmentWidths addObject:[NSNumber numberWithFloat:stringWidth]];
  556. }];
  557. self.segmentWidthsArray = [mutableSegmentWidths copy];
  558. } else if (self.type == HMSegmentedControlTypeImages) {
  559. for (UIImage *sectionImage in self.sectionImages) {
  560. CGFloat imageWidth = sectionImage.size.width + self.segmentEdgeInset.left + self.segmentEdgeInset.right;
  561. self.segmentWidth = MAX(imageWidth, self.segmentWidth);
  562. }
  563. } else if (self.type == HMSegmentedControlTypeTextImages && self.segmentWidthStyle == HMSegmentedControlSegmentWidthStyleFixed){
  564. //lets just use the title.. we will assume it is wider then images...
  565. [self.sectionTitles enumerateObjectsUsingBlock:^(id titleString, NSUInteger idx, BOOL *stop) {
  566. CGFloat stringWidth = [self measureTitleAtIndex:idx].width + self.segmentEdgeInset.left + self.segmentEdgeInset.right;
  567. self.segmentWidth = MAX(stringWidth, self.segmentWidth);
  568. }];
  569. } else if (self.type == HMSegmentedControlTypeTextImages && self.segmentWidthStyle == HMSegmentedControlSegmentWidthStyleDynamic) {
  570. NSMutableArray *mutableSegmentWidths = [NSMutableArray array];
  571. __block CGFloat totalWidth = 0.0;
  572. int i = 0;
  573. [self.sectionTitles enumerateObjectsUsingBlock:^(id titleString, NSUInteger idx, BOOL *stop) {
  574. CGFloat stringWidth = [self measureTitleAtIndex:idx].width + self.segmentEdgeInset.right;
  575. UIImage *sectionImage = [self.sectionImages objectAtIndex:i];
  576. CGFloat imageWidth = sectionImage.size.width + self.segmentEdgeInset.left;
  577. CGFloat combinedWidth = 0.0;
  578. if (self.imagePosition == HMSegmentedControlImagePositionLeftOfText || self.imagePosition == HMSegmentedControlImagePositionRightOfText) {
  579. combinedWidth = imageWidth + stringWidth + self.textImageSpacing;
  580. } else {
  581. combinedWidth = MAX(imageWidth, stringWidth);
  582. }
  583. totalWidth += combinedWidth;
  584. [mutableSegmentWidths addObject:[NSNumber numberWithFloat:combinedWidth]];
  585. }];
  586. if (self.shouldStretchSegmentsToScreenSize && totalWidth < self.bounds.size.width) {
  587. CGFloat whitespace = self.bounds.size.width - totalWidth;
  588. CGFloat whitespaceForSegment = whitespace / [mutableSegmentWidths count];
  589. [mutableSegmentWidths enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
  590. CGFloat extendedWidth = whitespaceForSegment + [obj floatValue];
  591. [mutableSegmentWidths replaceObjectAtIndex:idx withObject:[NSNumber numberWithFloat:extendedWidth]];
  592. }];
  593. }
  594. self.segmentWidthsArray = [mutableSegmentWidths copy];
  595. }
  596. self.scrollView.scrollEnabled = self.isUserDraggable;
  597. self.scrollView.contentSize = CGSizeMake([self totalSegmentedControlWidth], self.frame.size.height);
  598. }
  599. - (NSUInteger)sectionCount {
  600. if (self.type == HMSegmentedControlTypeText) {
  601. return self.sectionTitles.count;
  602. } else if (self.type == HMSegmentedControlTypeImages ||
  603. self.type == HMSegmentedControlTypeTextImages) {
  604. return self.sectionImages.count;
  605. }
  606. return 0;
  607. }
  608. - (void)willMoveToSuperview:(UIView *)newSuperview {
  609. // Control is being removed
  610. if (newSuperview == nil)
  611. return;
  612. if (self.sectionTitles || self.sectionImages) {
  613. [self updateSegmentsRects];
  614. }
  615. }
  616. #pragma mark - Touch
  617. - (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
  618. UITouch *touch = [touches anyObject];
  619. CGPoint touchLocation = [touch locationInView:self];
  620. CGRect enlargeRect = CGRectMake(self.bounds.origin.x - self.enlargeEdgeInset.left,
  621. self.bounds.origin.y - self.enlargeEdgeInset.top,
  622. self.bounds.size.width + self.enlargeEdgeInset.left + self.enlargeEdgeInset.right,
  623. self.bounds.size.height + self.enlargeEdgeInset.top + self.enlargeEdgeInset.bottom);
  624. if (CGRectContainsPoint(enlargeRect, touchLocation)) {
  625. NSInteger segment = 0;
  626. if (self.segmentWidthStyle == HMSegmentedControlSegmentWidthStyleFixed) {
  627. segment = (touchLocation.x + self.scrollView.contentOffset.x) / self.segmentWidth;
  628. } else if (self.segmentWidthStyle == HMSegmentedControlSegmentWidthStyleDynamic) {
  629. // To know which segment the user touched, we need to loop over the widths and substract it from the x position.
  630. CGFloat widthLeft = (touchLocation.x + self.scrollView.contentOffset.x);
  631. for (NSNumber *width in self.segmentWidthsArray) {
  632. widthLeft = widthLeft - [width floatValue];
  633. // When we don't have any width left to substract, we have the segment index.
  634. if (widthLeft <= 0)
  635. break;
  636. segment++;
  637. }
  638. }
  639. NSUInteger sectionsCount = 0;
  640. if (self.type == HMSegmentedControlTypeImages) {
  641. sectionsCount = [self.sectionImages count];
  642. } else if (self.type == HMSegmentedControlTypeTextImages || self.type == HMSegmentedControlTypeText) {
  643. sectionsCount = [self.sectionTitles count];
  644. }
  645. if (segment != self.selectedSegmentIndex && segment < sectionsCount) {
  646. // Check if we have to do anything with the touch event
  647. if (self.isTouchEnabled)
  648. [self setSelectedSegmentIndex:segment animated:self.shouldAnimateUserSelection notify:YES];
  649. }
  650. }
  651. }
  652. #pragma mark - Scrolling
  653. - (CGFloat)totalSegmentedControlWidth {
  654. if (self.type == HMSegmentedControlTypeText && self.segmentWidthStyle == HMSegmentedControlSegmentWidthStyleFixed) {
  655. return self.sectionTitles.count * self.segmentWidth;
  656. } else if (self.segmentWidthStyle == HMSegmentedControlSegmentWidthStyleDynamic) {
  657. return [[self.segmentWidthsArray valueForKeyPath:@"@sum.self"] floatValue];
  658. } else {
  659. return self.sectionImages.count * self.segmentWidth;
  660. }
  661. }
  662. - (void)scrollToSelectedSegmentIndex:(BOOL)animated {
  663. CGRect rectForSelectedIndex = CGRectZero;
  664. CGFloat selectedSegmentOffset = 0;
  665. if (self.segmentWidthStyle == HMSegmentedControlSegmentWidthStyleFixed) {
  666. rectForSelectedIndex = CGRectMake(self.segmentWidth * self.selectedSegmentIndex,
  667. 0,
  668. self.segmentWidth,
  669. self.frame.size.height);
  670. selectedSegmentOffset = (CGRectGetWidth(self.frame) / 2) - (self.segmentWidth / 2);
  671. } else {
  672. NSInteger i = 0;
  673. CGFloat offsetter = 0;
  674. for (NSNumber *width in self.segmentWidthsArray) {
  675. if (self.selectedSegmentIndex == i)
  676. break;
  677. offsetter = offsetter + [width floatValue];
  678. i++;
  679. }
  680. rectForSelectedIndex = CGRectMake(offsetter,
  681. 0,
  682. [[self.segmentWidthsArray objectAtIndex:self.selectedSegmentIndex] floatValue],
  683. self.frame.size.height);
  684. selectedSegmentOffset = (CGRectGetWidth(self.frame) / 2) - ([[self.segmentWidthsArray objectAtIndex:self.selectedSegmentIndex] floatValue] / 2);
  685. }
  686. CGRect rectToScrollTo = rectForSelectedIndex;
  687. rectToScrollTo.origin.x -= selectedSegmentOffset;
  688. rectToScrollTo.size.width += selectedSegmentOffset * 2;
  689. [self.scrollView scrollRectToVisible:rectToScrollTo animated:animated];
  690. }
  691. #pragma mark - Index Change
  692. - (void)setSelectedSegmentIndex:(NSInteger)index {
  693. [self setSelectedSegmentIndex:index animated:NO notify:NO];
  694. }
  695. - (void)setSelectedSegmentIndex:(NSUInteger)index animated:(BOOL)animated {
  696. [self setSelectedSegmentIndex:index animated:animated notify:NO];
  697. }
  698. - (void)setSelectedSegmentIndex:(NSUInteger)index animated:(BOOL)animated notify:(BOOL)notify {
  699. _selectedSegmentIndex = index;
  700. [self setNeedsDisplay];
  701. if (index == HMSegmentedControlNoSegment) {
  702. [self.selectionIndicatorArrowLayer removeFromSuperlayer];
  703. [self.selectionIndicatorStripLayer removeFromSuperlayer];
  704. [self.selectionIndicatorBoxLayer removeFromSuperlayer];
  705. } else {
  706. [self scrollToSelectedSegmentIndex:animated];
  707. if (animated) {
  708. // If the selected segment layer is not added to the super layer, that means no
  709. // index is currently selected, so add the layer then move it to the new
  710. // segment index without animating.
  711. if(self.selectionStyle == HMSegmentedControlSelectionStyleArrow) {
  712. if ([self.selectionIndicatorArrowLayer superlayer] == nil) {
  713. [self.scrollView.layer addSublayer:self.selectionIndicatorArrowLayer];
  714. [self setSelectedSegmentIndex:index animated:NO notify:YES];
  715. return;
  716. }
  717. }else {
  718. if ([self.selectionIndicatorStripLayer superlayer] == nil) {
  719. [self.scrollView.layer addSublayer:self.selectionIndicatorStripLayer];
  720. if (self.selectionStyle == HMSegmentedControlSelectionStyleBox && [self.selectionIndicatorBoxLayer superlayer] == nil)
  721. [self.scrollView.layer insertSublayer:self.selectionIndicatorBoxLayer atIndex:0];
  722. [self setSelectedSegmentIndex:index animated:NO notify:YES];
  723. return;
  724. }
  725. }
  726. if (notify)
  727. [self notifyForSegmentChangeToIndex:index];
  728. // Restore CALayer animations
  729. self.selectionIndicatorArrowLayer.actions = nil;
  730. self.selectionIndicatorStripLayer.actions = nil;
  731. self.selectionIndicatorBoxLayer.actions = nil;
  732. // Animate to new position
  733. [CATransaction begin];
  734. [CATransaction setAnimationDuration:0.15f];
  735. [CATransaction setAnimationTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear]];
  736. [self setArrowFrame];
  737. self.selectionIndicatorBoxLayer.frame = [self frameForSelectionIndicator];
  738. self.selectionIndicatorStripLayer.frame = [self frameForSelectionIndicator];
  739. self.selectionIndicatorBoxLayer.frame = [self frameForFillerSelectionIndicator];
  740. [CATransaction commit];
  741. } else {
  742. // Disable CALayer animations
  743. NSMutableDictionary *newActions = [[NSMutableDictionary alloc] initWithObjectsAndKeys:[NSNull null], @"position", [NSNull null], @"bounds", nil];
  744. self.selectionIndicatorArrowLayer.actions = newActions;
  745. [self setArrowFrame];
  746. self.selectionIndicatorStripLayer.actions = newActions;
  747. self.selectionIndicatorStripLayer.frame = [self frameForSelectionIndicator];
  748. self.selectionIndicatorBoxLayer.actions = newActions;
  749. self.selectionIndicatorBoxLayer.frame = [self frameForFillerSelectionIndicator];
  750. if (notify)
  751. [self notifyForSegmentChangeToIndex:index];
  752. }
  753. }
  754. }
  755. - (void)notifyForSegmentChangeToIndex:(NSInteger)index {
  756. if (self.superview)
  757. [self sendActionsForControlEvents:UIControlEventValueChanged];
  758. if (self.indexChangeBlock)
  759. self.indexChangeBlock(index);
  760. }
  761. #pragma mark - Styling Support
  762. - (NSDictionary *)resultingTitleTextAttributes {
  763. NSDictionary *defaults = @{
  764. NSFontAttributeName : [UIFont systemFontOfSize:19.0f],
  765. NSForegroundColorAttributeName : [UIColor blackColor],
  766. };
  767. NSMutableDictionary *resultingAttrs = [NSMutableDictionary dictionaryWithDictionary:defaults];
  768. if (self.titleTextAttributes) {
  769. [resultingAttrs addEntriesFromDictionary:self.titleTextAttributes];
  770. }
  771. return [resultingAttrs copy];
  772. }
  773. - (NSDictionary *)resultingSelectedTitleTextAttributes {
  774. NSMutableDictionary *resultingAttrs = [NSMutableDictionary dictionaryWithDictionary:[self resultingTitleTextAttributes]];
  775. if (self.selectedTitleTextAttributes) {
  776. [resultingAttrs addEntriesFromDictionary:self.selectedTitleTextAttributes];
  777. }
  778. return [resultingAttrs copy];
  779. }
  780. @end