Advertisement
dinophanhk

[Obj-C] AKSegmentedControl

Jun 18th, 2014
213
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /* .h file */
  2.  
  3. #import <UIKit/UIKit.h>
  4.  
  5. /** Behavior of when touching the each buttons. */
  6. typedef NS_ENUM(NSUInteger, AKSegmentedControlMode) {
  7.     /** Upon touching the buttons, they will remain selected. */
  8.     AKSegmentedControlModeSticky,
  9.    
  10.     /** Button like mode. Upon touching the buttons, they will transition from selected to normal mode. */
  11.     AKSegmentedControlModeButton,
  12.    
  13.     /** Multi selectionable. It is possible to select multiple buttons at once. */
  14.     AKSegmentedControlModeMultipleSelectionable,
  15. };
  16.  
  17. @interface AKSegmentedControl : UIControl
  18.  
  19. /** Array containing pointers to the `UIButton` of the segmented control. */
  20. @property (nonatomic, strong, readwrite) NSArray *buttonsArray;
  21.  
  22. /** Image used to cover the background of the whole segmented control. */
  23. @property (nonatomic, strong, readwrite) UIImage *backgroundImage;
  24.  
  25. /** Image used to represent the vertical separator between each button of the segmented control. */
  26. @property (nonatomic, strong, readwrite) UIImage *separatorImage;
  27.  
  28. /** list of indexed currently selected. */
  29. @property (nonatomic, strong, readwrite) NSIndexSet *selectedIndexes;
  30.  
  31. /** Insets of the whole segmented control view. */
  32. @property (nonatomic, assign, readwrite) UIEdgeInsets contentEdgeInsets;
  33.  
  34. /** Button behavior used upon the user touch.  */
  35. @property (nonatomic, assign, readwrite) AKSegmentedControlMode segmentedControlMode;
  36.  
  37.  
  38. /**
  39.  *  Manually selects an index of the segmented control.
  40.  *
  41.  *  @param index Index of the button you want to be selected.
  42.  */
  43. - (void)setSelectedIndex:(NSUInteger)index;
  44.  
  45. /**
  46.  *  Manually sets the selected indexes when using the `AKSegmentedControlModeMultipleSelectionable` mode.
  47.  *
  48.  *  @param indexSet        Set of the indexes you want to be selected.
  49.  *  @param expandSelection When set this keeps previously selected indexes.
  50.  */
  51. - (void)setSelectedIndexes:(NSIndexSet *)indexSet byExpandingSelection:(BOOL)expandSelection;
  52.  
  53. @end
  54.  
  55.  
  56. /* .m file */
  57.  
  58. #import "AKSegmentedControl.h"
  59.  
  60. // Default separator width.
  61. static CGFloat const kAKButtonSeparatorWidth = 1.0;
  62.  
  63. @interface AKSegmentedControl ()
  64.  
  65. @property (nonatomic, strong) NSMutableArray *separatorsArray;
  66. @property (nonatomic, strong) UIImageView *backgroundImageView;
  67.  
  68. // Init
  69. - (void)commonInitializer;
  70.  
  71. @end
  72.  
  73. @implementation AKSegmentedControl
  74.  
  75. #pragma mark - Init and Dealloc
  76.  
  77. - (id)initWithFrame:(CGRect)frame {
  78.     self = [super initWithFrame:frame];
  79.     if (!self) return nil;
  80.    
  81.     [self commonInitializer];
  82.    
  83.     return self;
  84. }
  85.  
  86. - (id)initWithCoder:(NSCoder *)aDecoder {
  87.     self = [super initWithCoder:aDecoder];
  88.     if (!self) return nil;
  89.    
  90.     [self commonInitializer];
  91.    
  92.     return self;
  93. }
  94.  
  95. - (void)commonInitializer {
  96.     _separatorsArray = [NSMutableArray array];
  97.     self.selectedIndexes = [NSIndexSet indexSet];
  98.     self.contentEdgeInsets = UIEdgeInsetsZero;
  99.     self.segmentedControlMode = AKSegmentedControlModeSticky;
  100.     self.buttonsArray = [[NSArray alloc] init];
  101.    
  102.     [self addSubview:self.backgroundImageView];
  103. }
  104.  
  105. #pragma mark - Layout
  106.  
  107. - (void)layoutSubviews {
  108.     CGRect contentRect = UIEdgeInsetsInsetRect(self.bounds, _contentEdgeInsets);
  109.    
  110.     NSUInteger buttonsCount    = _buttonsArray.count;
  111.     NSUInteger separtorsNumber = buttonsCount - 1;
  112.     CGFloat separatorWidth     = (_separatorImage != nil) ? _separatorImage.size.width : kAKButtonSeparatorWidth;
  113.     CGFloat buttonWidth        = floorf((CGRectGetWidth(contentRect) - (separtorsNumber * separatorWidth)) / buttonsCount);
  114.     CGFloat buttonHeight       = CGRectGetHeight(contentRect);
  115.     CGSize buttonSize          = CGSizeMake(buttonWidth, buttonHeight);
  116.    
  117.     __block CGFloat offsetX      = CGRectGetMinX(contentRect);
  118.     __block CGFloat offsetY      = CGRectGetMinY(contentRect);
  119.     __block CGFloat spaceLeft    = CGRectGetWidth(contentRect) - (buttonsCount * buttonSize.width) - (separtorsNumber * separatorWidth);
  120.     __block CGFloat dButtonWidth = 0;
  121.     __block NSUInteger increment = 0;
  122.    
  123.     [_buttonsArray enumerateObjectsUsingBlock:^(UIButton *button, NSUInteger idx, BOOL *stop) {
  124.         if (![button isKindOfClass:UIButton.class]) {
  125.             return;
  126.         }
  127.        
  128.         dButtonWidth = buttonSize.width;
  129.        
  130.         if (spaceLeft != 0) {
  131.             dButtonWidth++;
  132.             spaceLeft--;
  133.         }
  134.        
  135.         if (increment != 0) {
  136.             offsetX += separatorWidth;
  137.         }
  138.        
  139.         button.frame = CGRectMake(offsetX, offsetY, dButtonWidth, buttonSize.height);
  140.        
  141.         if (increment < separtorsNumber) {
  142.             UIImageView *separatorImageView = _separatorsArray[increment];
  143.             [separatorImageView setFrame:CGRectMake(CGRectGetMaxX(button.frame),
  144.                                                     offsetY,
  145.                                                     separatorWidth,
  146.                                                     CGRectGetHeight(self.bounds) - _contentEdgeInsets.top - _contentEdgeInsets.bottom)];
  147.         }
  148.        
  149.         increment++;
  150.         offsetX = CGRectGetMaxX(button.frame);
  151.     }];
  152.    
  153.     [_backgroundImageView setFrame:self.bounds];
  154. }
  155.  
  156. #pragma mark - Button Actions
  157.  
  158. - (void)segmentButtonPressed:(id)sender {
  159.     UIButton *button = (UIButton *)sender;
  160.    
  161.     if (![button isKindOfClass:UIButton.class]) {
  162.         return;
  163.     }
  164.    
  165.     NSUInteger selectedIndex = button.tag;
  166.     NSIndexSet *set = _selectedIndexes;
  167.    
  168.     if (_segmentedControlMode == AKSegmentedControlModeMultipleSelectionable) {
  169.  
  170.         NSMutableIndexSet *mutableSet = [set mutableCopy];
  171.         if ([_selectedIndexes containsIndex:selectedIndex]) {
  172.             [mutableSet removeIndex:selectedIndex];
  173.         }
  174.        
  175.         else {
  176.             [mutableSet addIndex:selectedIndex];
  177.         }
  178.        
  179.         [self setSelectedIndexes:[mutableSet copy]];
  180.     }
  181.    
  182.     else {
  183.         [self setSelectedIndex:selectedIndex];
  184.     }
  185.    
  186.     BOOL willSendAction = (![_selectedIndexes isEqualToIndexSet:set] || _segmentedControlMode == AKSegmentedControlModeButton);
  187.    
  188.     if (willSendAction) {
  189.         [self sendActionsForControlEvents:UIControlEventValueChanged];
  190.     }
  191.    
  192. }
  193.  
  194. #pragma mark - Setters
  195.  
  196. - (void)setBackgroundImage:(UIImage *)backgroundImage {
  197.     _backgroundImage = backgroundImage;
  198.     [_backgroundImageView setImage:_backgroundImage];
  199. }
  200.  
  201. - (void)setButtonsArray:(NSArray *)buttonsArray {
  202.     [_buttonsArray makeObjectsPerformSelector:@selector(removeFromSuperview)];
  203.     [_separatorsArray removeAllObjects];
  204.    
  205.     _buttonsArray = buttonsArray;
  206.    
  207.     [_buttonsArray enumerateObjectsUsingBlock:^(UIButton *button, NSUInteger idx, BOOL *stop) {
  208.         [self addSubview:button];
  209.         [button addTarget:self action:@selector(segmentButtonPressed:) forControlEvents:UIControlEventTouchDown];
  210.         [button setTag:idx];
  211.     }];
  212.    
  213.     [self rebuildSeparators];
  214.     [self updateButtons];
  215. }
  216.  
  217. - (void)setSeparatorImage:(UIImage *)separatorImage {
  218.     _separatorImage = separatorImage;
  219.     [self rebuildSeparators];
  220. }
  221.  
  222. - (void)setSegmentedControlMode:(AKSegmentedControlMode)segmentedControlMode {
  223.     _segmentedControlMode = segmentedControlMode;
  224.     [self updateButtons];
  225. }
  226.  
  227. - (void)setSelectedIndex:(NSUInteger)index {
  228.     _selectedIndexes = [NSIndexSet indexSetWithIndex:index];
  229.     [self updateButtons];
  230. }
  231.  
  232. - (void)setSelectedIndexes:(NSIndexSet *)indexSet byExpandingSelection:(BOOL)expandSelection {
  233.    
  234.     if (_segmentedControlMode != AKSegmentedControlModeMultipleSelectionable) {
  235.         return;
  236.     }
  237.    
  238.     if (!expandSelection) {
  239.         _selectedIndexes = [NSIndexSet indexSet];
  240.     }
  241.    
  242.     NSMutableIndexSet *mutableIndexSet = [_selectedIndexes mutableCopy];
  243.     [mutableIndexSet addIndexes:indexSet];
  244.     [self setSelectedIndexes:mutableIndexSet];
  245. }
  246.  
  247. - (void)setSelectedIndexes:(NSIndexSet *)selectedIndexes {
  248.     _selectedIndexes = [selectedIndexes copy];
  249.     [self updateButtons];
  250. }
  251.  
  252. #pragma mark - Rearranging
  253.  
  254. - (void)rebuildSeparators {
  255.     [_separatorsArray makeObjectsPerformSelector:@selector(removeFromSuperview)];
  256.    
  257.     NSUInteger separatorsNumber = [_buttonsArray count] - 1;
  258.    
  259.     [_separatorsArray removeAllObjects];
  260.     [_buttonsArray enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
  261.         if (idx < separatorsNumber) {
  262.             UIImageView *separatorImageView = [[UIImageView alloc] initWithImage:_separatorImage];
  263.             [self addSubview:separatorImageView];
  264.             [_separatorsArray addObject:separatorImageView];
  265.         }
  266.     }];
  267. }
  268.  
  269. - (UIImageView *)backgroundImageView {
  270.     if (_backgroundImageView == nil) {
  271.         _backgroundImageView = [[UIImageView alloc] initWithFrame:self.bounds];
  272.         [_backgroundImageView setAutoresizingMask:UIViewAutoresizingFlexibleWidth];
  273.     }
  274.    
  275.     return _backgroundImageView;
  276. }
  277.  
  278. - (void)updateButtons {
  279.    
  280.     if ([_buttonsArray count] == 0) {
  281.         return;
  282.     }
  283.    
  284.     [_buttonsArray makeObjectsPerformSelector:@selector(setSelected:) withObject:nil];
  285.    
  286.     [_selectedIndexes enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL *stop) {
  287.        
  288.         if (_segmentedControlMode != AKSegmentedControlModeButton) {
  289.             if (idx >= [_buttonsArray count]) return;
  290.            
  291.             UIButton *button = _buttonsArray[idx];
  292.             button.selected = YES;
  293.         }
  294.     }];
  295. }
  296.  
  297. @end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement