Browse Source

top tabs support - ios (#2454)

* top tabs support - ios
yogevbd 6 years ago
parent
commit
06aa587a4a
No account linked to committer's email address

+ 262
- 0
lib/ios/HMSegmentedControl.h View File

@@ -0,0 +1,262 @@
1
+//
2
+//  HMSegmentedControl.h
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
+
9
+#import <UIKit/UIKit.h>
10
+
11
+@class HMSegmentedControl;
12
+
13
+typedef void (^IndexChangeBlock)(NSInteger index);
14
+typedef NSAttributedString *(^HMTitleFormatterBlock)(HMSegmentedControl *segmentedControl, NSString *title, NSUInteger index, BOOL selected);
15
+
16
+typedef NS_ENUM(NSInteger, HMSegmentedControlSelectionStyle) {
17
+    HMSegmentedControlSelectionStyleTextWidthStripe, // Indicator width will only be as big as the text width
18
+    HMSegmentedControlSelectionStyleFullWidthStripe, // Indicator width will fill the whole segment
19
+    HMSegmentedControlSelectionStyleBox, // A rectangle that covers the whole segment
20
+    HMSegmentedControlSelectionStyleArrow // An arrow in the middle of the segment pointing up or down depending on `HMSegmentedControlSelectionIndicatorLocation`
21
+};
22
+
23
+typedef NS_ENUM(NSInteger, HMSegmentedControlSelectionIndicatorLocation) {
24
+    HMSegmentedControlSelectionIndicatorLocationUp,
25
+    HMSegmentedControlSelectionIndicatorLocationDown,
26
+	HMSegmentedControlSelectionIndicatorLocationNone // No selection indicator
27
+};
28
+
29
+typedef NS_ENUM(NSInteger, HMSegmentedControlSegmentWidthStyle) {
30
+    HMSegmentedControlSegmentWidthStyleFixed, // Segment width is fixed
31
+    HMSegmentedControlSegmentWidthStyleDynamic, // Segment width will only be as big as the text width (including inset)
32
+};
33
+
34
+typedef NS_OPTIONS(NSInteger, HMSegmentedControlBorderType) {
35
+    HMSegmentedControlBorderTypeNone = 0,
36
+    HMSegmentedControlBorderTypeTop = (1 << 0),
37
+    HMSegmentedControlBorderTypeLeft = (1 << 1),
38
+    HMSegmentedControlBorderTypeBottom = (1 << 2),
39
+    HMSegmentedControlBorderTypeRight = (1 << 3)
40
+};
41
+
42
+enum {
43
+    HMSegmentedControlNoSegment = -1   // Segment index for no selected segment
44
+};
45
+
46
+typedef NS_ENUM(NSInteger, HMSegmentedControlType) {
47
+    HMSegmentedControlTypeText,
48
+    HMSegmentedControlTypeImages,
49
+	HMSegmentedControlTypeTextImages
50
+};
51
+
52
+typedef NS_ENUM(NSInteger, HMSegmentedControlImagePosition) {
53
+    HMSegmentedControlImagePositionBehindText,
54
+    HMSegmentedControlImagePositionLeftOfText,
55
+    HMSegmentedControlImagePositionRightOfText,
56
+    HMSegmentedControlImagePositionAboveText,
57
+    HMSegmentedControlImagePositionBelowText
58
+};
59
+
60
+@interface HMSegmentedControl : UIControl
61
+
62
+@property (nonatomic, strong) NSArray<NSString *> *sectionTitles;
63
+@property (nonatomic, strong) NSArray<UIImage *> *sectionImages;
64
+@property (nonatomic, strong) NSArray<UIImage *> *sectionSelectedImages;
65
+
66
+/**
67
+ Provide a block to be executed when selected index is changed.
68
+ 
69
+ Alternativly, you could use `addTarget:action:forControlEvents:`
70
+ */
71
+@property (nonatomic, copy) IndexChangeBlock indexChangeBlock;
72
+
73
+/**
74
+ Used to apply custom text styling to titles when set.
75
+ 
76
+ When this block is set, no additional styling is applied to the `NSAttributedString` object returned from this block.
77
+ */
78
+@property (nonatomic, copy) HMTitleFormatterBlock titleFormatter;
79
+
80
+/**
81
+ Text attributes to apply to item title text.
82
+ */
83
+@property (nonatomic, strong) NSDictionary *titleTextAttributes UI_APPEARANCE_SELECTOR;
84
+
85
+/*
86
+ Text attributes to apply to selected item title text.
87
+ 
88
+ Attributes not set in this dictionary are inherited from `titleTextAttributes`.
89
+ */
90
+@property (nonatomic, strong) NSDictionary *selectedTitleTextAttributes UI_APPEARANCE_SELECTOR;
91
+
92
+/**
93
+ Segmented control background color.
94
+ 
95
+ Default is `[UIColor whiteColor]`
96
+ */
97
+@property (nonatomic, strong) UIColor *backgroundColor UI_APPEARANCE_SELECTOR;
98
+
99
+/**
100
+ Color for the selection indicator stripe
101
+ 
102
+ Default is `R:52, G:181, B:229`
103
+ */
104
+@property (nonatomic, strong) UIColor *selectionIndicatorColor UI_APPEARANCE_SELECTOR;
105
+
106
+/**
107
+ Color for the selection indicator box
108
+ 
109
+ Default is selectionIndicatorColor
110
+ */
111
+@property (nonatomic, strong) UIColor *selectionIndicatorBoxColor UI_APPEARANCE_SELECTOR;
112
+
113
+/**
114
+ Color for the vertical divider between segments.
115
+ 
116
+ Default is `[UIColor blackColor]`
117
+ */
118
+@property (nonatomic, strong) UIColor *verticalDividerColor UI_APPEARANCE_SELECTOR;
119
+
120
+/**
121
+ Opacity for the seletion indicator box.
122
+ 
123
+ Default is `0.2f`
124
+ */
125
+@property (nonatomic) CGFloat selectionIndicatorBoxOpacity;
126
+
127
+/**
128
+ Width the vertical divider between segments that is added when `verticalDividerEnabled` is set to YES.
129
+ 
130
+ Default is `1.0f`
131
+ */
132
+@property (nonatomic, assign) CGFloat verticalDividerWidth;
133
+
134
+/**
135
+ Specifies the style of the control
136
+ 
137
+ Default is `HMSegmentedControlTypeText`
138
+ */
139
+@property (nonatomic, assign) HMSegmentedControlType type;
140
+
141
+/**
142
+ Specifies the style of the selection indicator.
143
+ 
144
+ Default is `HMSegmentedControlSelectionStyleTextWidthStripe`
145
+ */
146
+@property (nonatomic, assign) HMSegmentedControlSelectionStyle selectionStyle;
147
+
148
+/**
149
+ Specifies the style of the segment's width.
150
+ 
151
+ Default is `HMSegmentedControlSegmentWidthStyleFixed`
152
+ */
153
+@property (nonatomic, assign) HMSegmentedControlSegmentWidthStyle segmentWidthStyle;
154
+
155
+/**
156
+ Specifies the location of the selection indicator.
157
+ 
158
+ Default is `HMSegmentedControlSelectionIndicatorLocationUp`
159
+ */
160
+@property (nonatomic, assign) HMSegmentedControlSelectionIndicatorLocation selectionIndicatorLocation;
161
+
162
+/*
163
+ Specifies the border type.
164
+ 
165
+ Default is `HMSegmentedControlBorderTypeNone`
166
+ */
167
+@property (nonatomic, assign) HMSegmentedControlBorderType borderType;
168
+
169
+/**
170
+ Specifies the image position relative to the text. Only applicable for HMSegmentedControlTypeTextImages
171
+ 
172
+ Default is `HMSegmentedControlImagePositionBehindText`
173
+ */
174
+@property (nonatomic) HMSegmentedControlImagePosition imagePosition;
175
+
176
+/**
177
+ Specifies the distance between the text and the image. Only applicable for HMSegmentedControlTypeTextImages
178
+ 
179
+ Default is `0,0`
180
+ */
181
+@property (nonatomic) CGFloat textImageSpacing;
182
+
183
+/**
184
+ Specifies the border color.
185
+ 
186
+ Default is `[UIColor blackColor]`
187
+ */
188
+@property (nonatomic, strong) UIColor *borderColor;
189
+
190
+/**
191
+ Specifies the border width.
192
+ 
193
+ Default is `1.0f`
194
+ */
195
+@property (nonatomic, assign) CGFloat borderWidth;
196
+
197
+/**
198
+ Default is YES. Set to NO to deny scrolling by dragging the scrollView by the user.
199
+ */
200
+@property(nonatomic, getter = isUserDraggable) BOOL userDraggable;
201
+
202
+/**
203
+ Default is YES. Set to NO to deny any touch events by the user.
204
+ */
205
+@property(nonatomic, getter = isTouchEnabled) BOOL touchEnabled;
206
+
207
+/**
208
+ Default is NO. Set to YES to show a vertical divider between the segments.
209
+ */
210
+@property(nonatomic, getter = isVerticalDividerEnabled) BOOL verticalDividerEnabled;
211
+
212
+@property (nonatomic, getter=shouldStretchSegmentsToScreenSize) BOOL stretchSegmentsToScreenSize;
213
+
214
+/**
215
+ Index of the currently selected segment.
216
+ */
217
+@property (nonatomic, assign) NSInteger selectedSegmentIndex;
218
+
219
+/**
220
+ Height of the selection indicator. Only effective when `HMSegmentedControlSelectionStyle` is either `HMSegmentedControlSelectionStyleTextWidthStripe` or `HMSegmentedControlSelectionStyleFullWidthStripe`.
221
+ 
222
+ Default is 5.0
223
+ */
224
+@property (nonatomic, readwrite) CGFloat selectionIndicatorHeight;
225
+
226
+/**
227
+ Edge insets for the selection indicator.
228
+ NOTE: This does not affect the bounding box of HMSegmentedControlSelectionStyleBox
229
+ 
230
+ When HMSegmentedControlSelectionIndicatorLocationUp is selected, bottom edge insets are not used
231
+ 
232
+ When HMSegmentedControlSelectionIndicatorLocationDown is selected, top edge insets are not used
233
+ 
234
+ Defaults are top: 0.0f
235
+             left: 0.0f
236
+           bottom: 0.0f
237
+            right: 0.0f
238
+ */
239
+@property (nonatomic, readwrite) UIEdgeInsets selectionIndicatorEdgeInsets;
240
+
241
+/**
242
+ Inset left and right edges of segments.
243
+ 
244
+ Default is UIEdgeInsetsMake(0, 5, 0, 5)
245
+ */
246
+@property (nonatomic, readwrite) UIEdgeInsets segmentEdgeInset;
247
+
248
+@property (nonatomic, readwrite) UIEdgeInsets enlargeEdgeInset;
249
+
250
+/**
251
+ Default is YES. Set to NO to disable animation during user selection.
252
+ */
253
+@property (nonatomic) BOOL shouldAnimateUserSelection;
254
+
255
+- (id)initWithSectionTitles:(NSArray<NSString *> *)sectiontitles;
256
+- (id)initWithSectionImages:(NSArray<UIImage *> *)sectionImages sectionSelectedImages:(NSArray<UIImage *> *)sectionSelectedImages;
257
+- (instancetype)initWithSectionImages:(NSArray<UIImage *> *)sectionImages sectionSelectedImages:(NSArray<UIImage *> *)sectionSelectedImages titlesForSections:(NSArray<NSString *> *)sectiontitles;
258
+- (void)setSelectedSegmentIndex:(NSUInteger)index animated:(BOOL)animated;
259
+- (void)setIndexChangeBlock:(IndexChangeBlock)indexChangeBlock;
260
+- (void)setTitleFormatter:(HMTitleFormatterBlock)titleFormatter;
261
+
262
+@end

+ 958
- 0
lib/ios/HMSegmentedControl.m View File

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

+ 1
- 1
lib/ios/RNNCommandsHandler.h View File

@@ -6,7 +6,7 @@
6 6
 
7 7
 @interface RNNCommandsHandler : NSObject
8 8
 
9
--(instancetype) initWithStore:(RNNStore*)store controllerFactory:(RNNControllerFactory*)controllerFactory andBridge:(RCTBridge*)bridge;
9
+-(instancetype) initWithStore:(RNNStore*)store controllerFactory:(RNNControllerFactory*)controllerFactory;
10 10
 
11 11
 -(void) setRoot:(NSDictionary*)layout completion:(RNNTransitionCompletionBlock)completion;
12 12
 

+ 1
- 6
lib/ios/RNNCommandsHandler.m View File

@@ -8,14 +8,12 @@
8 8
 @implementation RNNCommandsHandler {
9 9
 	RNNControllerFactory *_controllerFactory;
10 10
 	RNNStore *_store;
11
-	RCTBridge* _bridge;
12 11
 	RNNNavigationStackManager* _navigationStackManager;
13 12
 	RNNModalManager* _modalManager;
14 13
 }
15 14
 
16
--(instancetype) initWithStore:(RNNStore*)store controllerFactory:(RNNControllerFactory*)controllerFactory andBridge:(RCTBridge*)bridge {
15
+-(instancetype) initWithStore:(RNNStore*)store controllerFactory:(RNNControllerFactory*)controllerFactory {
17 16
 	self = [super init];
18
-	_bridge = bridge;
19 17
 	_store = store;
20 18
 	_controllerFactory = controllerFactory;
21 19
 	_navigationStackManager = [[RNNNavigationStackManager alloc] initWithStore:_store];
@@ -58,9 +56,6 @@
58 56
 	[self assertReady];
59 57
 	
60 58
 	UIViewController<RNNRootViewProtocol> *newVc = [_controllerFactory createLayoutAndSaveToStore:layout];
61
-	UIViewController *fromVc = [_store findContainerForId:containerId];
62
-	[_bridge.uiManager setAvailableSize:fromVc.view.bounds.size forRootView:newVc.view];
63
-
64 59
 	[_navigationStackManager push:newVc onTop:containerId completion:completion];
65 60
 }
66 61
 

+ 2
- 1
lib/ios/RNNControllerFactory.h View File

@@ -10,7 +10,8 @@
10 10
 
11 11
 -(instancetype)initWithRootViewCreator:(id <RNNRootViewCreator>)creator
12 12
 								 store:(RNNStore*)store
13
-						  eventEmitter:(RNNEventEmitter*)eventEmitter;
13
+						  eventEmitter:(RNNEventEmitter*)eventEmitter
14
+							 andBridge:(RCTBridge*)bridge;
14 15
 
15 16
 -(UIViewController<RNNRootViewProtocol> *)createLayoutAndSaveToStore:(NSDictionary*)layout;
16 17
 

+ 31
- 3
lib/ios/RNNControllerFactory.m View File

@@ -7,11 +7,13 @@
7 7
 #import "RNNNavigationOptions.h"
8 8
 #import "RNNNavigationController.h"
9 9
 #import "RNNTabBarController.h"
10
+#import "RNNTopTabsViewController.h"
10 11
 
11 12
 @implementation RNNControllerFactory {
12 13
 	id<RNNRootViewCreator> _creator;
13 14
 	RNNStore *_store;
14 15
 	RNNEventEmitter *_eventEmitter;
16
+	RCTBridge *_bridge;
15 17
 }
16 18
 
17 19
 # pragma mark public
@@ -19,12 +21,14 @@
19 21
 
20 22
 - (instancetype)initWithRootViewCreator:(id <RNNRootViewCreator>)creator
21 23
 								  store:(RNNStore *)store
22
-						   eventEmitter:(RNNEventEmitter*)eventEmitter {
24
+						   eventEmitter:(RNNEventEmitter*)eventEmitter
25
+							  andBridge:(RCTBridge *)bridge {
23 26
 	
24 27
 	self = [super init];
25 28
 	_creator = creator;
26 29
 	_store = store;
27 30
 	_eventEmitter = eventEmitter;
31
+	_bridge = bridge;
28 32
 	
29 33
 	return self;
30 34
 }
@@ -40,7 +44,7 @@
40 44
 	
41 45
 	UIViewController<RNNRootViewProtocol> *result;
42 46
 	
43
-	if ( node.isContainer) {
47
+	if ( node.isContainer || node.isTopTab) {
44 48
 		result = [self createContainer:node];
45 49
 	}
46 50
 	
@@ -52,6 +56,10 @@
52 56
 		result = [self createTabs:node];
53 57
 	}
54 58
 	
59
+	else if (node.isTopTabs) {
60
+		result = [self createTopTabs:node];
61
+	}
62
+	
55 63
 	else if (node.isSideMenuRoot) {
56 64
 		result = [self createSideMenu:node];
57 65
 	}
@@ -82,7 +90,11 @@
82 90
 	RNNAnimator* animator = [[RNNAnimator alloc] initWithAnimationsDictionary:customTransition];
83 91
 	RNNNavigationOptions* options = [[RNNNavigationOptions alloc] initWithDict:node.data[@"navigationOptions"]];
84 92
 	NSString* containerId = node.nodeId;
85
-	return [[RNNRootViewController alloc] initWithName:name withOptions:options withContainerId:containerId rootViewCreator:_creator eventEmitter:_eventEmitter animator:animator];
93
+	RNNRootViewController* container = [[RNNRootViewController alloc] initWithName:name withOptions:options withContainerId:containerId rootViewCreator:_creator eventEmitter:_eventEmitter animator:animator];
94
+	CGSize availableSize = UIApplication.sharedApplication.delegate.window.bounds.size;
95
+	[_bridge.uiManager setAvailableSize:availableSize forRootView:container.view];
96
+	
97
+	return container;
86 98
 }
87 99
 
88 100
 - (UIViewController<RNNRootViewProtocol> *)createContainerStack:(RNNLayoutNode*)node {
@@ -113,6 +125,22 @@
113 125
 	return vc;
114 126
 }
115 127
 
128
+- (UIViewController<RNNRootViewProtocol> *)createTopTabs:(RNNLayoutNode*)node {
129
+	RNNTopTabsViewController* vc = [[RNNTopTabsViewController alloc] init];
130
+	
131
+	NSMutableArray* controllers = [NSMutableArray new];
132
+	for (NSDictionary *child in node.children) {
133
+		RNNRootViewController* childVc = (RNNRootViewController*)[self fromTree:child];
134
+		childVc.topTabsViewController = vc;
135
+		[controllers addObject:childVc];
136
+		[_bridge.uiManager setAvailableSize:vc.contentView.bounds.size forRootView:childVc.view];
137
+	}
138
+	
139
+	[vc setViewControllers:controllers];
140
+	
141
+	return vc;
142
+}
143
+
116 144
 - (UIViewController<RNNRootViewProtocol> *)createSideMenu:(RNNLayoutNode*)node {
117 145
 	NSMutableArray* childrenVCs = [NSMutableArray new];
118 146
 	

+ 2
- 0
lib/ios/RNNLayoutNode.h View File

@@ -14,6 +14,8 @@
14 14
 -(BOOL)isContainer;
15 15
 -(BOOL)isContainerStack;
16 16
 -(BOOL)isTabs;
17
+-(BOOL)isTopTabs;
18
+-(BOOL)isTopTab;
17 19
 -(BOOL)isSideMenuRoot;
18 20
 -(BOOL)isSideMenuLeft;
19 21
 -(BOOL)isSideMenuRight;

+ 8
- 0
lib/ios/RNNLayoutNode.m View File

@@ -25,6 +25,14 @@
25 25
 {
26 26
 	return [self.type isEqualToString:@"BottomTabs"];
27 27
 }
28
+-(BOOL)isTopTabs
29
+{
30
+	return [self.type isEqualToString:@"TopTabs"];
31
+}
32
+-(BOOL)isTopTab
33
+{
34
+	return [self.type isEqualToString:@"TopTab"];
35
+}
28 36
 -(BOOL)isSideMenuRoot
29 37
 {
30 38
 	return [self.type isEqualToString:@"SideMenuRoot"];

+ 3
- 0
lib/ios/RNNNavigationOptions.h View File

@@ -4,6 +4,7 @@
4 4
 #import "RNNTabBarOptions.h"
5 5
 #import "RNNSideMenuOptions.h"
6 6
 #import "RNNTabItemOptions.h"
7
+#import "RNNTopTabOptions.h"
7 8
 
8 9
 extern const NSInteger BLUR_STATUS_TAG;
9 10
 extern const NSInteger BLUR_TOPBAR_TAG;
@@ -23,6 +24,7 @@ extern const NSInteger TOP_BAR_TRANSPARENT_TAG;
23 24
 @property (nonatomic, strong) NSNumber* popGesture;
24 25
 @property (nonatomic, strong) RNNTopBarOptions* topBar;
25 26
 @property (nonatomic, strong) RNNTabBarOptions* bottomTabs;
27
+@property (nonatomic, strong) RNNTopTabOptions* topTab;
26 28
 @property (nonatomic, strong) RNNSideMenuOptions* sideMenu;
27 29
 @property (nonatomic, strong) UIImage* backgroundImage;
28 30
 @property (nonatomic, strong) UIImage* rootBackgroundImage;
@@ -39,5 +41,6 @@ extern const NSInteger TOP_BAR_TRANSPARENT_TAG;
39 41
 -(void)storeOriginalTopBarImages:(UIViewController*)viewController;
40 42
 
41 43
 - (void)applyTabBarItemOptions:(UIViewController*)viewController;
44
+- (void)applyTopTab:(UIViewController*)viewController;
42 45
 
43 46
 @end

+ 13
- 0
lib/ios/RNNNavigationOptions.m View File

@@ -4,6 +4,7 @@
4 4
 #import "RNNTabBarController.h"
5 5
 #import "RNNTopBarOptions.h"
6 6
 #import "RNNSideMenuController.h"
7
+#import "RNNRootViewController.h"
7 8
 
8 9
 const NSInteger BLUR_STATUS_TAG = 78264801;
9 10
 const NSInteger BLUR_TOPBAR_TAG = 78264802;
@@ -26,6 +27,7 @@ const NSInteger TOP_BAR_TRANSPARENT_TAG = 78264803;
26 27
 	self.leftButtons = [navigationOptions objectForKey:@"leftButtons"];
27 28
 	self.rightButtons = [navigationOptions objectForKey:@"rightButtons"];
28 29
 	self.topBar = [[RNNTopBarOptions alloc] initWithDict:[navigationOptions objectForKey:@"topBar"]];
30
+	self.topTab = [[RNNTopTabOptions alloc] initWithDict:[navigationOptions objectForKey:@"topTab"]];
29 31
 	self.bottomTabs = [[RNNTabBarOptions alloc] initWithDict:[navigationOptions objectForKey:@"bottomTabs"]];
30 32
 	self.sideMenu = [[RNNSideMenuOptions alloc] initWithDict:[navigationOptions objectForKey:@"sideMenu"]];
31 33
 	self.backgroundImage = [RCTConvert UIImage:[navigationOptions objectForKey:@"backgroundImage"]];
@@ -41,6 +43,8 @@ const NSInteger TOP_BAR_TRANSPARENT_TAG = 78264803;
41 43
 			[self.topBar mergeWith:[otherOptions objectForKey:key]];
42 44
 		} else if ([key isEqualToString:@"bottomTabs"]) {
43 45
 			[self.bottomTabs mergeWith:[otherOptions objectForKey:key]];
46
+		} else if ([key isEqualToString:@"topTab"]) {
47
+			[self.topTab mergeWith:[otherOptions objectForKey:key]];
44 48
 		} else if ([key isEqualToString:@"sideMenu"]) {
45 49
 			[self.sideMenu mergeWith:[otherOptions objectForKey:@"sideMenu"]];
46 50
 		} else if ([key isEqualToString:@"bottomTab"]) {
@@ -291,6 +295,15 @@ const NSInteger TOP_BAR_TRANSPARENT_TAG = 78264803;
291 295
 	}
292 296
 	
293 297
 	[self applyTabBarItemOptions:viewController];
298
+	[self applyTopTab:viewController];
299
+}
300
+
301
+- (void)applyTopTab:(RNNRootViewController*)viewController {
302
+	if (self.topTab) {
303
+		if (self.topTab.title) {
304
+			[viewController.topTabsViewController viewController:viewController changedTitle:self.topTab.title];
305
+		}
306
+	}
294 307
 }
295 308
 
296 309
 - (void)applyTabBarItemOptions:(UIViewController*)viewController {

+ 5
- 0
lib/ios/RNNRootViewController.h View File

@@ -6,6 +6,7 @@
6 6
 #import "RNNEventEmitter.h"
7 7
 #import "RNNNavigationOptions.h"
8 8
 #import "RNNAnimator.h"
9
+#import "RNNTopTabsViewController.h"
9 10
 #import "RNNRootViewProtocol.h"
10 11
 
11 12
 @interface RNNRootViewController : UIViewController	<RNNRootViewProtocol>
@@ -14,6 +15,7 @@
14 15
 @property (nonatomic, strong) RNNAnimator* animator;
15 16
 @property (nonatomic, strong) RNNEventEmitter *eventEmitter;
16 17
 @property (nonatomic, strong) NSString* containerId;
18
+@property (nonatomic, strong) RNNTopTabsViewController* topTabsViewController;
17 19
 
18 20
 -(instancetype)initWithName:(NSString*)name
19 21
 				withOptions:(RNNNavigationOptions*)options
@@ -25,5 +27,8 @@
25 27
 
26 28
 -(void)applyNavigationButtons;
27 29
 -(void)applyTabBarItem;
30
+-(void)applyTopTabsOptions;
31
+
32
+-(BOOL)isAnimated;
28 33
 
29 34
 @end

+ 4
- 2
lib/ios/RNNRootViewController.m View File

@@ -106,8 +106,6 @@
106 106
 
107 107
 }
108 108
 
109
-
110
-
111 109
 -(void)applyNavigationButtons{
112 110
 	[self.navigationButtons applyLeftButtons:self.navigationOptions.leftButtons rightButtons:self.navigationOptions.rightButtons];
113 111
 }
@@ -116,6 +114,10 @@
116 114
 	[self.navigationOptions applyTabBarItemOptions:self];
117 115
 }
118 116
 
117
+-(void)applyTopTabsOptions {
118
+	[self.navigationOptions applyTopTab:self];
119
+}
120
+
119 121
 /**
120 122
  *	fix for #877, #878
121 123
  */

+ 8
- 0
lib/ios/RNNSegmentedControl.h View File

@@ -0,0 +1,8 @@
1
+#import <Foundation/Foundation.h>
2
+#import "HMSegmentedControl.h"
3
+
4
+@interface RNNSegmentedControl : HMSegmentedControl
5
+
6
+- (void)setTitle:(NSString*)title atIndex:(NSUInteger)index;
7
+
8
+@end

+ 11
- 0
lib/ios/RNNSegmentedControl.m View File

@@ -0,0 +1,11 @@
1
+#import "RNNSegmentedControl.h"
2
+
3
+@implementation RNNSegmentedControl
4
+
5
+- (void)setTitle:(NSString*)title atIndex:(NSUInteger)index {
6
+	NSMutableArray* mutableTitles = [[NSMutableArray alloc] initWithArray:self.sectionTitles];
7
+	[mutableTitles setObject:title atIndexedSubscript:index];
8
+	[self setSectionTitles:mutableTitles];
9
+}
10
+
11
+@end

+ 14
- 0
lib/ios/RNNTopTabOptions.h View File

@@ -0,0 +1,14 @@
1
+#import <Foundation/Foundation.h>
2
+
3
+extern const NSInteger BLUR_TOPBAR_TAG;
4
+
5
+@interface RNNTopTabOptions : NSObject
6
+
7
+@property (nonatomic, strong) NSString* title;
8
+
9
+-(instancetype)init;
10
+-(instancetype)initWithDict:(NSDictionary *)topBarOptions;
11
+-(void)mergeWith:(NSDictionary*)otherOptions;
12
+
13
+@end
14
+

+ 23
- 0
lib/ios/RNNTopTabOptions.m View File

@@ -0,0 +1,23 @@
1
+#import "RNNTopTabOptions.h"
2
+
3
+@implementation RNNTopTabOptions
4
+
5
+-(instancetype)init {
6
+	return [self initWithDict:@{}];
7
+}
8
+
9
+-(instancetype)initWithDict:(NSDictionary *)tabBarOptions {
10
+	self = [super init];
11
+	
12
+	self.title = [tabBarOptions valueForKey:@"title"];
13
+	
14
+	return self;
15
+}
16
+
17
+-(void)mergeWith:(NSDictionary *)otherOptions {
18
+	for (id key in otherOptions) {
19
+		[self setValue:[otherOptions objectForKey:key] forKey:key];
20
+	}
21
+}
22
+@end
23
+

+ 14
- 0
lib/ios/RNNTopTabsViewController.h View File

@@ -0,0 +1,14 @@
1
+#import <Foundation/Foundation.h>
2
+#import <UIKit/UIKit.h>
3
+#import <React/RCTUIManager.h>
4
+#import "RNNRootViewProtocol.h"
5
+
6
+@interface RNNTopTabsViewController : UIViewController <RNNRootViewProtocol>
7
+
8
+@property (nonatomic, retain) UIView* contentView;
9
+
10
+- (void)setViewControllers:(NSArray*)viewControllers;
11
+- (void)viewController:(UIViewController*)vc changedTitle:(NSString*)title;
12
+- (instancetype)init;
13
+
14
+@end

+ 79
- 0
lib/ios/RNNTopTabsViewController.m View File

@@ -0,0 +1,79 @@
1
+#import "RNNTopTabsViewController.h"
2
+#import "RNNSegmentedControl.h"
3
+#import "RNNRootViewController.h"
4
+#import "ReactNativeNavigation.h"
5
+
6
+@interface RNNTopTabsViewController () {
7
+	NSArray* _viewControllers;
8
+	UIViewController* _currentViewController;
9
+	RNNSegmentedControl* _segmentedControl;
10
+}
11
+
12
+@end
13
+
14
+@implementation RNNTopTabsViewController
15
+
16
+- (instancetype)init {
17
+	self = [super init];
18
+		
19
+	[self.view setBackgroundColor:[UIColor whiteColor]];
20
+	self.edgesForExtendedLayout = UIRectEdgeNone;
21
+	
22
+	[self createTabBar];
23
+	[self createContentView];
24
+	
25
+	return self;
26
+}
27
+
28
+- (void)createTabBar {
29
+	_segmentedControl = [[RNNSegmentedControl alloc] initWithSectionTitles:@[@"", @"", @""]];
30
+	_segmentedControl.frame = CGRectMake(0, 0, self.view.bounds.size.width, 50);
31
+	_segmentedControl.selectionIndicatorLocation = HMSegmentedControlSelectionIndicatorLocationNone;
32
+	_segmentedControl.selectionStyle = HMSegmentedControlSelectionStyleBox;
33
+	_segmentedControl.selectedSegmentIndex = HMSegmentedControlNoSegment;
34
+	
35
+	[_segmentedControl addTarget:self action:@selector(segmentedControlChangedValue:) forControlEvents:UIControlEventValueChanged];
36
+	[self.view addSubview:_segmentedControl];
37
+}
38
+
39
+- (void)segmentedControlChangedValue:(HMSegmentedControl*)segmentedControl {
40
+	[self setSelectedViewControllerIndex:segmentedControl.selectedSegmentIndex];
41
+}
42
+
43
+- (void)createContentView {
44
+	_contentView = [[UIView alloc] initWithFrame:CGRectMake(0, 50, self.view.bounds.size.width, self.view.bounds.size.height - 50)];
45
+	_contentView.backgroundColor = [UIColor grayColor];
46
+	[self.view addSubview:_contentView];
47
+}
48
+
49
+- (void)setSelectedViewControllerIndex:(NSUInteger)index {
50
+	UIViewController *toVC = _viewControllers[index];
51
+	[_contentView addSubview:toVC.view];
52
+	[_currentViewController.view removeFromSuperview];
53
+	_currentViewController = toVC;
54
+}
55
+
56
+- (void)setViewControllers:(NSArray *)viewControllers {
57
+	_viewControllers = viewControllers;
58
+	for (RNNRootViewController* childVc in viewControllers) {
59
+		[childVc.view setFrame:_contentView.bounds];
60
+		[childVc applyTopTabsOptions];
61
+	}
62
+	
63
+	[self setSelectedViewControllerIndex:0];
64
+}
65
+
66
+- (void)viewController:(UIViewController*)vc changedTitle:(NSString*)title {
67
+	NSUInteger vcIndex = [_viewControllers indexOfObject:vc];
68
+	[_segmentedControl setTitle:title atIndex:vcIndex];
69
+}
70
+
71
+- (void)viewDidLoad {
72
+    [super viewDidLoad];
73
+}
74
+
75
+- (BOOL)isAnimated {
76
+	return NO;
77
+}
78
+
79
+@end

+ 2
- 2
lib/ios/ReactNativeNavigation.m View File

@@ -69,8 +69,8 @@
69 69
 	RNNEventEmitter *eventEmitter = [[RNNEventEmitter alloc] init];
70 70
 	
71 71
 	id<RNNRootViewCreator> rootViewCreator = [[RNNReactRootViewCreator alloc] initWithBridge:bridge];
72
-	RNNControllerFactory *controllerFactory = [[RNNControllerFactory alloc] initWithRootViewCreator:rootViewCreator store:_store eventEmitter:eventEmitter];
73
-	_commandsHandler = [[RNNCommandsHandler alloc] initWithStore:_store controllerFactory:controllerFactory andBridge:bridge];
72
+	RNNControllerFactory *controllerFactory = [[RNNControllerFactory alloc] initWithRootViewCreator:rootViewCreator store:_store eventEmitter:eventEmitter andBridge:bridge];
73
+	_commandsHandler = [[RNNCommandsHandler alloc] initWithStore:_store controllerFactory:controllerFactory];
74 74
 	RNNBridgeModule *bridgeModule = [[RNNBridgeModule alloc] initWithCommandsHandler:_commandsHandler];
75 75
 	
76 76
 	return @[bridgeModule,eventEmitter];

+ 40
- 0
lib/ios/ReactNativeNavigation.xcodeproj/project.pbxproj View File

@@ -57,6 +57,14 @@
57 57
 		268692831E5054F800E2C612 /* RNNStore.m in Sources */ = {isa = PBXBuildFile; fileRef = 268692811E5054F800E2C612 /* RNNStore.m */; };
58 58
 		26916C981E4B9E7700D13680 /* RNNReactRootViewCreator.h in Headers */ = {isa = PBXBuildFile; fileRef = 26916C961E4B9E7700D13680 /* RNNReactRootViewCreator.h */; };
59 59
 		26916C991E4B9E7700D13680 /* RNNReactRootViewCreator.m in Sources */ = {isa = PBXBuildFile; fileRef = 26916C971E4B9E7700D13680 /* RNNReactRootViewCreator.m */; };
60
+		507F43C51FF4F17C00D9425B /* RNNTopTabsViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 507F43C31FF4F17C00D9425B /* RNNTopTabsViewController.h */; };
61
+		507F43C61FF4F17C00D9425B /* RNNTopTabsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 507F43C41FF4F17C00D9425B /* RNNTopTabsViewController.m */; };
62
+		507F43C91FF4F9CC00D9425B /* RNNTopTabOptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 507F43C71FF4F9CC00D9425B /* RNNTopTabOptions.h */; };
63
+		507F43CA1FF4F9CC00D9425B /* RNNTopTabOptions.m in Sources */ = {isa = PBXBuildFile; fileRef = 507F43C81FF4F9CC00D9425B /* RNNTopTabOptions.m */; };
64
+		507F43F41FF4FCFE00D9425B /* HMSegmentedControl.h in Headers */ = {isa = PBXBuildFile; fileRef = 507F43F21FF4FCFE00D9425B /* HMSegmentedControl.h */; };
65
+		507F43F51FF4FCFE00D9425B /* HMSegmentedControl.m in Sources */ = {isa = PBXBuildFile; fileRef = 507F43F31FF4FCFE00D9425B /* HMSegmentedControl.m */; };
66
+		507F43F81FF525B500D9425B /* RNNSegmentedControl.h in Headers */ = {isa = PBXBuildFile; fileRef = 507F43F61FF525B500D9425B /* RNNSegmentedControl.h */; };
67
+		507F43F91FF525B500D9425B /* RNNSegmentedControl.m in Sources */ = {isa = PBXBuildFile; fileRef = 507F43F71FF525B500D9425B /* RNNSegmentedControl.m */; };
60 68
 		507F44201FFA8A8800D9425B /* RNNRootViewProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = 507F441F1FFA8A8800D9425B /* RNNRootViewProtocol.h */; };
