// // LXCustomSwith.m // CustomUISwitch // // Created by lianxiang on 2018/9/7. // Copyright © 2018年 GIGA. All rights reserved. // #import "LXCustomSwith.h" #import #define VW(view) (view.frame.size.width) #define VH(view) (view.frame.size.height) static const CGFloat kAnimateDuration = 0.3f; static const CGFloat kHorizontalAdjustment = 3.0f; static const CGFloat kThumbShadowOpacity = 0.3f; static const CGFloat kThumbShadowRadius = 0.5f; static const CGFloat kSwitchBorderWidth = 1.75f; @interface LXCustomSwith() @property (nonatomic, strong) UIView *onBackgroundView; @property (nonatomic, strong) UIView *offBackgroundView; @property (nonatomic, strong) UIView *thumbView; @end @implementation LXCustomSwith @synthesize onBackgroundView = _onBackgroundView; @synthesize offBackgroundView = _offBackgroundView; @synthesize thumbView = _thumbView; @synthesize on = _on; @synthesize shape = _shape; @synthesize onTintColor = _onTintColor; @synthesize tintColor = _tintColor; @synthesize thumbTintColor = _thumbTintColor; @synthesize shadow = _shadow; @synthesize onTintBorderColor = _onTintBorderColor; @synthesize tintBorderColor = _tintBorderColor; @synthesize onBackLabel = _onBackLabel; @synthesize offBackLabel = _offBackLabel; @synthesize offthumTitle = _offthumTitle; @synthesize onthumTitle = _onthumTitle; - (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { // Initialization code [self setupUI]; } return self; } - (instancetype)initWithCoder:(NSCoder *)aDecoder{ if (self = [super initWithCoder:aDecoder]) { [self setupUI]; } return self; } - (void)setupUI { self.shape = LXCustomSwithShapeNormal; self.onBackgroundView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)]; //打开背景 [self.onBackgroundView.layer setCornerRadius:self.frame.size.height/2]; [self.onBackgroundView.layer setShouldRasterize:YES]; [self.onBackgroundView.layer setRasterizationScale:[UIScreen mainScreen].scale]; self.onBackgroundView.backgroundColor = [UIColor redColor]; [self addSubview:self.onBackgroundView]; // 关闭 self.offBackgroundView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)]; [self.offBackgroundView setBackgroundColor:[UIColor whiteColor]]; [self.offBackgroundView.layer setCornerRadius:self.frame.size.height/2]; [self.offBackgroundView.layer setShouldRasterize:YES]; [self.offBackgroundView.layer setRasterizationScale:[UIScreen mainScreen].scale]; [self addSubview:self.offBackgroundView]; self.thumbView = [[UIView alloc] init]; [self.thumbView setUserInteractionEnabled:YES]; [self.thumbView.layer setCornerRadius:(self.frame.size.height-kHorizontalAdjustment)/2]; [self.thumbView.layer setShadowOffset:CGSizeMake(0, 1)]; [self.thumbView.layer setShouldRasterize:YES]; [self.thumbView.layer setShadowOpacity:kThumbShadowOpacity]; [self.thumbView.layer setRasterizationScale:[UIScreen mainScreen].scale]; self.thumbView.backgroundColor = [UIColor greenColor]; [self addSubview:self.thumbView]; self.thumbLabel = [[UILabel alloc] init]; self.thumbLabel.frame = CGRectMake(kHorizontalAdjustment, 0, self.frame.size.width, self.frame.size.height); self.offthumTitle = @"关闭"; self.thumbLabel.text = self.offthumTitle; [self.thumbLabel sizeToFit]; self.shadow = YES; self.thumbView.frame = CGRectMake(0,0, self.thumbLabel.frame.size.width + self.frame.size.height, self.frame.size.height); self.thumbLabel.center = self.thumbView.center; [self.thumbView addSubview:self.thumbLabel]; // Default to OFF position [self.thumbView setCenter:CGPointMake(self.thumbView.frame.size.width/2, self.frame.size.height/2)]; // Handle Thumb Tap Gesture UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleSwitchTap:)]; [tapGestureRecognizer setDelegate:self]; [self.thumbView addGestureRecognizer:tapGestureRecognizer]; // Handle Background Tap Gesture UITapGestureRecognizer *tapBgGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleBgTap:)]; [tapBgGestureRecognizer setDelegate:self]; [self addGestureRecognizer:tapBgGestureRecognizer]; // Handle Thumb Pan Gesture UIPanGestureRecognizer *panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePan:)]; [panGestureRecognizer setDelegate:self]; [self.thumbView addGestureRecognizer:panGestureRecognizer]; [self setOn:NO]; } - (void)layoutSubviews{ [super layoutSubviews]; [self updateFrame]; } -(void)updateFrame{ self.thumbLabel.frame = CGRectMake(kHorizontalAdjustment, 0, self.frame.size.width, self.frame.size.height); [self.thumbLabel sizeToFit]; self.thumbView.frame = CGRectMake(0,0, self.thumbLabel.frame.size.width + self.frame.size.height - 10, self.frame.size.height); self.thumbLabel.center = self.thumbView.center; } - (BOOL)isOn { return _on; } - (void)setOn:(BOOL)on { if (_on != on) _on = on; if (_on) { [self.onBackgroundView setAlpha:1.0]; self.offBackgroundView.transform = CGAffineTransformMakeScale(0.0, 0.0); self.thumbView.center = CGPointMake(self.onBackgroundView.frame.size.width - (self.thumbView.frame.size.width+kHorizontalAdjustment)/2, self.thumbView.center.y); self.thumbLabel.text = self.onthumTitle; } else { [self.onBackgroundView setAlpha:0.0]; self.offBackgroundView.transform = CGAffineTransformMakeScale(1.0, 1.0); self.thumbView.center = CGPointMake((self.thumbView.frame.size.width+kHorizontalAdjustment)/2, self.thumbView.center.y); self.thumbLabel.text = self.offthumTitle; } } - (void)setShadow:(BOOL)showShadow { if (_shadow != showShadow) _shadow = showShadow; if (showShadow) { [self.thumbView.layer setShadowOffset:CGSizeMake(0, 1)]; [self.thumbView.layer setShadowRadius:kThumbShadowRadius]; [self.thumbView.layer setShadowOpacity:kThumbShadowOpacity]; } else { [self.thumbView.layer setShadowRadius:0.0]; [self.thumbView.layer setShadowOpacity:0.0]; } } - (void)setOnTintColor:(UIColor *)color { if (_onTintColor != color) _onTintColor = color; [self.onBackgroundView setBackgroundColor:color]; } - (void)setOnTintBorderColor:(UIColor *)color { if (_onTintBorderColor != color) _onTintBorderColor = color; [self.onBackgroundView.layer setBorderColor:color.CGColor]; if (color) [self.onBackgroundView.layer setBorderWidth:kSwitchBorderWidth]; else [self.onBackgroundView.layer setBorderWidth:0.0]; } - (void)setTintColor:(UIColor *)color { if (_tintColor != color) _tintColor = color; [self.offBackgroundView setBackgroundColor:color]; } - (void)setTintBorderColor:(UIColor *)color { if (_tintBorderColor != color) _tintBorderColor = color; [self.offBackgroundView.layer setBorderColor:color.CGColor]; if (color) [self.offBackgroundView.layer setBorderWidth:kSwitchBorderWidth]; else [self.offBackgroundView.layer setBorderWidth:0.0]; } - (void)setThumbTintColor:(UIColor *)color { if (_thumbTintColor != color) _thumbTintColor = color; [self.thumbView setBackgroundColor:color]; } - (void)setOnthumTitle:(NSString *)onthumTitle{ _onthumTitle = onthumTitle; } - (void)setOffthumTitle:(NSString *)offthumTitle{ _offthumTitle = offthumTitle; self.thumbLabel.text = self.offthumTitle; } #pragma mark - Animation - (void)animateToDestination:(CGPoint)centerPoint withDuration:(CGFloat)duration switch:(BOOL)on { [UIView animateWithDuration:duration delay:0.0f options:UIViewAnimationOptionCurveEaseOut animations:^{ self.thumbView.center = centerPoint; if (on) { [self.onBackgroundView setAlpha:1.0]; } else { [self.onBackgroundView setAlpha:0.0]; } } completion:^(BOOL finished) { if (finished) { [self updateSwitch:on]; } }]; [UIView animateWithDuration:duration delay:0.0f options:UIViewAnimationOptionCurveEaseOut animations:^{ if (on) { //打开方式:加动画 // self.offBackgroundView.transform = CGAffineTransformMakeScale(0.0, 0.0); [self.offBackgroundView setAlpha:0.0]; } else { // self.offBackgroundView.transform = CGAffineTransformMakeScale(1.0, 1.0); [self.offBackgroundView setAlpha:1.0]; } } completion:^(BOOL finished) { }]; } #pragma mark - Gesture Recognizers - (void)handlePan:(UIPanGestureRecognizer *)recognizer { CGPoint translation = [recognizer translationInView:self.thumbView]; // Check the new center to see if within the boud CGPoint newCenter = CGPointMake(recognizer.view.center.x + translation.x, recognizer.view.center.y); if (newCenter.x < (recognizer.view.frame.size.width+kHorizontalAdjustment)/2 || newCenter.x > self.onBackgroundView.frame.size.width-(recognizer.view.frame.size.width+kHorizontalAdjustment)/2) { // New center is Out of bound. Animate to left or right position if(recognizer.state == UIGestureRecognizerStateBegan || recognizer.state == UIGestureRecognizerStateChanged) { CGPoint velocity = [recognizer velocityInView:self.thumbView]; if (velocity.x >= 0) { // Animate move to right [self animateToDestination:CGPointMake(self.onBackgroundView.frame.size.width - (self.thumbView.frame.size.width+kHorizontalAdjustment)/2, recognizer.view.center.y) withDuration:kAnimateDuration switch:YES]; } else { // Animate move to left [self animateToDestination:CGPointMake((self.thumbView.frame.size.width+kHorizontalAdjustment)/2, recognizer.view.center.y) withDuration:kAnimateDuration switch:NO]; } } return; } // Only allow vertical pan recognizer.view.center = CGPointMake(recognizer.view.center.x + translation.x, recognizer.view.center.y); [recognizer setTranslation:CGPointMake(0, 0) inView:self.thumbView]; CGPoint velocity = [recognizer velocityInView:self.thumbView]; if(recognizer.state == UIGestureRecognizerStateEnded) { if (velocity.x >= 0) { if (recognizer.view.center.x < self.onBackgroundView.frame.size.width - (self.thumbView.frame.size.width+kHorizontalAdjustment)/2) { // Animate move to right [self animateToDestination:CGPointMake(self.onBackgroundView.frame.size.width - (self.thumbView.frame.size.width+kHorizontalAdjustment)/2, recognizer.view.center.y) withDuration:kAnimateDuration switch:YES]; } } else { // Animate move to left [self animateToDestination:CGPointMake((self.thumbView.frame.size.width+kHorizontalAdjustment)/2, recognizer.view.center.y) withDuration:kAnimateDuration switch:NO]; } } } - (void)handleSwitchTap:(UIPanGestureRecognizer *)recognizer { if (recognizer.state == UIGestureRecognizerStateEnded) { if (self.isOn) { // Animate move to left [self animateToDestination:CGPointMake((self.thumbView.frame.size.width+kHorizontalAdjustment)/2, recognizer.view.center.y) withDuration:kAnimateDuration switch:NO]; } else { // Animate move to right [self animateToDestination:CGPointMake(self.onBackgroundView.frame.size.width - (self.thumbView.frame.size.width+kHorizontalAdjustment)/2, recognizer.view.center.y) withDuration:kAnimateDuration switch:YES]; } } } - (void)handleBgTap:(UITapGestureRecognizer *)recognizer { if (recognizer.state == UIGestureRecognizerStateEnded) { if (self.isOn) { // Animate move to left [self animateToDestination:CGPointMake((self.thumbView.frame.size.width+kHorizontalAdjustment)/2, self.thumbView.center.y) withDuration:kAnimateDuration switch:NO]; } else { // Animate move to right [self animateToDestination:CGPointMake(self.onBackgroundView.frame.size.width - (self.thumbView.frame.size.width+kHorizontalAdjustment)/2, self.thumbView.center.y) withDuration:kAnimateDuration switch:YES]; } } } - (void)updateSwitch:(BOOL)on { if (_on != on) _on = on; if (_on) { self.thumbLabel.text = self.onthumTitle; }else{ self.thumbLabel.text = self.offthumTitle; } [self sendActionsForControlEvents:UIControlEventValueChanged]; } @end