由于自己的证券公司要做语音识别,基于view自定义了语音按钮,支持
单击、双击、长按、开始拖拽、拖拽中、结束拖拽
以上各种事件互不冲突,即同一时刻只有一种事件(手势)存在
以上各个手势事件,都留出了相应的方法,方法内有对应事件的说明输出文字
1. 源码地址 GitHub : https://github.com/liuchengli/LongPressButton
(GitHub上的长按源码较新)
2. 效果图:
3. 代码:
.h
//
// LongPressButton.h
// ASR
//
// Created by 刘成利 on 2017/3/2.
// Copyright © 2017年 刘成利. All rights reserved.
//
#import <UIKit/UIKit.h>
typedef enum {
LongTouchBegin = 1000, // 开始触摸
LongTouchEnd = 1001, // 结束触摸
}TouchType;
typedef void (^EventAndTime) (TouchType TouchType,NSTimeInterval time);
/* 为正方形,取宽高的最大值为方形边长 */
@interface LongPressButton : UIView
// 开始和结束触摸事件回调
@property (nonatomic, copy) EventAndTime eventBlock;
// 不需要loading圈请设为YES,默认带loading
@property (nonatomic, assign) BOOL removeLoading;
- (void)finishAndRest;
@end
//
// LongPressButton.h
// ASR
//
// Created by 刘成利 on 2017/3/2.
// Copyright © 2017年 刘成利. All rights reserved.
//
#import <UIKit/UIKit.h>
typedef enum {
LongTouchBegin = 1000, // 开始触摸
LongTouchEnd = 1001, // 结束触摸
}TouchType;
typedef void (^EventAndTime) (TouchType TouchType,NSTimeInterval time);
/* 为正方形,取宽高的最大值为方形边长 */
@interface LongPressButton : UIView
// 开始和结束触摸事件回调
@property (nonatomic, copy) EventAndTime eventBlock;
// 不需要loading圈请设为YES,默认带loading
@property (nonatomic, assign) BOOL removeLoading;
- (void)finishAndRest;
@end
.m
//
// LongPressButton.m
// ASR
//
// Created by 刘成利 on 2017/3/2.
// Copyright © 2017年 刘成利. All rights reserved.
//
#import "LongPressButton.h"
@interface LongPressButton ()
// 点击后的放大白圈
@property (nonatomic, strong) CAShapeLayer *clickCicrleLayer;
// 最后的旋转圈
@property (nonatomic, strong) CAShapeLayer *loadingLayer;
// 宽度的一般,控制贴边
@property (nonatomic, assign) CGFloat halfWidth;
@end
@implementation LongPressButton
// 初始化
- (id)initWithFrame:(CGRect)frame
{
// 获取最大宽高值为方形边长
CGFloat square = CGRectGetWidth(frame) > CGRectGetHeight(frame) ? CGRectGetWidth(frame):CGRectGetHeight(frame);
self = [super initWithFrame:CGRectMake(frame.origin.x, frame.origin.y, square, square)];
if (self)
{
[self setUp];
}
return self;
}
- (void)setUp{
// 1.初始化样式
// self.backgroundColor = [[UIColor greenColor]colorWithAlphaComponent:0.3];
// self.clipsToBounds = YES;
// 初始浅白色层
CGFloat withValue = CGRectGetWidth(self.bounds);
self.halfWidth = withValue/2;
// 1.放大白圈
UIBezierPath *clickCicrlePath = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, 0, withValue, withValue)];
self.clickCicrleLayer = [CAShapeLayer layer];
self.clickCicrleLayer.frame = self.bounds;
self.clickCicrleLayer.fillColor = [[[UIColor blackColor]colorWithAlphaComponent:0.1] CGColor];
self.clickCicrleLayer.path = clickCicrlePath.CGPath;
// 2. 麦克风图片
UIImageView *image = [[UIImageView alloc]initWithFrame:CGRectMake(withValue/4, withValue/4, withValue/2, withValue/2)];
image.image = [UIImage imageNamed:@"mic"];
[self.layer addSublayer:self.clickCicrleLayer];
[self addSubview:image];
// 3. 拖拽、长按、单击、双击手势
UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(dragAction:)];
[self addGestureRecognizer:pan];
UILongPressGestureRecognizer *longPressGesture = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPress:)];
longPressGesture.minimumPressDuration = 0.2;
[self addGestureRecognizer:longPressGesture];
UITapGestureRecognizer *oneTap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(oneClick:)];
oneTap.numberOfTapsRequired = 1;
oneTap.numberOfTouchesRequired = 1;
[self addGestureRecognizer:oneTap];
UITapGestureRecognizer *doubleTap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(doubelClick:)];
doubleTap.numberOfTapsRequired = 2;
doubleTap.numberOfTouchesRequired = 1;
[self addGestureRecognizer:doubleTap];
[oneTap requireGestureRecognizerToFail:doubleTap];
// 4. 识别进度
self.loadingLayer = [CAShapeLayer layer];
self.loadingLayer.position = CGPointMake(self.bounds.size.width/2, self.bounds.size.height/2);
self.loadingLayer.fillColor = [UIColor clearColor].CGColor;
self.loadingLayer.strokeColor = [UIColor whiteColor].CGColor;
self.loadingLayer.lineWidth = 5;
self.loadingLayer.opacity = 0;
CGFloat radius = self.bounds.size.height/2 - 3;
UIBezierPath *loadingBezier = [UIBezierPath bezierPath];
[loadingBezier addArcWithCenter:CGPointMake(0,0) radius:radius startAngle:M_PI/2 endAngle:M_PI/2+M_PI/2 clockwise:YES];
self.loadingLayer.path = loadingBezier.CGPath;
[self.layer addSublayer:self.loadingLayer];
}
// 响应事件
-(void)longPress: (UILongPressGestureRecognizer *)gesture {
switch (gesture.state) {
case UIGestureRecognizerStateBegan:
{
[self LongPressBegin]; // 开始长按
NSLog(@"开始长按");
}
break;
case UIGestureRecognizerStateEnded:
{
[self LongPressEnd]; // 结束长按
NSLog(@"结束长按");
}
break;
case UIGestureRecognizerStateChanged:
{
NSLog(@"长按改变");
}
break;
case UIGestureRecognizerStateCancelled:
{
NSLog(@"长按取消");
}
break;
default:
break;
}
}
#pragma mark 手势处理
// 单击事件
- (void)oneClick:(UITapGestureRecognizer *)sender{
NSLog(@"单击事件");
}
// 双击事件
- (void)doubelClick:(UITapGestureRecognizer *)sender{
NSLog(@"双击事件");
}
// 开始长按
- (void)LongPressBegin{
if (self.eventBlock)
{
self.eventBlock(LongTouchBegin,0);
}
if (self.loadingLayer) {
[self.loadingLayer removeAnimationForKey:@"loadingAnimation"];
self.loadingLayer.opacity = 0;
}
// 圆弧变大
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
animation.duration = 0.5; // 动画持续时间
animation.repeatCount = LONG_MAX; // 重复次数
animation.autoreverses = YES; // 动画结束时执行逆动画
animation.fromValue = [NSNumber numberWithFloat:1]; // 开始时的倍率
animation.toValue = [NSNumber numberWithFloat:1.8]; // 结束时的倍率
[self.clickCicrleLayer addAnimation:animation forKey:@"scale-layer"];
}
// 结束长按
- (void)LongPressEnd{
if (self.eventBlock)
{
self.eventBlock(LongTouchEnd,0);
}
[self.clickCicrleLayer removeAnimationForKey:@"scale-layer"];
self.loadingLayer.opacity = 1;
CABasicAnimation *basicAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
basicAnimation.fromValue = @(0);
basicAnimation.toValue = @(M_PI*2);
basicAnimation.duration = 0.5;
basicAnimation.repeatCount = LONG_MAX;
[self.loadingLayer addAnimation:basicAnimation forKey:@"loadingAnimation"];
}
// 拖拽手势处理
- (void)dragAction:(UIPanGestureRecognizer *)sender
{
//获取手势在屏幕上拖动的点
CGPoint point=[sender translationInView:sender.self.view];
//设置中心点
sender.view.center=CGPointMake(sender.view.center.x+point.x, sender.view.center.y+point.y);
//设置视图在父视图上拖拽的位置
[sender setTranslation:CGPointZero inView:sender.self.view];//用来设置匀速运动
NSLog(@"***拖拽事件响应= %f %f",point.x,point.y);
// 处理滑动结束贴边
if (sender.state == UIGestureRecognizerStateEnded){
CGFloat screenWidth = [UIScreen mainScreen].bounds.size.width;
CGFloat screenHeight = [UIScreen mainScreen].bounds.size.height;
// 方形宽高相等
CGFloat minX = self.halfWidth;
CGFloat maxX = screenWidth-self.halfWidth;
CGFloat minY = self.halfWidth;
CGFloat maxY = screenHeight-self.halfWidth;
CGFloat X = sender.view.center.x;
CGFloat Y = sender.view.center.y;
if (sender.view.center.x < minX) X = minX;
if (sender.view.center.x > maxX) X = maxX;
if (sender.view.center.y < minY) Y = minY;
if (sender.view.center.y > maxY) Y = maxY;
sender.view.center=CGPointMake(X, Y);
//设置视图在父视图上拖拽的位置
[sender setTranslation:CGPointZero inView:sender.self.view];//用来设置匀速运动
NSLog(@"***结束拖拽***");
}
}
// 停止loadiing,重置
- (void)finishAndRest{
self.loadingLayer.opacity = 0;
[self.loadingLayer removeAnimationForKey:@"loadingAnimation"];
if(self.removeLoading == YES){
[self.loadingLayer removeFromSuperlayer];
}
}
@end