UIControl详解

UIControl的继承关系:
UIView(控件的祖先) ---> UIControl ----> UIButton


UIControl 的重要方法:
- (void)addTarget:(nullable id)target action:(SEL)action forControlEvents:(UIControlEvents)controlEvents;


UIView 的重要方法:
- (void)addSubview:(UIView *)view;


UIControl的作用:
1.UIControl作为UIButton的父类,所以具有UIButton一样的事件响应机制(用于事件响应)
2.UIControl作为UIView的子类,具有作为容器视图的潜质(用于页面布局)


UIControl和UIView的区别:
UIView侧重于页面布局,因addTarget:action:forControlEvents是在UIControl中定义的,它的父类UIView中没有,所以没有事件交互的方法
可以通过手势UITapGestureRecognizer来实现

UIControl侧重于事件交互,最大的特点是拥有addTarget:action:forControlEvents方法


自定义控件

实现效果如果:

UIControl详解_第1张图片

1.SegmentControl

#import <UIKit/UIKit.h>

enum SelectionIndicatorMode {
    SelectionIndicatorResozesToStringWidth = 0,
};


@interface SegmentControl : UIControl

@property (strong, nonatomic)       NSArray *sectionTitles;
@property (strong, nonatomic)       UIFont  *font;
@property (strong, nonatomic)       UIColor *textColor;
@property (strong, nonatomic)       UIColor *selectionIndicatorColor;
@property (nonatomic, readwrite)    CGFloat height;
@property (nonatomic, readwrite)    CGFloat selectionIndicatorHeight;
@property (strong, nonatomic)       UIColor *backgroundColor;
@property (assign, nonatomic)       NSInteger selectedIndex;
@property (nonatomic, readwrite)    UIEdgeInsets segmentEdgeInset;
@property (nonatomic, strong)       CALayer *selectedSegmentLayer;
@property (nonatomic, readwrite)    CGFloat segmentWidth;
@property (nonatomic, copy)         void(^indexChangeBlock)(NSUInteger index);
@property (assign, nonatomic)       enum SelectionIndicatorMode selectionIndicatorMode;

- (id)initWithSectionTitles:(NSArray *)sectionTitles;

@end

#import "SegmentControl.h"

@implementation SegmentControl

- (id)initWithFrame:(CGRect)frame {
    if (self = [super initWithFrame:frame]) {
        [self _initDefaults];
    }
    
    return self;
}


- (id) initWithSectionTitles:(NSArray *)sectionTitles {
    if (self = [super initWithFrame:CGRectZero]) {
        self.sectionTitles = sectionTitles;
        [self _initDefaults];
    }
    
    return self;
}


- (void)setFrame:(CGRect)frame {
    [super setFrame:frame];
    if (self.sectionTitles) {
        [self _updateSegmentRects];
    }
    
    [self setNeedsDisplay];
}

// 初始化默认值
- (void)_initDefaults {
    self.font = [UIFont fontWithName:@"STHeitiSC-Light" size:18.0f];
    self.textColor = [UIColor blackColor];
    self.backgroundColor = [UIColor whiteColor];
    self.selectionIndicatorColor = [UIColor colorWithRed:52.0f/255.0f green:181.0f/255.0f blue:229.0f/255.0f alpha:1.0f];
    self.selectedIndex = 0;
    self.height = 60.0f;
    self.selectionIndicatorHeight = 5.0f;
    self.selectionIndicatorMode = SelectionIndicatorResozesToStringWidth;
    self.selectedSegmentLayer = [CALayer layer];
}


