Skip to content

Commit

Permalink
重构
Browse files Browse the repository at this point in the history
  • Loading branch information
afishhhhh committed Feb 16, 2017
1 parent 9f06466 commit 69587f2
Show file tree
Hide file tree
Showing 5 changed files with 229 additions and 230 deletions.
28 changes: 21 additions & 7 deletions Classes/YUSegment+Internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,12 @@
#define YUSegment_Internal_h

static const NSTimeInterval kMovingAnimationDuration = 0.3;
static const CGFloat kEachSegmentDefaultMargin = 32.0;
static const CGFloat kContentOffsetDefaultValue = 64.0;

typedef struct FrameCache {
CGFloat x;
CGFloat width;
}FrameCache;

NS_ASSUME_NONNULL_BEGIN

Expand All @@ -18,30 +23,39 @@ NS_ASSUME_NONNULL_BEGIN

@end

@interface YUSegment ()
@interface YUSegment () {
FrameCache *cache;
}

@property (nonatomic, assign, getter = isTitleAsContent) BOOL titleAsContent;

/// @name Views

@property (nonatomic, strong) UIView *containerNormal;
@property (nonatomic, strong) UIView *containerSelected;

@property (nonatomic, strong) NSMutableArray <UILabel *> *labelsSelected;
@property (nonatomic, strong) NSMutableArray <UIImageView *> *imageViewsSelected;

@property (nonatomic, strong) NSMutableArray <NSString *> *internalTitles;
@property (nonatomic, strong) NSMutableArray <UIImage *> *internalImages;
@property (nonatomic, strong) NSMutableArray <UIImage *> *unselectImages;

@property (nonatomic, strong) NSMutableArray <UILabel *> *labelsSelected;
@property (nonatomic, strong) NSMutableArray <UIImageView *> *imageViewsSelected;
@property (nonatomic, strong) NSMutableArray <UILabel *> *labelsNormal;
@property (nonatomic, strong) NSMutableArray <UIImageView *> *imageViewsNormal;

@property (nonatomic, strong) NSMutableDictionary *textAttributesNormal;
@property (nonatomic, strong) NSMutableDictionary *textAttributesSelected;
@property (nonatomic, strong) NSMutableDictionary *textAttributesNormal;
@property (nonatomic, strong) NSMutableDictionary *textAttributesSelected;

@property (nonatomic, strong) NSMutableArray <NSLayoutConstraint *> *widthConstraints;

- (instancetype)initWithTitles:(NSArray <NSString *> *)titles;
- (instancetype)initWithImages:(NSArray <UIImage *> *)images unselectedImages:(nullable NSArray <UIImage *> *)unselectedImages;
- (void)makeContainerUsable;
- (void)addLabels;
- (void)addImageViews;
- (FrameCache)cacheAt:(NSUInteger)index;
- (void)setX:(CGFloat)x forCacheAt:(NSUInteger)index;
- (void)setWidth:(CGFloat)width forCacheAt:(NSUInteger)index;
- (void)makeSegmentCenterIfNeeded;

@end
Expand Down
2 changes: 0 additions & 2 deletions Classes/YUSegment.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,6 @@ NS_ASSUME_NONNULL_BEGIN
*/
@interface YUIndicatorView : UIView

@property (nonatomic, assign) CGSize size;

