iOS輕點、觸摸和手勢代碼開發(fā)
一、響應者鏈
以UIResponder作為超類的任何類都是響應者。UIView和UIControl是UIReponder的子類,因此所有視圖和所有控件都是響應者。
1、初始相應器
事件首先會傳遞給UIApplication對象,接下來會傳遞給應用程序的UIWindow,UIWindow會選擇一個初始相應器來處理事件。初始響應器會選擇下面的方式選擇1、對于觸摸事件,UIWindow會確定用戶觸摸的視圖,然后將事件交給注冊了這個視圖的手勢識別器或則注冊視圖層級更高的手勢識別器。只要存在能處理事件的識別器,就不會再繼續(xù)找了。如果沒有的話,被觸摸視圖就是初始相應器,事件也會傳遞給它。
2、對于用戶搖晃設備產(chǎn)生的或者是來自遠程遙控設備事件,將會傳遞給第一響應器
如果初始響應器不處理時間,它會將事件傳遞給它的父視圖(如果存在的話),或者傳遞給視圖控制器(如果此視圖是視圖控制器的視圖)。如果視圖控制器不處理事件,它將沿著響應器鏈的層級繼續(xù)傳給父視圖控制器(如果存在的話)。
如果在整個視圖層級中都沒與能處理事件的視圖或控制器,事件就會被傳遞給應用程序的窗口。如果窗口不能處理事件,而應用委托是UIResponder的子類,UIApplication對象就會將其傳遞給應用程序委托。最后,如果應用委托不是UIResponder的子類,或者不處理這個事件,那么這個事件將會被丟棄。
4個手勢通知方法
#pragma mark - Touch Event Methods
// 用戶第一次觸摸屏幕時被調(diào)用
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
}
// 當發(fā)生某些事件(如來電呼叫)導致手勢中斷時被調(diào)用
- (void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
}
// 當用戶手指離開屏幕時被調(diào)用
- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
}
// 當用戶手指移動時觸發(fā)
- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
}
二、檢測掃描事件
1、手動檢測
//
// ViewController.m
// Swipes
//
// Created by Jierism on 16/8/4.
// Copyright © 2016年 Jierism. All rights reserved.
//
#import "ViewController.h"
// 設置檢測范圍
static CGFloat const kMinimmGestureLength = 25;
static CGFloat const kMaximmVariance = 5;
@interface ViewController ()
@property (weak, nonatomic) IBOutlet UILabel *label;
@property (nonatomic) CGPoint gestureStartPoint;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
self.gestureStartPoint = [touch locationInView:self.view];
}
- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGPoint currentPosition = [touch locationInView:self.view];
// 返回一個float的絕對值
CGFloat deltaX = fabsf(self.gestureStartPoint.x - currentPosition.x);
CGFloat deltaY = fabsf(self.gestureStartPoint.y - currentPosition.y);
// 獲得兩個增量后,判斷用戶在兩個方向上移動過的距離,檢測用戶是否在一個方向上移動得足夠遠但在另一個方向移動得不夠來形成輕掃動作
if (deltaX >= kMinimmGestureLength && deltaY <= kMaximmVariance) {
self.label.text = @"Horizontal swipe detected";
// 2s后擦除文本
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)),
dispatch_get_main_queue(),
^{
self.label.text = @"";
});
}else if (deltaY >= kMinimmGestureLength && deltaX <= kMaximmVariance){
self.label.text = @"Vertical swipe detected";
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
self.label.text = @"";
});
}
}
@end
2、識別器檢測
//
// ViewController.m
// Swipes
//
// Created by Jierism on 16/8/4.
// Copyright © 2016年 Jierism. All rights reserved.
//
#import "ViewController.h"
@interface ViewController ()
@property (weak, nonatomic) IBOutlet UILabel *label;
@property (nonatomic) CGPoint gestureStartPoint;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
//創(chuàng)建兩個手勢識別器
// 1、水平方向識別器
UISwipeGestureRecognizer *horizontal = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(reportHorizontalSwipe:)];
horizontal.direction = UISwipeGestureRecognizerDirectionLeft | UISwipeGestureRecognizerDirectionRight;
[self.view addGestureRecognizer:horizontal];
// 2、垂直方向識別器
UISwipeGestureRecognizer *vertical = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(reportVerticalSwipe:)];
vertical.direction = UISwipeGestureRecognizerDirectionUp | UISwipeGestureRecognizerDirectionDown;
[self.view addGestureRecognizer:vertical];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)reportHorizontalSwipe:(UIGestureRecognizer *)recognizer
{
self.label.text = @"Horizontal swipe detected";
// 2s后擦除文本
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)),
dispatch_get_main_queue(),
^{
self.label.text = @"";
});
}
- (void)reportVerticalSwipe:(UIGestureRecognizer *)recognizer
{
self.label.text = @"Vertical swipe detected";
// 2s后擦除文本
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)),
dispatch_get_main_queue(),
^{
self.label.text = @"";
});
}
@end
三、實現(xiàn)多指輕掃
//
// ViewController.m
// Swipes
//
// Created by Jierism on 16/8/4.
// Copyright © 2016年 Jierism. All rights reserved.
//
#import "ViewController.h"
@interface ViewController ()
@property (weak, nonatomic) IBOutlet UILabel *label;
@property (nonatomic) CGPoint gestureStartPoint;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
for (NSUInteger touchCount = 1; touchCount <= 5; touchCount++) {
//創(chuàng)建兩個手勢識別器
// 1、水平方向識別器
UISwipeGestureRecognizer *horizontal = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(reportHorizontalSwipe:)];
horizontal.direction = UISwipeGestureRecognizerDirectionLeft | UISwipeGestureRecognizerDirectionRight;
[self.view addGestureRecognizer:horizontal];
// 2、垂直方向識別器
UISwipeGestureRecognizer *vertical = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(reportVerticalSwipe:)];
vertical.direction = UISwipeGestureRecognizerDirectionUp | UISwipeGestureRecognizerDirectionDown;
[self.view addGestureRecognizer:vertical];
}
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (NSString *)descriptionForTouchCount:(NSUInteger)touchCount
{
switch (touchCount) {
case 1:
return @"Single";
case 2:
return @"Double";
case 3:
return @"Triple";
case 4:
return @"Quadruple";
case 5:
return @"Quintuple";
default:
return @"";
}
}
- (void)reportHorizontalSwipe:(UIGestureRecognizer *)recognizer
{
self.label.text = [NSString stringWithFormat:@"%@ Horizontal swipe detected",[self descriptionForTouchCount:[recognizer numberOfTouches]]];
// 2s后擦除文本
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)),
dispatch_get_main_queue(),
^{
self.label.text = @"";
});
}
- (void)reportVerticalSwipe:(UIGestureRecognizer *)recognizer
{
self.label.text = [NSString stringWithFormat:@"%@ Vertical swipe detected",[self descriptionForTouchCount:[recognizer numberOfTouches]]];
// 2s后擦除文本
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)),
dispatch_get_main_queue(),
^{
self.label.text = @"";
});
}
@end
四、檢測多次輕點
//
// ViewController.m
// TapTaps
//
// Created by Jierism on 16/8/4.
// Copyright © 2016年 Jierism. All rights reserved.
//
#import "ViewController.h"
@interface ViewController ()
@property (weak, nonatomic) IBOutlet UILabel *singleLabel;
@property (weak, nonatomic) IBOutlet UILabel *doubleLabel;
@property (weak, nonatomic) IBOutlet UILabel *tripleLabel;
@property (weak, nonatomic) IBOutlet UILabel *quadrupleLabel;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
// 創(chuàng)建4個點擊手勢識別器
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(singleTap)];
singleTap.numberOfTapsRequired = 1;
singleTap.numberOfTouchesRequired = 1;
// 附加到視圖
[self.view addGestureRecognizer:singleTap];
UITapGestureRecognizer *doubleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(doubleTap)];
doubleTap.numberOfTapsRequired = 2;
doubleTap.numberOfTouchesRequired = 1;
[self.view addGestureRecognizer:doubleTap];
// 當doubleTap響應“失敗”才運行singleTap
[singleTap requireGestureRecognizerToFail:doubleTap];
UITapGestureRecognizer *tripleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tripleTap)];
tripleTap.numberOfTapsRequired = 3;
tripleTap.numberOfTouchesRequired = 1;
[self.view addGestureRecognizer:tripleTap];
[doubleTap requireGestureRecognizerToFail:tripleTap];
UITapGestureRecognizer *quadrupleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(quadrupleTap)];
quadrupleTap.numberOfTapsRequired = 4;
quadrupleTap.numberOfTouchesRequired = 1;
[self.view addGestureRecognizer:quadrupleTap];
[tripleTap requireGestureRecognizerToFail:quadrupleTap];
}
- (void)singleTap
{
self.singleLabel.text = @"Single Tap Detected";
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
self.singleLabel.text = @"";
});
}
- (void)doubleTap
{
self.doubleLabel.text = @"Double Tap Detected";
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
self.doubleLabel.text = @"";
});
}
- (void)tripleTap
{
self.tripleLabel.text = @"Triple Tap Detected";
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
self.tripleLabel.text = @"";
});
}
- (void)quadrupleTap
{
self.quadrupleLabel.text = @"Quadruple Tap Detected";
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
self.quadrupleLabel.text = @"";
});
}
@end
五、檢測捏合和旋轉(zhuǎn)
#import <UIKit/UIKit.h> @interface ViewController : UIViewController<UIGestureRecognizerDelegate> @end
//
// ViewController.m
// PinchMe
//
// Created by Jierism on 16/8/4.
// Copyright © 2016年 Jierism. All rights reserved.
//
#import "ViewController.h"
@interface ViewController ()
@property (strong,nonatomic) UIImageView *imageView;
@end
@implementation ViewController
// 當前縮放比例,先前縮放比例
CGFloat scale,previousScale;
// 當前旋轉(zhuǎn)角度,先前旋轉(zhuǎn)角度
CGFloat rotation,previousRotation;
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
previousScale = 1;
UIImage *image = [UIImage imageNamed:@"yosemite-meadows"];
self.imageView = [[UIImageView alloc] initWithImage:image];
// 對圖像啟用交互功能
self.imageView.userInteractionEnabled = YES;
self.imageView.center = self.view.center;
[self.view addSubview:self.imageView];
// 建立捏合手勢識別器
UIPinchGestureRecognizer *pinchGesture = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(doPinch:)];
pinchGesture.delegate = self;
[self.imageView addGestureRecognizer:pinchGesture];
// 建立旋轉(zhuǎn)手勢識別器
UIRotationGestureRecognizer *rotationGesture = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:@selector(doRorate:)];
rotationGesture.delegate = self;
[self.imageView addGestureRecognizer:rotationGesture];
}
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
// 允許捏合手勢和旋轉(zhuǎn)手勢同時工作。否則,先開始的手勢識別器會屏蔽另一個
return YES;
}
// 根據(jù)手勢識別器中獲得的縮放比例和旋轉(zhuǎn)角度對圖像進行變換
- (void)transformImageView
{
CGAffineTransform t = CGAffineTransformMakeScale(scale * previousScale, scale * previousScale);
t = CGAffineTransformRotate(t, rotation + previousRotation);
self.imageView.transform = t;
}
- (void)doPinch:(UIPinchGestureRecognizer *)gesture
{
scale = gesture.scale;
[self transformImageView];
if (gesture.state == UIGestureRecognizerStateEnded) {
previousScale = scale * previousScale;
scale = 1;
}
}
- (void)doRorate:(UIRotationGestureRecognizer *)gesture
{
rotation = gesture.rotation;
[self transformImageView];
if (gesture.state == UIGestureRecognizerStateEnded) {
previousRotation = rotation + previousRotation;
rotation = 0;
}
}
@end
六、自定義手勢
//
// CheckMarkRecognizer.m
// CheckPlease
//
// Created by Jierism on 16/8/4.
// Copyright © 2016年 Jierism. All rights reserved.
//
#import "CheckMarkRecognizer.h"
#import "CGPointUtils.h"
#import <UIKit/UIGestureRecognizerSubclass.h> // 一個重要目的是使手勢識別器的state屬性可寫,子類將使用這個機制斷言我們所觀察的手勢已成功完成
// 設置檢測范圍
static CGFloat const kMinimunCheckMarkAngle = 80;
static CGFloat const kMaximumCheckMarkAngle = 100;
static CGFloat const kMinimumCheckMarkLength = 10;
@implementation CheckMarkRecognizer{
// 前兩個實例變量提供之前的線段
CGPoint lastPreviousPoint;
CGPoint lastCurrentPoint;
// 畫出的線段長度
CGFloat lineLengthSoFar;
}
// 用lastPreviousPoint和lastCurrentPoint組成第一條線段,跟第二條線段形成角度去完成手勢
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
[super touchesBegan:touches withEvent:event];
UITouch *touch = [touches anyObject];
CGPoint point = [touch locationInView:self.view];
lastPreviousPoint = point;
lastCurrentPoint = point;
lineLengthSoFar = 0.0;
}
- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
[super touchesMoved:touches withEvent:event];
UITouch *touch = [touches anyObject];
CGPoint previousPoint = [touch previousLocationInView:self.view];
CGPoint currentPoint = [touch locationInView:self.view];
CGFloat angle = angleBetweenLines(lastPreviousPoint, lastCurrentPoint, previousPoint, currentPoint);
if (angle >= kMinimunCheckMarkAngle && angle <= kMaximumCheckMarkAngle && lineLengthSoFar > kMinimumCheckMarkLength) {
self.state = UIGestureRecognizerStateRecognized;
}
lineLengthSoFar += distanceBetweenPoints(previousPoint, currentPoint);
lastPreviousPoint = previousPoint;
lastCurrentPoint = currentPoint;
}
@end
//
// ViewController.m
// CheckPlease
//
// Created by Jierism on 16/8/4.
// Copyright © 2016年 Jierism. All rights reserved.
//
#import "ViewController.h"
#import "CheckMarkRecognizer.h"
@interface ViewController ()
@property (weak, nonatomic) IBOutlet UIImageView *imageView;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
CheckMarkRecognizer *check = [[CheckMarkRecognizer alloc] initWithTarget:self action:@selector(doCheck:)];
[self.view addGestureRecognizer:check];
self.imageView.hidden = YES;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)doCheck:(CheckMarkRecognizer *)check
{
self.imageView.hidden = NO;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
self.imageView.hidden = YES;
});
}
@end
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關文章
Flutter開發(fā)Widgets?之?PageView使用示例
這篇文章主要為大家介紹了Flutter開發(fā)Widgets?之?PageView使用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-10-10
iOS中創(chuàng)建表格類視圖WBDataGridView的實例代碼
這篇文章主要介紹了iOS中創(chuàng)建表格類視圖WBDataGridView的實例代碼,需要的朋友可以參考下2017-02-02

