iOS-CAShapeLayer实战

iOS-CAShapeLayer实战_第1张图片
login.gif

源代码

项目的小动画基于CAShapeLayer与CABasicAnimation。

将界面分为三个模块介绍

  • 渐变的背景色
    利用CAGradientLayer实现渐变背景色
    CAGradientLayer *gradientLayer = [CAGradientLayer layer];
    gradientLayer.frame  = self.view.bounds;
    gradientLayer.colors = @[
                             (__bridge id)[UIColor purpleColor].CGColor,
                             (__bridge id)[UIColor redColor].CGColor,
                             (__bridge id)[UIColor blueColor].CGColor
                             ];
    gradientLayer.startPoint = CGPointMake(0.5, 0);
    gradientLayer.endPoint   = CGPointMake(0.5, 1);
    gradientLayer.locations  = @[@0.3,@0.7,@1];
    [self.view.layer addSublayer:gradientLayer];

  • 带动画的textfield
    监听文字长度的变化,利用animateWithDuration改变位置。

#import 

@interface ICETextField : UIView

@property (nonatomic, strong) NSString *strPlaceHolder;
@property (nonatomic, strong) UITextField *tfdICE;

@end
//
//  ICETextField.m
//  ICELogin
//
//  Created by iOS on 1/4/17.
//  Copyright © 2017年 iOS. All rights reserved.
//

#import "ICETextField.h"
@interface ICETextField ()
<
 UITextFieldDelegate
>
@property (nonatomic, strong) UILabel *lblPlaceHolder;
@property (nonatomic, assign) BOOL isUp;//yes表示placeholder在tfd上面
@end
@implementation ICETextField

- (instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        self.isUp = NO;
        [self createView];
    }
    return self;
}

- (void)setStrPlaceHolder:(NSString *)strPlaceHolder {
    _strPlaceHolder = strPlaceHolder;
    self.lblPlaceHolder.text = strPlaceHolder;
}

- (UITextField *)tfdICE {
    if (!_tfdICE) {
        _tfdICE = [[UITextField alloc]initWithFrame:CGRectZero];
        _tfdICE.delegate = self;
        [self addSubview:_tfdICE];
    }
    return _tfdICE;
}

- (UILabel *)lblPlaceHolder {
    if (!_lblPlaceHolder) {
        self.lblPlaceHolder           = [[UILabel alloc]init];
        self.lblPlaceHolder.textColor = [UIColor grayColor];
        self.lblPlaceHolder.font = [UIFont systemFontOfSize:15];
        _lblPlaceHolder.text = self.strPlaceHolder;
        [self addSubview:self.lblPlaceHolder];
    }
    return _lblPlaceHolder;
}

- (void)createView {
    [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(p_TextFieldLengthChange:) name:UITextFieldTextDidChangeNotification object:self.tfdICE];
    [self.lblPlaceHolder class];
    
    UIView *view = [[UIView alloc]initWithFrame:CGRectMake(0, CGRectGetHeight(self.frame)-1, CGRectGetWidth(self.frame), 1)];
    view.backgroundColor = [UIColor whiteColor];
    [self addSubview:view];
}


-(void)layoutSubviews {
    [super layoutSubviews];
    self.tfdICE.frame = CGRectMake(0, 0, CGRectGetWidth(self.frame), CGRectGetHeight(self.frame)-1);
    self.lblPlaceHolder.frame = CGRectMake(0, 0, CGRectGetWidth(self.frame), CGRectGetHeight(self.frame)-1);
}

/**
 监听tfd长度改变

 @param sender sender
 */
- (void)p_TextFieldLengthChange:(UITextField *)sender {
    [self p_movelblAnimation];
}


- (void)p_movelblAnimation {
    if (_tfdICE.text.length == 0 && _isUp) {
        //下移动
        [self p_ChangeFrameWithBool:YES];
    }
    else if (_tfdICE.text.length != 0 && !_isUp) {
        //上移动
        [self p_ChangeFrameWithBool:NO];
    }
}

