404 lines
14 KiB
Objective-C
404 lines
14 KiB
Objective-C
//
|
|
// LXCustomSwith.m
|
|
// CustomUISwitch
|
|
//
|
|
// Created by lianxiang on 2018/9/7.
|
|
// Copyright © 2018年 GIGA. All rights reserved.
|
|
//
|
|
|
|
#import "LXCustomSwith.h"
|
|
#import <QuartzCore/QuartzCore.h>
|
|
#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
|