Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions HMSegmentedControl/HMSegmentedControl.h
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,24 @@ typedef NS_ENUM(NSInteger, HMSegmentedControlImagePosition) {

@property (nonatomic, readwrite) UIEdgeInsets enlargeEdgeInset;

/**
Inset left and right edges of between segments.

Default is UIEdgeInsetsMake(0, 0, 0, 0)
*/
@property (nonatomic, readwrite) UIEdgeInsets segmentMarginInset;
/**
Color for the title background
*/
@property (nonatomic, strong) UIColor *titleBackgroundColor;
/**
Radius for the title background:0~1.0
*/
@property (nonatomic) CGFloat titleBackgroundRadius;
/**
Height for the segment item
*/
@property (nonatomic) CGFloat segmentHeight;
/**
Default is YES. Set to NO to disable animation during user selection.
*/
Expand Down
80 changes: 47 additions & 33 deletions HMSegmentedControl/HMSegmentedControl.m
Original file line number Diff line number Diff line change
Expand Up @@ -117,17 +117,17 @@ - (instancetype)initWithSectionImages:(NSArray<UIImage *> *)sectionImages sectio
}

- (instancetype)initWithSectionImages:(NSArray<UIImage *> *)sectionImages sectionSelectedImages:(NSArray<UIImage *> *)sectionSelectedImages titlesForSections:(NSArray<NSString *> *)sectiontitles {
self = [super initWithFrame:CGRectZero];
self = [super initWithFrame:CGRectZero];
if (self) {
[self commonInit];
if (sectionImages.count != sectiontitles.count) {
[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];
if (sectionImages.count != sectiontitles.count) {
[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];
}
self.sectionImages = sectionImages;
self.sectionSelectedImages = sectionSelectedImages;
self.sectionTitles = sectiontitles;
self.sectionTitles = sectiontitles;
self.type = HMSegmentedControlTypeTextImages;
}
return self;
Expand Down Expand Up @@ -207,11 +207,11 @@ - (void)setSectionImages:(NSArray<UIImage *> *)sectionImages {
}

- (void)setSelectionIndicatorLocation:(HMSegmentedControlSelectionIndicatorLocation)selectionIndicatorLocation {
_selectionIndicatorLocation = selectionIndicatorLocation;
if (selectionIndicatorLocation == HMSegmentedControlSelectionIndicatorLocationNone) {
self.selectionIndicatorHeight = 0.0f;
}
_selectionIndicatorLocation = selectionIndicatorLocation;
if (selectionIndicatorLocation == HMSegmentedControlSelectionIndicatorLocationNone) {
self.selectionIndicatorHeight = 0.0f;
}
}

- (void)setSelectionIndicatorBoxOpacity:(CGFloat)selectionIndicatorBoxOpacity {
Expand Down Expand Up @@ -313,6 +313,10 @@ - (void)drawRect:(CGRect)rect {
if (self.accessibilityElements==nil)
self.accessibilityElements = [NSMutableArray arrayWithCapacity:0];

if (self.segmentWidthsArray.count == 0 && self.sectionTitles.count == 0 && self.sectionImages.count == 0) {
return;
}

if (self.type == HMSegmentedControlTypeText) {
[self removeTitleBackgroundLayers];
[self.sectionTitles enumerateObjectsUsingBlock:^(id titleString, NSUInteger idx, BOOL *stop) {
Expand All @@ -321,7 +325,7 @@ - (void)drawRect:(CGRect)rect {
CGFloat stringHeight = 0;
CGSize size = [self measureTitleAtIndex:idx];
stringWidth = size.width;
stringHeight = size.height;
stringHeight = self.segmentHeight > 0 ? self.segmentHeight:size.height;
CGRect rectDiv = CGRectZero;
CGRect fullRect = CGRectZero;

Expand All @@ -342,7 +346,7 @@ - (void)drawRect:(CGRect)rect {
for (NSNumber *width in self.segmentWidthsArray) {
if (idx == i)
break;
xOffset = xOffset + [width floatValue];
xOffset = xOffset + [width floatValue] + self.segmentMarginInset.left + self.segmentMarginInset.right;
i++;
}

Expand All @@ -363,6 +367,8 @@ - (void)drawRect:(CGRect)rect {
}
titleLayer.string = [self attributedTitleAtIndex:idx];
titleLayer.contentsScale = [[UIScreen mainScreen] scale];
titleLayer.backgroundColor = self.titleBackgroundColor.CGColor;
titleLayer.cornerRadius = CGRectGetHeight(rect) * self.titleBackgroundRadius;

[self.scrollView.layer addSublayer:titleLayer];

Expand Down Expand Up @@ -465,11 +471,11 @@ - (void)drawRect:(CGRect)rect {
}];
} else if (self.type == HMSegmentedControlTypeTextImages){
[self removeTitleBackgroundLayers];
[self.sectionImages enumerateObjectsUsingBlock:^(id iconImage, NSUInteger idx, BOOL *stop) {
[self.sectionImages enumerateObjectsUsingBlock:^(id iconImage, NSUInteger idx, BOOL *stop) {
UIImage *icon = iconImage;
CGFloat imageWidth = icon.size.width;
CGFloat imageHeight = icon.size.height;
CGSize stringSize = [self measureTitleAtIndex:idx];
CGFloat stringHeight = stringSize.height;
CGFloat stringWidth = stringSize.width;
Expand Down Expand Up @@ -554,7 +560,7 @@ - (void)drawRect:(CGRect)rect {
}
CALayer *imageLayer = [CALayer layer];
imageLayer.frame = imageRect;
if (self.selectedSegmentIndex == idx) {
if (self.sectionSelectedImages) {
UIImage *highlightIcon = [self.sectionSelectedImages objectAtIndex:idx];
Expand All @@ -567,7 +573,7 @@ - (void)drawRect:(CGRect)rect {
}

[self.scrollView.layer addSublayer:imageLayer];
titleLayer.contentsScale = [[UIScreen mainScreen] scale];
titleLayer.contentsScale = [[UIScreen mainScreen] scale];
[self.scrollView.layer addSublayer:titleLayer];

if ([self.accessibilityElements count]<=idx) {
Expand All @@ -594,10 +600,10 @@ - (void)drawRect:(CGRect)rect {
else
element.accessibilityTraits = UIAccessibilityTraitButton;
}
[self addBackgroundAndBorderLayerWithRect:imageRect];
}];
}
}

// Add the selection indicators
if (self.selectedSegmentIndex != HMSegmentedControlNoSegment) {
Expand Down Expand Up @@ -714,11 +720,11 @@ - (CGRect)frameForSelectionIndicator {
CGFloat imageWidth = sectionImage.size.width;
sectionWidth = imageWidth;
} else if (self.type == HMSegmentedControlTypeTextImages) {
CGFloat stringWidth = [self measureTitleAtIndex:self.selectedSegmentIndex].width;
UIImage *sectionImage = [self.sectionImages objectAtIndex:self.selectedSegmentIndex];
CGFloat imageWidth = sectionImage.size.width;
CGFloat stringWidth = [self measureTitleAtIndex:self.selectedSegmentIndex].width;
UIImage *sectionImage = [self.sectionImages objectAtIndex:self.selectedSegmentIndex];
CGFloat imageWidth = sectionImage.size.width;
sectionWidth = MAX(stringWidth, imageWidth);
}
}

if (self.selectionStyle == HMSegmentedControlSelectionStyleArrow) {
CGFloat widthToEndOfSelectedSegment = (self.segmentWidth * self.selectedSegmentIndex) + self.segmentWidth;
Expand Down Expand Up @@ -767,7 +773,7 @@ - (CGRect)frameForFillerSelectionIndicator {
if (self.selectedSegmentIndex == i) {
break;
}
selectedSegmentOffset = selectedSegmentOffset + [width floatValue];
selectedSegmentOffset = selectedSegmentOffset + [width floatValue] + self.segmentMarginInset.left + self.segmentMarginInset.right;

i++;
}
Expand Down Expand Up @@ -856,7 +862,7 @@ - (void)updateSegmentsRects {
}

self.scrollView.scrollEnabled = self.isUserDraggable;
self.scrollView.contentSize = CGSizeMake([self totalSegmentedControlWidth], self.frame.size.height);
self.scrollView.contentSize = CGSizeMake([self totalSegmentedControlWidth] + (self.segmentMarginInset.left + self.segmentMarginInset.right)*[self sectionCount], self.frame.size.height);
}

- (NSUInteger)sectionCount {
Expand Down Expand Up @@ -899,12 +905,18 @@ - (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
// To know which segment the user touched, we need to loop over the widths and substract it from the x position.
CGFloat widthLeft = (touchLocation.x + self.scrollView.contentOffset.x);
for (NSNumber *width in self.segmentWidthsArray) {
widthLeft = widthLeft - [width floatValue];
CGFloat fullWidth = (self.segmentMarginInset.left + self.segmentMarginInset.right + [width floatValue]);
if(widthLeft < self.segmentMarginInset.left ||
(widthLeft > self.segmentMarginInset.left + [width floatValue] && widthLeft < fullWidth)) {
segment = self.selectedSegmentIndex;
break;
}

widthLeft = widthLeft - fullWidth ;

// When we don't have any width left to substract, we have the segment index.
if (widthLeft <= 0)
break;

segment++;
}
}
Expand Down Expand Up @@ -961,12 +973,14 @@ - (void)scrollTo:(NSUInteger)index animated:(BOOL)animated {
i++;
}

rectForSelectedIndex = CGRectMake(offsetter,
0,
[[self.segmentWidthsArray objectAtIndex:index] floatValue],
self.frame.size.height);

selectedSegmentOffset = (CGRectGetWidth(self.frame) / 2) - ([[self.segmentWidthsArray objectAtIndex:index] floatValue] / 2);
if (self.segmentWidthsArray.count > index) {
rectForSelectedIndex = CGRectMake(offsetter,
0,
[[self.segmentWidthsArray objectAtIndex:index] floatValue],
self.frame.size.height);

selectedSegmentOffset = (CGRectGetWidth(self.frame) / 2) - ([[self.segmentWidthsArray objectAtIndex:index] floatValue] / 2);
}
}


Expand Down
2 changes: 1 addition & 1 deletion HMSegmentedControlExample/AppDelegate.m
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ @implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.viewController = [[ExampleViewController alloc] init];
self.viewController = [[ViewController alloc] init];
self.window.rootViewController = self.viewController;
[self.window makeKeyAndVisible];
return YES;
Expand Down
26 changes: 23 additions & 3 deletions HMSegmentedControlExample/ViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,30 @@ - (void)viewDidLoad {
// Minimum code required to use the segmented control with the default styling.
HMSegmentedControl *segmentedControl = [[HMSegmentedControl alloc] initWithSectionTitles:@[@"Trending", @"News", @"Library"]];
segmentedControl.frame = CGRectMake(0, 60, viewWidth, 40);
segmentedControl.autoresizingMask = UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleWidth;
// segmentedControl.autoresizingMask = UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleWidth;
segmentedControl.type = HMSegmentedControlTypeText;
segmentedControl.segmentEdgeInset = UIEdgeInsetsMake(0, 16, 0, 16);
segmentedControl.segmentWidthStyle = HMSegmentedControlSegmentWidthStyleDynamic;
segmentedControl.borderType = HMSegmentedControlBorderTypeNone;
segmentedControl.selectionIndicatorLocation = HMSegmentedControlSelectionIndicatorLocationNone;
segmentedControl.selectionStyle = HMSegmentedControlSelectionStyleBox;;
segmentedControl.selectionIndicatorBoxColor = [UIColor colorWithRed:0.882 green:0 blue:1 alpha:1];
[segmentedControl addTarget:self action:@selector(segmentedControlChangedValue:) forControlEvents:UIControlEventValueChanged];
segmentedControl.titleBackgroundColor = [[UIColor yellowColor] colorWithAlphaComponent:0.3];
segmentedControl.titleBackgroundRadius = 0.5;
segmentedControl.segmentMarginInset = UIEdgeInsetsMake(0, 0, 0, 8);
segmentedControl.segmentHeight = 40;
[segmentedControl setTitleFormatter:^NSAttributedString * _Nonnull(HMSegmentedControl * _Nonnull segmentedControl, NSString * _Nonnull title, NSUInteger index, BOOL selected) {
return [[NSAttributedString alloc] initWithString:title attributes:@{
NSFontAttributeName: [UIFont systemFontOfSize:14],
NSForegroundColorAttributeName: [UIColor purpleColor],
NSBaselineOffsetAttributeName:@(-10)
}];
}];
[self.view addSubview:segmentedControl];

CALayer *layer = [segmentedControl valueForKey:@"selectionIndicatorBoxLayer"];
layer.cornerRadius = 20;

// Segmented control with scrolling
HMSegmentedControl *segmentedControl1 = [[HMSegmentedControl alloc] initWithSectionTitles:@[@"One", @"Two", @"Three", @"Four", @"Five", @"Six", @"Seven", @"Eight"]];
Expand Down Expand Up @@ -154,11 +174,11 @@ - (void)setApperanceForLabel:(UILabel *)label {
}

- (void)segmentedControlChangedValue:(HMSegmentedControl *)segmentedControl {
NSLog(@"Selected index %tu (via UIControlEventValueChanged)", segmentedControl.selectedSegmentIndex);
NSLog(@"Selected index %tu (via UIControlEventValueChanged)", segmentedControl.selectedSegmentIndex);
}

- (void)uisegmentedControlChangedValue:(UISegmentedControl *)segmentedControl {
NSLog(@"Selected index %tu", segmentedControl.selectedSegmentIndex);
NSLog(@"Selected index %tu", segmentedControl.selectedSegmentIndex);
}

#pragma mark - UIScrollViewDelegate
Expand Down