61 69
 		50CB3B691FDE911400AA153B /* RNNSideMenuOptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 50CB3B671FDE911400AA153B /* RNNSideMenuOptions.h */; };
62 70
 		50CB3B6A1FDE911400AA153B /* RNNSideMenuOptions.m in Sources */ = {isa = PBXBuildFile; fileRef = 50CB3B681FDE911400AA153B /* RNNSideMenuOptions.m */; };
@@ -208,6 +216,14 @@
208 216
 		26916C941E4B9CCC00D13680 /* RNNRootViewCreator.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNNRootViewCreator.h; sourceTree = "<group>"; };
209 217
 		26916C961E4B9E7700D13680 /* RNNReactRootViewCreator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNNReactRootViewCreator.h; sourceTree = "<group>"; };
210 218
 		26916C971E4B9E7700D13680 /* RNNReactRootViewCreator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNNReactRootViewCreator.m; sourceTree = "<group>"; };
219
+		507F43C31FF4F17C00D9425B /* RNNTopTabsViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNNTopTabsViewController.h; sourceTree = "<group>"; };
220
+		507F43C41FF4F17C00D9425B /* RNNTopTabsViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNNTopTabsViewController.m; sourceTree = "<group>"; };
221
+		507F43C71FF4F9CC00D9425B /* RNNTopTabOptions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNNTopTabOptions.h; sourceTree = "<group>"; };
222
+		507F43C81FF4F9CC00D9425B /* RNNTopTabOptions.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNNTopTabOptions.m; sourceTree = "<group>"; };
223
+		507F43F21FF4FCFE00D9425B /* HMSegmentedControl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HMSegmentedControl.h; sourceTree = "<group>"; };
224
+		507F43F31FF4FCFE00D9425B /* HMSegmentedControl.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HMSegmentedControl.m; sourceTree = "<group>"; };
225
+		507F43F61FF525B500D9425B /* RNNSegmentedControl.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNNSegmentedControl.h; sourceTree = "<group>"; };
226
+		507F43F71FF525B500D9425B /* RNNSegmentedControl.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNNSegmentedControl.m; sourceTree = "<group>"; };
211 227
 		507F441F1FFA8A8800D9425B /* RNNRootViewProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNNRootViewProtocol.h; sourceTree = "<group>"; };
212 228
 		50CB3B671FDE911400AA153B /* RNNSideMenuOptions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNNSideMenuOptions.h; sourceTree = "<group>"; };
213 229
 		50CB3B681FDE911400AA153B /* RNNSideMenuOptions.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNNSideMenuOptions.m; sourceTree = "<group>"; };
@@ -398,6 +414,15 @@
398 414
 			path = Animations;
399 415
 			sourceTree = "<group>";
400 416
 		};
417
+		507F43F11FF4FCD800D9425B /* HMSegmentControl */ = {
418
+			isa = PBXGroup;
419
+			children = (
420
+				507F43F21FF4FCFE00D9425B /* HMSegmentedControl.h */,
421
+				507F43F31FF4FCFE00D9425B /* HMSegmentedControl.m */,
422
+			);
423
+			name = HMSegmentControl;
424
+			sourceTree = "<group>";
425
+		};
401 426
 		7B1E4C4B1E2D173700C3A525 /* Controllers */ = {
402 427
 			isa = PBXGroup;
403 428
 			children = (
@@ -438,8 +463,14 @@
438 463
 				A7626BFC1FC2FB2C00492FB8 /* RNNTopBarOptions.m */,
439 464
 				A7626BFF1FC578AB00492FB8 /* RNNTabBarOptions.h */,
440 465
 				A7626C001FC5796200492FB8 /* RNNTabBarOptions.m */,
466
+				507F43C71FF4F9CC00D9425B /* RNNTopTabOptions.h */,
467
+				507F43C81FF4F9CC00D9425B /* RNNTopTabOptions.m */,
441 468
 				50CB3B671FDE911400AA153B /* RNNSideMenuOptions.h */,
442 469
 				50CB3B681FDE911400AA153B /* RNNSideMenuOptions.m */,
470
+				507F43C31FF4F17C00D9425B /* RNNTopTabsViewController.h */,
471
+				507F43C41FF4F17C00D9425B /* RNNTopTabsViewController.m */,
472
+				507F43F61FF525B500D9425B /* RNNSegmentedControl.h */,
473
+				507F43F71FF525B500D9425B /* RNNSegmentedControl.m */,
443 474
 				507F441F1FFA8A8800D9425B /* RNNRootViewProtocol.h */,
444 475
 			);
445 476
 			name = Controllers;
@@ -508,6 +539,7 @@
508 539
 				7BD721F31E2D3AA100724059 /* Bridge */,
509 540
 				7B1E4C4B1E2D173700C3A525 /* Controllers */,
510 541
 				263905881E4C6F440023D7D3 /* RNNSideMenu */,
542
+				507F43F11FF4FCD800D9425B /* HMSegmentControl */,
511 543
 				7B49FEBC1E95090800DEB3EA /* ReactNativeNavigationTests */,
512 544
 				D8AFADBE1BEE6F3F00A4592D /* Products */,
513 545
 				7B49FED01E950A7A00DEB3EA /* Frameworks */,
@@ -582,6 +614,7 @@
582 614
 				263905B71E4C6F440023D7D3 /* UIViewController+MMDrawerController.h in Headers */,
583 615
 				263905BB1E4C6F440023D7D3 /* RCCDrawerHelper.h in Headers */,
584 616
 				263905CC1E4C6F440023D7D3 /* SidebarWunderlistAnimation.h in Headers */,
617
+				507F43F41FF4FCFE00D9425B /* HMSegmentedControl.h in Headers */,
585 618
 				7B4928081E70415400555040 /* RNNCommandsHandler.h in Headers */,
586 619
 				263905AE1E4C6F440023D7D3 /* MMDrawerBarButtonItem.h in Headers */,
587 620
 				50F5DFC11F407A8C001A00BC /* RNNTabBarController.h in Headers */,
@@ -590,6 +623,7 @@
590 623
 				263905C21E4C6F440023D7D3 /* SidebarAnimation.h in Headers */,
591 624
 				E8E518361F83B94A000467AC /* RNNViewLocation.h in Headers */,
592 625
 				263905B51E4C6F440023D7D3 /* MMExampleDrawerVisualStateManager.h in Headers */,
626
+				507F43C51FF4F17C00D9425B /* RNNTopTabsViewController.h in Headers */,
593 627
 				263905C61E4C6F440023D7D3 /* SidebarFeedlyAnimation.h in Headers */,
594 628
 				7B1126A31E2D2B6C00F9B03B /* RNNSplashScreen.h in Headers */,
595 629
 				261F0E641E6EC94900989DE2 /* RNNModalManager.h in Headers */,
@@ -622,7 +656,9 @@
622 656
 				263905D61E4C94970023D7D3 /* RNNSideMenuController.h in Headers */,
623 657
 				263905C81E4C6F440023D7D3 /* SidebarFlipboardAnimation.h in Headers */,
624 658
 				7BEF0D1C1E43771B003E96B0 /* RNNLayoutNode.h in Headers */,
659
+				507F43C91FF4F9CC00D9425B /* RNNTopTabOptions.h in Headers */,
625 660
 				E8A5CD521F464F0400E89D0D /* RNNAnimator.h in Headers */,
661
+				507F43F81FF525B500D9425B /* RNNSegmentedControl.h in Headers */,
626 662
 			);