/**
Returns a block which accepts an argument as the value of `borderWidth`.
Expand Down
160 changes: 73 additions & 87 deletions Classes/YUSegment.m
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ - (instancetype)initWithTitles:(NSArray <NSString *> *)titles {
_internalTitles = [titles mutableCopy];
_numberOfSegments = [titles count];
_labelsNormal = [NSMutableArray array];
_titleAsContent = YES;
[self commonInit];
}
return self;
Expand All @@ -82,6 +83,7 @@ - (instancetype)initWithImages:(NSArray <UIImage *> *)images unselectedImages:(N
}
_numberOfSegments = [images count];
_imageViewsNormal = [NSMutableArray array];
_titleAsContent = NO;
[self commonInit];
}
return self;
Expand All @@ -91,17 +93,21 @@ - (void)commonInit {
// Set default values.
_scrollEnabled = NO;
_selectedIndex = 0;
_contentOffset = kEachSegmentDefaultMargin;
_contentOffset = kContentOffsetDefaultValue;
cache = malloc(sizeof(FrameCache) * _numberOfSegments);

// Setup views.
self.backgroundColor = [UIColor whiteColor];
_containerNormal = [self setupContainer];
_indicator = ({
YUIndicatorView *indicator = [[YUIndicatorView alloc] init];
[self addSubview:indicator];

indicator;
});

// Setup gesture
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tap:)];
[self addGestureRecognizer:tap];
}

#pragma mark - Managing Segment Content
Expand Down Expand Up @@ -136,73 +142,6 @@ - (UIImage *)imageForSegmentAtIndex:(NSUInteger)index {
// Subclasses override this.
}

//- (void)addSegmentWithTitle:(NSString *)title {
// [self insertSegmentWithTitle:title atIndex:_numberOfSegments];
//}
//
//- (void)addSegmentWithImage:(UIImage *)image {
// [self insertSegmentWithImage:image atIndex:_numberOfSegments];
//}
//
//- (void)addSegmentWithTitle:(NSString *)title forImage:(UIImage *)image {
// [self insertSegmentWithTitle:title forImage:image atIndex:_numberOfSegments];
//}
//
//- (void)insertSegmentWithTitle:(NSString *)title atIndex:(NSUInteger)index {
// NSAssert(_internalTitles, @"You should use this method when the content of segment is `NSString` objcet.");
// if (index > _numberOfSegments) {
// index = _numberOfSegments;
// }
// [self.internalTitles insertObject:title atIndex:index];
// _numberOfSegments++;
// [self insertViewWithTitle:title atIndex:index];
//}
//
//- (void)insertSegmentWithImage:(UIImage *)image atIndex:(NSUInteger)index {
// NSAssert(_internalImages, @"You should use this method when the content of segment is `UIImage` objcet.");
// if (index > _numberOfSegments) {
// index = _numberOfSegments;
// }
// [self.internalImages insertObject:image atIndex:index];
// _numberOfSegments++;
// [self insertViewWithImage:image atIndex:index];
//}
//
//- (void)insertSegmentWithTitle:(NSString *)title forImage:(UIImage *)image atIndex:(NSUInteger)index {
// NSAssert(_internalTitles && _internalImages, @"You should use this method when the content of the segment including `NSString` object and `UIImage` object.");
// if (index > _numberOfSegments) {
// index = _numberOfSegments;
// }
// [self.internalTitles insertObject:title atIndex:index];
// [self.internalImages insertObject:image atIndex:index];
// _numberOfSegments++;
// [self insertViewWithTitle:title forImage:image atIndex:index];
//}
//
//- (void)insertViewWithTitle:(NSString *)title atIndex:(NSUInteger)index {
//
//}
//
//- (void)insertViewWithImage:(UIImage *)image atIndex:(NSUInteger)index {
//
//}
//
//- (void)insertViewWithTitle:(NSString *)title forImage:(UIImage *)image atIndex:(NSUInteger)index {
//
//}
//
//- (void)removeAllItems {
//
//}
//
//- (void)removeLastItem {
// [self removeItemAtIndex:_numberOfSegments - 1];
//}
//
//- (void)removeItemAtIndex:(NSUInteger)index {
//
//}

#pragma mark - Views Setup

- (void)makeContainerUsable {
Expand Down Expand Up @@ -242,6 +181,7 @@ - (void)addLabels {
label = [self setupNormalLabelWithTitle:_internalTitles[i]];
[_labelsNormal addObject:label];
[_containerNormal addSubview:label];
cache[i].width = label.intrinsicContentSize.width;
}
[self layoutSubviewsInContainer:_containerNormal];

Expand Down Expand Up @@ -271,6 +211,7 @@ - (void)addImageViews {
imageView = [self setupImageViewWithImage:images[i]];
[_imageViewsNormal addObject:imageView];
[_containerNormal addSubview:imageView];
cache[i].width = imageView.intrinsicContentSize.width;
}
[self layoutSubviewsInContainer:_containerNormal];

Expand Down Expand Up @@ -307,6 +248,7 @@ - (void)updateViewHierarchy {
[_scrollView addSubview:_indicator];

if (_containerSelected) {
[_containerSelected removeFromSuperview];
[_scrollView addSubview:_containerSelected];
[self setupConstraintsToScrollViewWithItem:_containerSelected];
[self resetWidthConstraintsForSubviewsInContainer:_containerSelected];
Expand Down Expand Up @@ -378,8 +320,37 @@ - (NSDictionary *)textAttributesForState:(YUSegmentedControlState)state {
};
}

#pragma mark - Event Response

- (void)tap:(UITapGestureRecognizer *)gestureRecognizer {
CGPoint location = [gestureRecognizer locationInView:_containerNormal];
UIView *hitView = [_containerNormal hitTest:location withEvent:nil];
NSUInteger toIndex = [_containerNormal.subviews indexOfObject:hitView];
if (toIndex != NSNotFound) {
if (_selectedIndex != toIndex) {
[self moveIndicatorFromIndex:_selectedIndex toIndex:toIndex];
}
}
}

- (void)moveIndicatorFromIndex:(NSUInteger)fromIndex toIndex:(NSUInteger)toIndex {
// subclasses implement this.
}

#pragma mark -

- (FrameCache)cacheAt:(NSUInteger)index {
return cache[index];
}

- (void)setX:(CGFloat)x forCacheAt:(NSUInteger)index {
cache[index].x = x;
}

- (void)setWidth:(CGFloat)width forCacheAt:(NSUInteger)index {
cache[index].width = width;
}

- (void)makeSegmentCenterIfNeeded {
// CGFloat finalOffset = self.segmentWidth * (_selectedIndex + 0.5) - CGRectGetWidth(self.frame) / 2;
// CGFloat maxOffset = _scrollView.contentSize.width - CGRectGetWidth(self.frame);
Expand All @@ -403,6 +374,15 @@ - (void)makeSegmentCenterIfNeeded {
- (void)setScrollEnabled:(BOOL)scrollEnabled {
_scrollEnabled = scrollEnabled;
if (scrollEnabled) {
// configure frame cache
CGFloat constant = kContentOffsetDefaultValue;
CGFloat x = 0.0;
for (int i = 0; i < _numberOfSegments; i++) {
cache[i].width += constant;
cache[i].x = x;
x += cache[i].width;
}
// update view hierarchy
[self updateViewHierarchy];
}
}
Expand All @@ -425,6 +405,14 @@ - (void)setContentOffset:(CGFloat)contentOffset {
return [_internalImages copy];
}

- (NSMutableArray <NSLayoutConstraint *> *)widthConstraints {
if (_widthConstraints) {
return _widthConstraints;
}
_widthConstraints = [NSMutableArray array];
return _widthConstraints;
}

#pragma mark - Constraints

+ (BOOL)requiresConstraintBasedLayout {
Expand All @@ -438,24 +426,18 @@ - (void)layoutSubviewsInContainer:(UIView *)container {
[NSLayoutConstraint constraintWithItem:subviews[i] attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:container attribute:NSLayoutAttributeCenterY multiplier:1.0 constant:0.0].active = YES;

if (lastView) {
NSLayoutConstraint *offset = [NSLayoutConstraint constraintWithItem:subviews[i] attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:lastView attribute:NSLayoutAttributeTrailing multiplier:1.0 constant:0.0];
offset.active = YES;
offset.identifier = @"o";
[NSLayoutConstraint constraintWithItem:subviews[i] attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:lastView attribute:NSLayoutAttributeTrailing multiplier:1.0 constant:0.0].active = YES;

NSLayoutConstraint *width = [NSLayoutConstraint constraintWithItem:subviews[i] attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:lastView attribute:NSLayoutAttributeWidth multiplier:1.0 constant:0.0];
width.active = YES;
width.identifier = @"w";
}
else {
NSLayoutConstraint *edge = [NSLayoutConstraint constraintWithItem:subviews[i] attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:container attribute:NSLayoutAttributeLeading multiplier:1.0 constant:0.0];
edge.active = YES;
edge.identifier = @"e";
[NSLayoutConstraint constraintWithItem:subviews[i] attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:container attribute:NSLayoutAttributeLeading multiplier:1.0 constant:0.0].active = YES;
}
lastView = subviews[i];
}
NSLayoutConstraint *edge = [NSLayoutConstraint constraintWithItem:container attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:lastView attribute:NSLayoutAttributeTrailing multiplier:1.0 constant:0.0];
edge.active = YES;
edge.identifier = @"e";
[NSLayoutConstraint constraintWithItem:container attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:lastView attribute:NSLayoutAttributeTrailing multiplier:1.0 constant:0.0].active = YES;
}

- (void)setupConstraintsWithItem:(id)item1 toItem:(id)item2 {
Expand All @@ -478,12 +460,13 @@ - (void)resetWidthConstraintsForSubviewsInContainer:(UIView *)container {
if ([constraint.identifier isEqualToString:@"w"]) {
constraint.active = NO;
}
if ([constraint.identifier isEqualToString:@"o"]) {
constraint.constant = _contentOffset * 2.0;
}
if ([constraint.identifier isEqualToString:@"e"]) {
constraint.constant = _contentOffset;
}
}
NSArray <UIView *> *subviews = container.subviews;
NSMutableArray *widthConstraints = self.widthConstraints;
for (int i = 0; i < _numberOfSegments; i++) {
NSLayoutConstraint *width = [NSLayoutConstraint constraintWithItem:subviews[i] attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:cache[i].width];
width.active = YES;
[widthConstraints addObject:width];
}
}

Expand Down Expand Up @@ -536,10 +519,13 @@ - (void)setCenterX:(CGFloat)centerX {
};
}

#pragma mark - Getters
#pragma mark - Setters

- (CGSize)size {
return _size;
- (void)setFrame:(CGRect)frame {
[super setFrame:frame];
if (self.maskView) {
self.maskView.frame = frame;
}
}

@end
Loading

0 comments on commit 69587f2

Please sign in to comment.