该功能为项目中的需求。现在时间空闲一点。记录一下!
话不多说,看代码!
声明文件
#import
@interface YHRippleLayer : UIView
@property (nonatomic, strong) UIView *container;
@property (nonatomic, strong) UIView *bgViewView;
- (void)show;
- (void)dismiss;
@end
实现文件
#import "YHRippleLayer.h"
@interface YHRippleLayer ()
@property (nonatomic, strong) NSTimer *rippleTimer;
@property (nonatomic, strong) UIImageView *voiceIV;
@end
@implementation YHRippleLayer
-(instancetype)init{
self = [super init];
if(self) {
self.frame = [UIScreen mainScreen].bounds;
self.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.618];
[self addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleGuesture:)]];
_bgViewView = [[UIView alloc] initWithFrame:CGRectMake(0, [UIScreen mainScreen].bounds.size.height-400, [UIScreen mainScreen].bounds.size.width, 400)];
_bgViewView.backgroundColor = [UIColor whiteColor];
[self addSubview:_bgViewView];
self.voiceIV=[[UIImageView alloc] init];
_voiceIV.tag=500;
[_voiceIV setFrame:CGRectMake(([UIScreen mainScreen].bounds.size.width-58)/2.0, (400-58)/2.0, 58, 58)];
[_voiceIV setImage:[UIImage imageNamed:@"组 1 拷贝"]];
_voiceIV.userInteractionEnabled = YES;
UILongPressGestureRecognizer *longPress =[[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(onBtnLongPressed:)];
[_voiceIV addGestureRecognizer:longPress];
[_bgViewView addSubview:_voiceIV];
}
return self;
}
#pragma mark - action
- (void)onBtnLongPressed:(UILongPressGestureRecognizer *)longGesture{
if (longGesture.state==UIGestureRecognizerStateBegan) {
// 打开动画
[self showWithRipple];
}else if(longGesture.state == UIGestureRecognizerStateEnded){
// 关闭动画
[self closeRippleTimer];
}
}
- (void)handleGuesture:(UITapGestureRecognizer *)sender {
[self dismiss];
}
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
UIView *hitView = [super hitTest:point withEvent:event];
if(hitView == self){
if(hitView.backgroundColor == [UIColor clearColor]) {
return nil;
}
}
return hitView;
}
#pragma mark - 动画效果
- (void)showWithRipple
{
self.rippleTimer = [NSTimer timerWithTimeInterval:0.5 target:self selector:@selector(addRippleLayer) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:_rippleTimer forMode:NSRunLoopCommonModes];
}
- (CGRect)makeEndRect
{
CGRect endRect = CGRectMake(_voiceIV.frame.origin.x, _voiceIV.frame.origin.y, 58, 58);
endRect = CGRectInset(endRect, -50, -50);
return endRect;
}
- (void)addRippleLayer
{
CAShapeLayer *rippleLayer = [[CAShapeLayer alloc] init];
rippleLayer.position = CGPointMake(150, 150);
rippleLayer.bounds = CGRectMake(0, 0, 300, 300);
rippleLayer.backgroundColor = [UIColor clearColor].CGColor;
UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(_voiceIV.frame.origin.x, _voiceIV.frame.origin.y, 58, 58)];
rippleLayer.path = path.CGPath;
rippleLayer.strokeColor = [UIColor blueColor].CGColor;
rippleLayer.lineWidth = 5;
[rippleLayer setFillColor:[UIColor clearColor].CGColor];
[_bgViewView.layer insertSublayer:rippleLayer below:_voiceIV.layer];
//addRippleAnimation
UIBezierPath *beginPath = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(_voiceIV.frame.origin.x, _voiceIV.frame.origin.y, 58, 58)];
CGRect endRect = CGRectInset([self makeEndRect], -50, -50);
UIBezierPath *endPath = [UIBezierPath bezierPathWithOvalInRect:endRect];
rippleLayer.path = endPath.CGPath;
rippleLayer.opacity = 0.0;
CABasicAnimation *rippleAnimation = [CABasicAnimation animationWithKeyPath:@"path"];
rippleAnimation.fromValue = (__bridge id _Nullable)(beginPath.CGPath);
rippleAnimation.toValue = (__bridge id _Nullable)(endPath.CGPath);
rippleAnimation.duration = 1.8;
CABasicAnimation *opacityAnimation = [CABasicAnimation animationWithKeyPath:@"opacity"];
opacityAnimation.fromValue = [NSNumber numberWithFloat:1.0];
opacityAnimation.toValue = [NSNumber numberWithFloat:0.0];
opacityAnimation.duration = 1.8;
[rippleLayer addAnimation:opacityAnimation forKey:@""];
[rippleLayer addAnimation:rippleAnimation forKey:@""];
[self performSelector:@selector(removeRippleLayer:) withObject:rippleLayer afterDelay:1.8];
}
- (void)removeRippleLayer:(CAShapeLayer *)rippleLayer
{
[rippleLayer removeFromSuperlayer];
rippleLayer = nil;
}
- (void)closeRippleTimer
{
if (_rippleTimer) {
if ([_rippleTimer isValid]) {
[_rippleTimer invalidate];
}
_rippleTimer = nil;
}
}
- (void)show {
UIWindow *window = [[[UIApplication sharedApplication] delegate] window];
[window addSubview:self];
self.bgViewView.transform = CGAffineTransformMakeTranslation(0.01, 209);
[UIView animateWithDuration:0.3 animations:^{
self.bgViewView.transform = CGAffineTransformMakeTranslation(0.01, 0.01);
}];
}
- (void)dismiss {
[UIView animateWithDuration:0.3 animations:^{
self.bgViewView.transform = CGAffineTransformMakeTranslation(0.01, 209);
self.alpha = 0;
} completion:^(BOOL finished) {
[self removeFromSuperview];
[self.bgViewView removeFromSuperview];
}];
}
@end
使用方法
#import "ViewController.h"
#import "YHRippleLayer.h"
@interface ViewController ()
@property (nonatomic , strong) YHRippleLayer *layerView;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
btn.frame = CGRectMake(150, 300, 75, 30);
btn.layer.borderWidth = 2.0;
btn.layer.borderColor = [UIColor cyanColor].CGColor;
[btn setTitle:@"录音" forState:UIControlStateNormal];
[btn setTitleColor:[UIColor orangeColor] forState:UIControlStateNormal];
[btn addTarget:self action:@selector(showRippleLayer) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:btn];
}
-(void)showRippleLayer{
_layerView = [YHRippleLayer new];
[_layerView show];
}
@end