627 663
 			runOnlyForDeploymentPostprocessing = 0;
628 664
 		};
@@ -762,12 +798,15 @@
762 798
 				2145452A1F4DC85F006E8DA1 /* RCTHelpers.m in Sources */,
763 799
 				263905C11E4C6F440023D7D3 /* SidebarAirbnbAnimation.m in Sources */,
764 800
 				263905D71E4C94970023D7D3 /* RNNSideMenuController.m in Sources */,
801
+				507F43CA1FF4F9CC00D9425B /* RNNTopTabOptions.m in Sources */,
765 802
 				26916C991E4B9E7700D13680 /* RNNReactRootViewCreator.m in Sources */,
766 803
 				214545251F4DC125006E8DA1 /* RNNUIBarButtonItem.m in Sources */,
767 804
 				263905B81E4C6F440023D7D3 /* UIViewController+MMDrawerController.m in Sources */,
768 805
 				263905CD1E4C6F440023D7D3 /* SidebarWunderlistAnimation.m in Sources */,
769 806
 				263905CF1E4C6F440023D7D3 /* TheSidebarController.m in Sources */,
770 807
 				E8A430121F9CB87B00B61A20 /* RNNAnimatedView.m in Sources */,
808
+				507F43F51FF4FCFE00D9425B /* HMSegmentedControl.m in Sources */,
809
+				507F43C61FF4F17C00D9425B /* RNNTopTabsViewController.m in Sources */,
771 810
 				50EB93421FE14A3E00BD8EEE /* RNNTabItemOptions.m in Sources */,
772 811
 				E8367B811F7A8A4700675C05 /* VICMAImageView.m in Sources */,
773 812
 				A7626C011FC5796200492FB8 /* RNNTabBarOptions.m in Sources */,
@@ -776,6 +815,7 @@
776 815
 				7B4928091E70415400555040 /* RNNCommandsHandler.m in Sources */,
777 816
 				268692831E5054F800E2C612 /* RNNStore.m in Sources */,
778 817
 				7BC9346E1E26886E00EFA125 /* RNNControllerFactory.m in Sources */,
818
+				507F43F91FF525B500D9425B /* RNNSegmentedControl.m in Sources */,
779 819
 				E8E5182F1F83A48B000467AC /* RNNTransitionStateHolder.m in Sources */,
780 820
 				263905B61E4C6F440023D7D3 /* MMExampleDrawerVisualStateManager.m in Sources */,
781 821
 				E8E518331F83B3E0000467AC /* RNNUtils.m in Sources */,

+ 2
- 4
lib/ios/ReactNativeNavigationTests/RNNCommandsHandlerTest.m View File

@@ -10,7 +10,6 @@
10 10
 
11 11
 @property (nonatomic, strong) RNNStore* store;
12 12
 @property (nonatomic, strong) RNNCommandsHandler* uut;
13
-@property (nonatomic, strong) RCTBridge* bridge;
14 13
 
15 14
 @end
16 15
 
@@ -20,8 +19,7 @@
20 19
 	[super setUp];
21 20
 //	[self.store setReadyToReceiveCommands:true];
22 21
 	self.store = [[RNNStore alloc] init];
23
-	self.bridge = nil;
24
-	self.uut = [[RNNCommandsHandler alloc] initWithStore:self.store controllerFactory:nil andBridge:self.bridge];
22
+	self.uut = [[RNNCommandsHandler alloc] initWithStore:self.store controllerFactory:nil];
25 23
 }
26 24
 
27 25
 
@@ -40,7 +38,7 @@
40 38
 -(NSArray*) getPublicMethodNamesForObject:(NSObject*)obj{
41 39
 	NSMutableArray* skipMethods = [NSMutableArray new];
42 40
 
43
-	[skipMethods addObject:@"initWithStore:controllerFactory:andBridge:"];
41
+	[skipMethods addObject:@"initWithStore:controllerFactory:"];
44 42
 	[skipMethods addObject:@"assertReady"];
45 43
 	[skipMethods addObject:@".cxx_destruct"];
46 44
 

+ 1
- 1
lib/ios/ReactNativeNavigationTests/RNNControllerFactoryTest.m View File

@@ -21,7 +21,7 @@
21 21
 	[super setUp];
22 22
 	self.creator = nil;
23 23
 	self.store = [RNNStore new];
24
-	self.factory = [[RNNControllerFactory alloc] initWithRootViewCreator:self.creator store:self.store eventEmitter:nil];
24
+	self.factory = [[RNNControllerFactory alloc] initWithRootViewCreator:self.creator store:self.store eventEmitter:nil andBridge:nil];
25 25
 }
26 26
 
27 27
 - (void)tearDown {