AKSegmentedControl.m 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  1. //
  2. // AKSegmentedControl.m
  3. //
  4. // Copyright (c) 2013 Ali Karagoz (http://alikaragoz.net)
  5. //
  6. // Permission is hereby granted, free of charge, to any person obtaining a copy
  7. // of this software and associated documentation files (the "Software"), to deal
  8. // in the Software without restriction, including without limitation the rights
  9. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10. // copies of the Software, and to permit persons to whom the Software is
  11. // furnished to do so, subject to the following conditions:
  12. //
  13. // The above copyright notice and this permission notice shall be included in
  14. // all copies or substantial portions of the Software.
  15. //
  16. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  19. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22. // THE SOFTWARE.
  23. #import "AKSegmentedControl.h"
  24. // Default separator width.
  25. static CGFloat const kAKButtonSeparatorWidth = 1.0;
  26. @interface AKSegmentedControl ()
  27. @property (nonatomic, strong) NSMutableArray *separatorsArray;
  28. @property (nonatomic, strong) UIImageView *backgroundImageView;
  29. // Init
  30. - (void)commonInitializer;
  31. @end
  32. @implementation AKSegmentedControl
  33. #pragma mark - Init and Dealloc
  34. - (id)initWithFrame:(CGRect)frame {
  35. self = [super initWithFrame:frame];
  36. if (!self) return nil;
  37. [self commonInitializer];
  38. return self;
  39. }
  40. - (id)initWithCoder:(NSCoder *)aDecoder {
  41. self = [super initWithCoder:aDecoder];
  42. if (!self) return nil;
  43. [self commonInitializer];
  44. return self;
  45. }
  46. - (void)commonInitializer {
  47. _separatorsArray = [NSMutableArray array];
  48. self.selectedIndexes = [NSIndexSet indexSet];
  49. self.contentEdgeInsets = UIEdgeInsetsZero;
  50. self.segmentedControlMode = AKSegmentedControlModeSticky;
  51. self.buttonsArray = [[NSArray alloc] init];
  52. [self addSubview:self.backgroundImageView];
  53. }
  54. #pragma mark - Layout
  55. - (void)layoutSubviews {
  56. [super layoutSubviews];
  57. CGRect contentRect = UIEdgeInsetsInsetRect(self.bounds, _contentEdgeInsets);
  58. NSUInteger buttonsCount = _buttonsArray.count;
  59. NSUInteger separtorsNumber = buttonsCount - 1;
  60. CGFloat separatorWidth = (_separatorImage != nil) ? _separatorImage.size.width : kAKButtonSeparatorWidth;
  61. CGFloat buttonWidth = floorf((CGRectGetWidth(contentRect) - (separtorsNumber * separatorWidth)) / buttonsCount);
  62. CGFloat buttonHeight = CGRectGetHeight(contentRect);
  63. CGSize buttonSize = CGSizeMake(buttonWidth, buttonHeight);
  64. __block CGFloat offsetX = CGRectGetMinX(contentRect);
  65. __block CGFloat offsetY = CGRectGetMinY(contentRect);
  66. __block CGFloat spaceLeft = CGRectGetWidth(contentRect) - (buttonsCount * buttonSize.width) - (separtorsNumber * separatorWidth);
  67. __block CGFloat dButtonWidth = 0;
  68. __block NSUInteger increment = 0;
  69. [_buttonsArray enumerateObjectsUsingBlock:^(UIButton *button, NSUInteger idx, BOOL *stop) {
  70. if (![button isKindOfClass:UIButton.class]) {
  71. return;
  72. }
  73. dButtonWidth = buttonSize.width;
  74. if (spaceLeft != 0) {
  75. dButtonWidth++;
  76. spaceLeft--;
  77. }
  78. if (increment != 0) {
  79. offsetX += separatorWidth;
  80. }
  81. button.frame = CGRectMake(offsetX, offsetY, dButtonWidth, buttonSize.height);
  82. if (increment < separtorsNumber) {
  83. UIImageView *separatorImageView = _separatorsArray[increment];
  84. [separatorImageView setFrame:CGRectMake(CGRectGetMaxX(button.frame),
  85. offsetY,
  86. separatorWidth,
  87. CGRectGetHeight(self.bounds) - _contentEdgeInsets.top - _contentEdgeInsets.bottom)];
  88. }
  89. increment++;
  90. offsetX = CGRectGetMaxX(button.frame);
  91. }];
  92. [_backgroundImageView setFrame:self.bounds];
  93. }
  94. #pragma mark - Button Actions
  95. - (void)segmentButtonPressed:(id)sender {
  96. UIButton *button = (UIButton *)sender;
  97. if (![button isKindOfClass:UIButton.class]) {
  98. return;
  99. }
  100. NSUInteger selectedIndex = button.tag;
  101. NSIndexSet *set = _selectedIndexes;
  102. if (_segmentedControlMode == AKSegmentedControlModeMultipleSelectionable) {
  103. NSMutableIndexSet *mutableSet = [set mutableCopy];
  104. if ([_selectedIndexes containsIndex:selectedIndex]) {
  105. [mutableSet removeIndex:selectedIndex];
  106. }
  107. else {
  108. [mutableSet addIndex:selectedIndex];
  109. }
  110. [self setSelectedIndexes:[mutableSet copy]];
  111. }
  112. else {
  113. [self setSelectedIndex:selectedIndex];
  114. }
  115. BOOL willSendAction = (![_selectedIndexes isEqualToIndexSet:set] || _segmentedControlMode == AKSegmentedControlModeButton);
  116. if (willSendAction) {
  117. [self sendActionsForControlEvents:UIControlEventValueChanged];
  118. }
  119. }
  120. #pragma mark - Setters
  121. - (void)setBackgroundImage:(UIImage *)backgroundImage {
  122. _backgroundImage = backgroundImage;
  123. [_backgroundImageView setImage:_backgroundImage];
  124. }
  125. - (void)setButtonsArray:(NSArray *)buttonsArray {
  126. [_buttonsArray makeObjectsPerformSelector:@selector(removeFromSuperview)];
  127. [_separatorsArray removeAllObjects];
  128. _buttonsArray = buttonsArray;
  129. [_buttonsArray enumerateObjectsUsingBlock:^(UIButton *button, NSUInteger idx, BOOL *stop) {
  130. [self addSubview:button];
  131. [button addTarget:self action:@selector(segmentButtonPressed:) forControlEvents:UIControlEventTouchDown];
  132. [button setTag:idx];
  133. }];
  134. [self rebuildSeparators];
  135. [self updateButtons];
  136. }
  137. - (void)setSeparatorImage:(UIImage *)separatorImage {
  138. _separatorImage = separatorImage;
  139. [self rebuildSeparators];
  140. }
  141. - (void)setSegmentedControlMode:(AKSegmentedControlMode)segmentedControlMode {
  142. _segmentedControlMode = segmentedControlMode;
  143. [self updateButtons];
  144. }
  145. - (void)setSelectedIndex:(NSUInteger)index {
  146. _selectedIndexes = [NSIndexSet indexSetWithIndex:index];
  147. [self updateButtons];
  148. }
  149. - (void)setSelectedIndexes:(NSIndexSet *)indexSet byExpandingSelection:(BOOL)expandSelection {
  150. if (_segmentedControlMode != AKSegmentedControlModeMultipleSelectionable) {
  151. return;
  152. }
  153. if (!expandSelection) {
  154. _selectedIndexes = [NSIndexSet indexSet];
  155. }
  156. NSMutableIndexSet *mutableIndexSet = [_selectedIndexes mutableCopy];
  157. [mutableIndexSet addIndexes:indexSet];
  158. [self setSelectedIndexes:mutableIndexSet];
  159. }
  160. - (void)setSelectedIndexes:(NSIndexSet *)selectedIndexes {
  161. _selectedIndexes = [selectedIndexes copy];
  162. [self updateButtons];
  163. }
  164. #pragma mark - Rearranging
  165. - (void)rebuildSeparators {
  166. [_separatorsArray makeObjectsPerformSelector:@selector(removeFromSuperview)];
  167. NSUInteger separatorsNumber = [_buttonsArray count] - 1;
  168. [_separatorsArray removeAllObjects];
  169. [_buttonsArray enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
  170. if (idx < separatorsNumber) {
  171. UIImageView *separatorImageView = [[UIImageView alloc] initWithImage:_separatorImage];
  172. [self addSubview:separatorImageView];
  173. [_separatorsArray addObject:separatorImageView];
  174. }
  175. }];
  176. }
  177. - (UIImageView *)backgroundImageView {
  178. if (_backgroundImageView == nil) {
  179. _backgroundImageView = [[UIImageView alloc] initWithFrame:self.bounds];
  180. [_backgroundImageView setAutoresizingMask:UIViewAutoresizingFlexibleWidth];
  181. }
  182. return _backgroundImageView;
  183. }
  184. - (void)updateButtons {
  185. if ([_buttonsArray count] == 0) {
  186. return;
  187. }
  188. [_buttonsArray makeObjectsPerformSelector:@selector(setSelected:) withObject:nil];
  189. [_selectedIndexes enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL *stop) {
  190. if (_segmentedControlMode != AKSegmentedControlModeButton) {
  191. if (idx >= [_buttonsArray count]) return;
  192. UIButton *button = _buttonsArray[idx];
  193. button.selected = YES;
  194. }
  195. }];
  196. }
  197. -(void)initButtonWithTitleandImage:(NSArray *)buttonTitleandImage{
  198. UIImage *backgroundImage = [[UIImage imageNamed:@"segmented-bg"] resizableImageWithCapInsets:UIEdgeInsetsMake(10.0, 10.0, 10.0, 10.0)];
  199. [self setBackgroundImage:backgroundImage];
  200. [self setContentEdgeInsets:UIEdgeInsetsMake(2.0, 2.0, 3.0, 2.0)];
  201. [self setAutoresizingMask:UIViewAutoresizingFlexibleRightMargin|UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleBottomMargin];
  202. [self setSeparatorImage:[UIImage imageNamed:@"segmented-separator"]];
  203. NSMutableArray *buttonArr = [[NSMutableArray alloc]init];
  204. UIImage *buttonBackgroundImagePressedLeft = [[UIImage imageNamed:@"segmented-bg-pressed-left"]
  205. resizableImageWithCapInsets:UIEdgeInsetsMake(0.0, 4.0, 0.0, 1.0)];
  206. // UIImage *buttonBackgroundImagePressedCenter = [[UIImage imageNamed:@"segmented-bg-pressed-center"]
  207. // resizableImageWithCapInsets:UIEdgeInsetsMake(0.0, 4.0, 0.0, 1.0)];
  208. // UIImage *buttonBackgroundImagePressedRight = [[UIImage imageNamed:@"segmented-bg-pressed-right"]
  209. // resizableImageWithCapInsets:UIEdgeInsetsMake(0.0, 1.0, 0.0, 4.0)];
  210. for (NSDictionary *dict in buttonTitleandImage) {
  211. UIButton *button = [[UIButton alloc] init];
  212. UIImage *button1ImageNormal = [UIImage imageNamed:dict[@"image"]];
  213. [button setImageEdgeInsets:UIEdgeInsetsMake(0.0, 0.0, 0.0, 5.0)];
  214. [button setBackgroundImage:buttonBackgroundImagePressedLeft forState:UIControlStateHighlighted];
  215. [button setBackgroundImage:buttonBackgroundImagePressedLeft forState:UIControlStateSelected];
  216. [button setBackgroundImage:buttonBackgroundImagePressedLeft forState:(UIControlStateHighlighted|UIControlStateSelected)];
  217. button.titleLabel.font = [UIFont fontWithName:dict[@"font"] size:14];
  218. [button setImage:button1ImageNormal forState:UIControlStateNormal];
  219. [button setImage:button1ImageNormal forState:UIControlStateSelected];
  220. [button setImage:button1ImageNormal forState:UIControlStateHighlighted];
  221. [button setImage:button1ImageNormal forState:(UIControlStateHighlighted|UIControlStateSelected)];
  222. [button setTitle:dict[@"title"] forState:normal];
  223. [button setTitleColor:[UIColor colorWithRed:((float)38/255) green:(float)82/255 blue:((float)67/255) alpha:1] forState:normal];
  224. [buttonArr addObject:button];
  225. }
  226. self.buttonsArray = buttonArr;
  227. }
  228. @end