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
20 changes: 20 additions & 0 deletions SJSegmentedScrollView-ObjC/SJContentView.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//
// SJContentView.h
// Hike
//
// Created by Pavan Goyal on 02/05/18.
// Copyright © 2018 Hike Pvt. Ltd. All rights reserved.
//

#import <UIKit/UIKit.h>
#import "SJSegmentTab.h"

@interface SJContentView : UIScrollView

@property (nonatomic, copy) DidSelectSegmentAtIndex didSelectSegmentAtIndex;

- (void)addContentView:(UIView *)view frame:(CGRect)frame;
- (void)updateContentControllersFrame:(CGRect)frame;
- (void)movePageToIndex:(NSInteger)index animated:(BOOL)animated;

@end
99 changes: 99 additions & 0 deletions SJSegmentedScrollView-ObjC/SJContentView.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
//
// SJContentView.m
// Hike
//
// Created by Pavan Goyal on 02/05/18.
// Copyright © 2018 Hike Pvt. Ltd. All rights reserved.
//

#import "SJContentView.h"

@interface SJContentView () <UIScrollViewDelegate>

@property (nonatomic, assign) NSInteger pageIndex;
@property (nonatomic, strong) NSMutableArray<UIView *> *contentViews;
@property (nonatomic, strong) UIView *contentView;
@property (nonatomic, strong) NSLayoutConstraint *contentViewWidthConstraint;
@property (nonatomic, strong) NSMutableArray<NSLayoutConstraint *> *contentSubViewWidthConstraints;
@property (nonatomic, assign) CGFloat animationDuration;

@end

@implementation SJContentView

- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
_pageIndex = 0;
_contentViews = [[NSMutableArray alloc] init];
_animationDuration = 0.3;
_contentSubViewWidthConstraints = [[NSMutableArray alloc] init];
self.delegate = self;
[self setPagingEnabled:YES];
self.contentView = [[UIView alloc] init];
self.contentView.translatesAutoresizingMaskIntoConstraints = NO;
[self addSubview:self.contentView];
NSArray<NSLayoutConstraint *> *horizontalConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[contentView]|" options:0 metrics:nil views:@{@"contentView": self.contentView, @"mainView": self}];
[self addConstraints:horizontalConstraints];
self.contentViewWidthConstraint = [NSLayoutConstraint constraintWithItem:self.contentView attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:0];
[self addConstraint:self.contentViewWidthConstraint];
NSArray<NSLayoutConstraint *> *verticalConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|[contentView(==mainView)]|" options:0 metrics:nil views:@{@"contentView": self.contentView, @"mainView": self}];
[self addConstraints:verticalConstraints];
}
return self;
}

- (void)addContentView:(UIView *)view frame:(CGRect)frame {
view.translatesAutoresizingMaskIntoConstraints = NO;
[self.contentView addSubview:view];
CGFloat width = frame.size.width;
if (self.contentViews.count > 0) {
UIView *previousView = self.contentViews.lastObject;
NSArray<NSLayoutConstraint *> *horizontalConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:[previousView]-0-[view]" options:0 metrics:@{@"xPos": @(self.contentViews.count * width)} views:@{@"view": view, @"previousView": previousView}];
[self.contentView addConstraints:horizontalConstraints];
} else {
NSArray<NSLayoutConstraint *> *horizontalConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[view]" options:0 metrics:@{@"xPos": @(self.contentViews.count * width)} views:@{@"view": view}];
[self.contentView addConstraints:horizontalConstraints];
}
NSLayoutConstraint *widthConstraint = [NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:width];
[self.contentView addConstraint:widthConstraint];
[self.contentSubViewWidthConstraints addObject:widthConstraint];
NSArray<NSLayoutConstraint *> *verticalConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-0-[view]-0-|" options:0 metrics:nil views:@{@"view": view}];
[self.contentView addConstraints:verticalConstraints];
[self.contentViews addObject:view];
self.contentViewWidthConstraint.constant = self.contentViews.count * self.bounds.size.width;
}

- (void)updateContentControllersFrame:(CGRect)frame {
CGFloat width = frame.size.width;
self.contentViewWidthConstraint.constant = self.contentViews.count * width;
for (NSLayoutConstraint *constraint in self.contentSubViewWidthConstraints) {
constraint.constant = width;
}
[self layoutIfNeeded];
CGPoint point = self.contentOffset;
point.x = self.pageIndex * width;
[self setContentOffset:point animated:YES];
}

- (void)movePageToIndex:(NSInteger)index animated:(BOOL)animated {
self.pageIndex = index;
CGPoint point = CGPointMake((index * self.bounds.size.width), 0);
if (animated) {
[UIView animateWithDuration:self.animationDuration animations:^{
self.contentOffset = point;
}];
} else {
self.contentOffset = point;
}
}

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
self.pageIndex = self.contentOffset.x / self.bounds.size.width;
if (self.didSelectSegmentAtIndex) {
self.didSelectSegmentAtIndex(nil, self.pageIndex, YES);
}
[[NSNotificationCenter defaultCenter] postNotificationName:@"DidChangeSegmentIndex" object:@(self.pageIndex)];
}

@end
28 changes: 28 additions & 0 deletions SJSegmentedScrollView-ObjC/SJSegmentTab.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
//
// SJSegmentTab.h
// Hike
//
// Created by Pavan Goyal on 30/04/18.
// Copyright © 2018 Hike Pvt. Ltd. All rights reserved.
//