- (void)p_ChangeFrameWithBool:(BOOL)isTurnDown {
    NSLog(@"%@",NSStringFromCGPoint(self.lblPlaceHolder.center));
    
    typeof(self) __weak weakSelf=self;
    if (isTurnDown) {
        //下移动
        [UIView animateWithDuration:0.2 animations:^{
            CGPoint point = weakSelf.lblPlaceHolder.center;
            point.y = point.y + 20;
            weakSelf.lblPlaceHolder.center = point;
            weakSelf.isUp = NO;
        }];
    }
    else {
        //上移动
        [UIView animateWithDuration:0.2 animations:^{
            CGPoint point = weakSelf.lblPlaceHolder.center;
            point.y = point.y - 20;
            weakSelf.lblPlaceHolder.center = point;
            weakSelf.isUp = YES;
        }];
    }
    NSLog(@"%@",NSStringFromCGPoint(self.lblPlaceHolder.center));
}

@end

  • 按钮的动画效果
#import 
typedef void(^ICEBlock)();

@interface ICEButton : UIButton

@property (nonatomic,copy) ICEBlock translateBlock;

@end
//
//  ICEButton.m
//  ICELogin
//
//  Created by iOS on 1/4/17.
//  Copyright © 2017年 iOS. All rights reserved.
//

#import "ICEButton.h"
@interface ICEButton ()

@property (nonatomic, strong) UIButton *button;

//拉升透明的masklayer
@property (nonatomic,strong) CAShapeLayer *maskLayer;

//view底层的椭圆边框
@property (nonatomic,strong) CAShapeLayer *shapeLayer;

//loading layer
@property (nonatomic,strong) CAShapeLayer *loadingLayer;

//点击按钮后的layer
@property (nonatomic,strong) CAShapeLayer *clickCicrleLayer;


@end

@implementation ICEButton
- (instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        [self drawMask:frame.size.height/2];
        
        [self.layer addSublayer:self.maskLayer];
        
        [self createDefaultBtn];
    }
    return self;
}


/**
 画椭圆边框
 
 @param height 高度
 */
- (void)drawMask:(CGFloat)height {
    _shapeLayer             = [CAShapeLayer layer];
    _shapeLayer.frame       = self.bounds;
    _shapeLayer.path        = [self drawBezierPath:height].CGPath;
    _shapeLayer.fillColor   = [UIColor clearColor].CGColor;
    _shapeLayer.strokeColor = [UIColor whiteColor].CGColor;
    _shapeLayer.lineWidth   = 2;
    [self.layer addSublayer:_shapeLayer];
}

/**
 创建按钮
 */
- (void) createDefaultBtn{
    _button                 = [UIButton buttonWithType:UIButtonTypeCustom];
    _button.frame           = self.bounds;
    _button.titleLabel.font = [UIFont systemFontOfSize:13.f];

    [_button setTitle:@"登陆"
             forState:UIControlStateNormal];
    [_button setTitleColor:[UIColor whiteColor]
                  forState:UIControlStateNormal];
    [self addSubview:_button];
    [_button addTarget:self
                action:@selector(didPressedToClickBtn:)
      forControlEvents:UIControlEventTouchUpInside];
}


/**
 点击按钮触发事件

 @param sender sender
 */
- (void)didPressedToClickBtn:(UIButton *)sender {
    //将要出现的盖在button上的layer
    _maskLayer.opacity            = 0.5;
    CABasicAnimation *animation   = [CABasicAnimation animationWithKeyPath:@"path"];
    animation.duration            = 0.25;
    animation.toValue             = (__bridge id _Nullable)([self drawBezierPath:self.frame.size.height/2].CGPath);
    animation.fillMode            = kCAFillModeForwards;
    animation.removedOnCompletion = NO;
    [_maskLayer addAnimation:animation forKey:@"maskAnimation"];
    
    [self performSelector:@selector(dismissAnimation) withObject:self afterDelay:animation.duration+0.2];
}