- (void)drawRect:(CGRect)rect {
    [self.backgroundColor set];
    UIRectFill([self bounds]);
    
    [self.textColor set];
    [self.sectionTitles enumerateObjectsUsingBlock:^(id  _Nonnull titleString, NSUInteger idx, BOOL * _Nonnull stop) {
        CGFloat stringHeight = [titleString sizeWithFont:self.font].height;
        CGFloat y = ((self.height - self.selectionIndicatorHeight) / 2) + (self.selectionIndicatorHeight - stringHeight /2);
        CGRect rect = CGRectMake(self.segmentWidth * idx, y, self.segmentWidth, stringHeight);
        
        NSMutableParagraphStyle *style = [[NSMutableParagraphStyle defaultParagraphStyle] mutableCopy];
        [style setLineBreakMode:NSLineBreakByClipping];
        [style setAlignment:NSTextAlignmentCenter];
        NSDictionary *dis = [[NSDictionary alloc] initWithObjectsAndKeys:style,NSParagraphStyleAttributeName,self.font, NSFontAttributeName, nil];
    
        [titleString drawInRect:rect withAttributes:dis];
        self.selectedSegmentLayer.frame = [self frameForSelectionIndicator];
        self.selectedSegmentLayer.backgroundColor = self.selectionIndicatorColor.CGColor;
        [self.layer addSublayer:self.selectedSegmentLayer];
        
    }];
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    UITouch *touch = [[event allTouches] anyObject];
    CGPoint touchLocation = [touch locationInView:self];
    
    if (CGRectContainsPoint(self.bounds, touchLocation)) {
        NSInteger segment = touchLocation.x / self.segmentWidth;
        if (segment != self.selectedIndex) {
            [self setSelectedIndex:segment animated:YES];
        }
    }
    
}

- (CGRect)frameForSelectionIndicator {
    CGFloat stringWidth = [[self.sectionTitles objectAtIndex:self.selectedIndex] sizeWithFont:self.font].width;
    CGFloat widthTillEndOfSelectedIndex = (self.segmentWidth * self.selectedIndex) + self.segmentWidth;
    CGFloat widthTillBeforeSelectedIndex = (self.segmentWidth * self.selectedIndex);
    
    CGFloat x = ((widthTillEndOfSelectedIndex - widthTillBeforeSelectedIndex) / 2) + (widthTillBeforeSelectedIndex - stringWidth /2);
    return CGRectMake(x, 0.0, stringWidth, self.selectionIndicatorHeight);
}

- (void) _updateSegmentRects {
    self.segmentWidth = self.frame.size.width / self.sectionTitles.count;
    self.height = self.frame.size.height;
}


- (void)setSelectedIndex:(NSInteger)selectedIndex {
    [self setSelectedIndex:selectedIndex animated:NO];
}

- (void)setSelectedIndex:(NSInteger)index animated:(BOOL)animated {
    _selectedIndex = index;
    if (animated) {
        self.selectedSegmentLayer.actions = nil;
        [CATransaction begin];
        [CATransaction setAnimationDuration:0.15f];
        [CATransaction setCompletionBlock:^{
            if (self.superview) {
                [self sendActionsForControlEvents:UIControlEventValueChanged];
            }
            
            if (self.indexChangeBlock) {
                self.indexChangeBlock(index);
            }
        }];
        self.selectedSegmentLayer.frame = [self frameForSelectionIndicator];
        [CATransaction commit];
    } else {
        NSMutableDictionary *newsActions = [[NSMutableDictionary alloc] initWithObjectsAndKeys:[NSNull null], @"position", [NSNull null], @"bounds", nil];
        self.selectedSegmentLayer.actions = newsActions;
        self.selectedSegmentLayer.frame = [self frameForSelectionIndicator];
        if (self.superview) {
            [self sendActionsForControlEvents:UIControlEventValueChanged];
        }
        if (self.indexChangeBlock) {
            self.indexChangeBlock(index);
        }
    }
}
@end

2.ViewController

#import "ViewController.h"
#import "SegmentControl.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    SegmentControl *segment = [[SegmentControl alloc] initWithSectionTitles:@[@"电视剧", @"娱乐", @"新闻头条"]];
    [segment setFrame:CGRectMake(10, 30, 300, 60)];
    [segment addTarget:self action:@selector(tab:) forControlEvents:UIControlEventValueChanged];
    
    [segment setTextColor:[UIColor blueColor]];
    [segment setSelectionIndicatorColor:[UIColor redColor]];
    [segment setSelectionIndicatorHeight:3.0f];
    segment.height = 30;
    
    [self.view addSubview:segment];
}

- (void) tab:(SegmentControl *)segment {
    NSLog(@"%ld", segment.selectedIndex);
}
@end

你可能感兴趣的:(UIControl详解)