#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>

@class SJSegmentTab;

typedef void (^DidSelectSegmentAtIndex)(SJSegmentTab *segmentTab, NSInteger index, BOOL animated);

@interface SJSegmentTab : UIView

@property (nonatomic, assign) BOOL isSelected;
@property (nonatomic, copy) DidSelectSegmentAtIndex didSelectSegmentAtIndex;

- (instancetype)initWithTitle:(NSString *)title;
- (instancetype)initWithView:(UIView *)view;
- (void)setTitle:(NSString *)title;
- (void)titleColor:(UIColor *)color;
- (void)titleFont:(UIFont *)font;
- (void)addConstraintsToView:(UIView *)view;

@end
79 changes: 79 additions & 0 deletions SJSegmentedScrollView-ObjC/SJSegmentTab.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
//
// SJSegmentTab.m
// Hike
//
// Created by Pavan Goyal on 30/04/18.
// Copyright © 2018 Hike Pvt. Ltd. All rights reserved.
//

#import "SJSegmentTab.h"

@interface SJSegmentTab ()

@property(nonatomic, strong) UIButton *button;

@end

@implementation SJSegmentTab

- (instancetype)initWithTitle:(NSString *)title {
self = [self initWithFrame:CGRectZero];
[self setTitle:title];
return self;
}

- (instancetype)initWithView:(UIView *)view {
self = [self initWithFrame:CGRectZero];
[self insertSubview:view atIndex:0];
[view removeConstraints:view.constraints];
[self addConstraintsToView:view];
return self;
}

- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
self.translatesAutoresizingMaskIntoConstraints = NO;
self.button = [UIButton buttonWithType:UIButtonTypeCustom];
self.button.frame = self.bounds;
[self.button setSelected:NO];
[self.button addTarget:self action:@selector(onSegmentButtonPress:) forControlEvents:UIControlEventTouchUpInside];
[self addSubview:self.button];
[self addConstraintsToView:self.button];
}
return self;
}

- (void)addConstraintsToView:(UIView *)view {
view.translatesAutoresizingMaskIntoConstraints = NO;
NSArray<NSLayoutConstraint *> *verticalConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|[view]|" options:0 metrics:nil views:@{@"view": view}];
NSArray<NSLayoutConstraint *> *horizontalConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[view]|" options:0 metrics:nil views:@{@"view": view}];
[self addConstraints:verticalConstraints];
[self addConstraints:horizontalConstraints];
}

- (void)setTitle:(NSString *)title {
[self.button setTitle:title forState:UIControlStateNormal];
}

- (void)titleColor:(UIColor *)color {
[self.button setTitleColor:color forState:UIControlStateNormal];
}

- (void)titleFont:(UIFont *)font {
self.button.titleLabel.font = font;
}

- (void)setIsSelected:(BOOL)isSelected {
[self.button setSelected:isSelected];
}

- (void)onSegmentButtonPress:(id)sender {
NSInteger index = self.tag - 100;
[[NSNotificationCenter defaultCenter] postNotificationName:@"DidChangeSegmentIndex" object:@(index)];
if (self.didSelectSegmentAtIndex) {
self.didSelectSegmentAtIndex(self, index, YES);
}
}

@end
37 changes: 37 additions & 0 deletions SJSegmentedScrollView-ObjC/SJSegmentView.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
//
// SJSegmentView.h
// Hike
//
// Created by Pavan Goyal on 02/05/18.
// Copyright © 2018 Hike Pvt. Ltd. All rights reserved.
//

#import <UIKit/UIKit.h>
#import "SJSegmentTab.h"
#import "SJContentView.h"

@interface SJSegmentView : UIScrollView

@property (nonatomic, strong) NSMutableArray<SJSegmentTab *> *segments;
@property (nonatomic, strong) UIFont *font;
@property (nonatomic, assign) CGFloat selectedSegmentViewHeight;
@property (nonatomic, assign) NSInteger kSegmentViewTagOffset;
@property (nonatomic, assign) CGFloat segmentViewOffsetWidth;
@property (nonatomic, strong) UIView *segmentContentView;
@property (nonatomic, copy) DidSelectSegmentAtIndex didSelectSegmentAtIndex;
@property (nonatomic, strong) UIView *selectedSegmentView;
@property (nonatomic, strong) NSLayoutConstraint *xPosConstraints;
@property (nonatomic, strong) NSLayoutConstraint *contentViewWidthConstraint;
@property (nonatomic, strong) NSLayoutConstraint *selectedSegmentViewWidthConstraint;
@property (nonatomic, strong) NSMutableArray<NSLayoutConstraint *> *contentSubViewWidthConstraints;
@property (nonatomic, strong) NSArray<UIViewController *> *controllers;
@property (nonatomic, assign) CGFloat segmentViewHeight;
@property (nonatomic, strong) UIColor *selectedSegmentViewColor;
@property (nonatomic, strong) UIColor *titleColor;
@property (nonatomic, strong) UIColor *segmentBackgroundColor;
@property (nonatomic, strong) SJContentView *contentView;

- (void)didChangeParentViewFrame:(CGRect)frame;
- (void)setSegmentsView:(CGRect)frame;

@end
Loading