//登录按钮合拢并消失(透明)
-(void)dismissAnimation{
    [self removeSubViews];
    
    CAAnimationGroup *animationGroup    = [CAAnimationGroup animation];
    CABasicAnimation *basicAnimation    = [CABasicAnimation animationWithKeyPath:@"path"];
    basicAnimation.duration             = 0.2;
    basicAnimation.toValue              = (__bridge id _Nullable)([self drawBezierPath:self.frame.size.width/2].CGPath);
    basicAnimation.removedOnCompletion  = NO;
    basicAnimation.fillMode             = kCAFillModeForwards;
    
    CABasicAnimation *basicAnimation1   = [CABasicAnimation animationWithKeyPath:@"opacity"];
    basicAnimation1.beginTime           = 0.10;
    basicAnimation1.duration            = 0.2;
    basicAnimation1.toValue             = @0;
    basicAnimation1.fillMode            = kCAFillModeForwards;
    basicAnimation1.removedOnCompletion = NO;
    animationGroup.removedOnCompletion  = NO;
    animationGroup.fillMode             = kCAFillModeForwards;
    animationGroup.animations           = @[
                                            basicAnimation,
                                            basicAnimation1
                                            ];
    animationGroup.duration             = basicAnimation1.beginTime + basicAnimation1.duration;
    [_shapeLayer addAnimation:animationGroup forKey:@"dismissAnimation"];
    
    [self performSelector:@selector(loadingAnimation) withObject:self afterDelay:animationGroup.duration];
}


//菊花
-(void)loadingAnimation{
    CGFloat radius            = self.bounds.size.height/2 - 3;
    UIBezierPath *bezierPath  = [UIBezierPath bezierPath];
    [bezierPath addArcWithCenter:CGPointMake(0,0) radius:radius startAngle:M_PI/2 endAngle:M_PI/2+M_PI/2 clockwise:YES];
    
    _loadingLayer             = [CAShapeLayer layer];
    _loadingLayer.position    = CGPointMake(self.bounds.size.width/2, self.bounds.size.height/2);
    _loadingLayer.fillColor   = [UIColor clearColor].CGColor;
    _loadingLayer.strokeColor = [UIColor whiteColor].CGColor;
    _loadingLayer.lineWidth   = 2;
    _loadingLayer.path        = bezierPath.CGPath;
    [self.layer addSublayer:_loadingLayer];
    
    
    CABasicAnimation *basicAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
    basicAnimation.fromValue         = @(0);
    basicAnimation.toValue           = @(M_PI*2);
    basicAnimation.duration          = 0.5;
    basicAnimation.repeatCount       = LONG_MAX;
    [_loadingLayer addAnimation:basicAnimation forKey:@"loadingAnimation"];
    
    [self performSelector:@selector(removeAllAnimation) withObject:self afterDelay:2];
}



//画一个位于view中间直径是view高的一个圆,透明度为0
-(CAShapeLayer *)maskLayer {
    if(!_maskLayer){
        _maskLayer           = [CAShapeLayer layer];
        _maskLayer.opacity   = 0;
        _maskLayer.fillColor = [UIColor whiteColor].CGColor;
        _maskLayer.path      = [self drawBezierPath:self.frame.size.width/2].CGPath;
    }
    return _maskLayer;
}


//
-(UIBezierPath *)drawBezierPath:(CGFloat)x{
    CGFloat radius = self.bounds.size.height/2 - 3;
    CGFloat right  = self.bounds.size.width-x;
    CGFloat left   = x;
    
    UIBezierPath *bezierPath = [UIBezierPath bezierPath];
    bezierPath.lineJoinStyle = kCGLineJoinRound;
    bezierPath.lineCapStyle  = kCGLineCapRound;
    //右边圆弧
    [bezierPath addArcWithCenter:CGPointMake(right, self.bounds.size.height/2) radius:radius startAngle:-M_PI/2 endAngle:M_PI/2 clockwise:YES];
    //左边圆弧
    [bezierPath addArcWithCenter:CGPointMake(left, self.bounds.size.height/2) radius:radius startAngle:M_PI/2 endAngle:-M_PI/2 clockwise:YES];
    //闭合弧线
    [bezierPath closePath];
    
    return bezierPath;
}

/**
 移除按钮 layer
 */
-(void)removeSubViews{
    [_button removeFromSuperview];
    [_maskLayer removeFromSuperlayer];
    [_loadingLayer removeFromSuperlayer];
    [_clickCicrleLayer removeFromSuperlayer];
}

-(void)removeAllAnimation{
    [self removeSubViews];
    if(self.translateBlock){
        self.translateBlock();
    }
}

@end

你可能感兴趣的:(iOS-CAShapeLayer实战)