UIControl侧重于事件交互,最大的特点是拥有addTarget:action:forControlEvents方法
自定义控件
实现效果如果:
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
#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