Những gì tôi đang sử dụng sự kiện chạm rất nhạy cảm về thời gian, vì vậy tôi tò mò liệu có thể kích hoạt UITapGestureRecognizer khi người dùng chỉ cần chạm xuống, thay vì yêu cầu họ chạm vào không?
Những gì tôi đang sử dụng sự kiện chạm rất nhạy cảm về thời gian, vì vậy tôi tò mò liệu có thể kích hoạt UITapGestureRecognizer khi người dùng chỉ cần chạm xuống, thay vì yêu cầu họ chạm vào không?
Câu trả lời:
Tạo lớp con TouchDownGestureRecognizer tùy chỉnh của bạn và triển khai cử chỉ khi chạm vàoBegan:
TouchDownGestureRecognizer.h
#import <UIKit/UIKit.h>
@interface TouchDownGestureRecognizer : UIGestureRecognizer
@end
TouchDownGestureRecognizer.m
#import "TouchDownGestureRecognizer.h"
#import <UIKit/UIGestureRecognizerSubclass.h>
@implementation TouchDownGestureRecognizer
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
if (self.state == UIGestureRecognizerStatePossible) {
self.state = UIGestureRecognizerStateRecognized;
}
}
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
self.state = UIGestureRecognizerStateFailed;
}
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
self.state = UIGestureRecognizerStateFailed;
}
@end
thực hiện:
#import "TouchDownGestureRecognizer.h"
TouchDownGestureRecognizer *touchDown = [[TouchDownGestureRecognizer alloc] initWithTarget:self action:@selector(handleTouchDown:)];
[yourView addGestureRecognizer:touchDown];
-(void)handleTouchDown:(TouchDownGestureRecognizer *)touchDown{
NSLog(@"Down");
}
Triển khai nhanh chóng:
import UIKit
import UIKit.UIGestureRecognizerSubclass
class TouchDownGestureRecognizer: UIGestureRecognizer
{
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent)
{
if self.state == .Possible
{
self.state = .Recognized
}
}
override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent)
{
self.state = .Failed
}
override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent)
{
self.state = .Failed
}
}
Đây là cú pháp Swift cho năm 2017 để dán:
import UIKit.UIGestureRecognizerSubclass
class SingleTouchDownGestureRecognizer: UIGestureRecognizer {
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent) {
if self.state == .possible {
self.state = .recognized
}
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent) {
self.state = .failed
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent) {
self.state = .failed
}
}
Lưu ý rằng đây là một thay thế thả vào cho UITap
. Vì vậy, trong mã như ...
func add(tap v:UIView, _ action:Selector) {
let t = UITapGestureRecognizer(target: self, action: action)
v.addGestureRecognizer(t)
}
bạn có thể hoán đổi một cách an toàn sang ....
func add(hairtriggerTap v:UIView, _ action:Selector) {
let t = SingleTouchDownGestureRecognizer(target: self, action: action)
v.addGestureRecognizer(t)
}
Thử nghiệm cho thấy nó sẽ không được gọi nhiều hơn một lần. Nó hoạt động như một sự thay thế thả vào; bạn chỉ có thể hoán đổi giữa hai cuộc gọi.
Sử dụng UILongPressGestureRecognizer và đặt nó minimumPressDuration
thành 0. Nó sẽ hoạt động giống như một lần chạm xuống trong UIGestureRecognizerStateBegan
trạng thái.
func setupTap() {
let touchDown = UILongPressGestureRecognizer(target:self, action: #selector(didTouchDown))
touchDown.minimumPressDuration = 0
view.addGestureRecognizer(touchDown)
}
@objc func didTouchDown(gesture: UILongPressGestureRecognizer) {
if gesture.state == .began {
doSomething()
}
}
-(void)setupLongPress
{
self.longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(didLongPress:)];
self.longPress.minimumPressDuration = 0;
[self.view addGestureRecognizer:self.longPress];
}
-(void)didLongPress:(UILongPressGestureRecognizer *)gesture
{
if (gesture.state == UIGestureRecognizerStateBegan){
[self doSomething];
}
}
UIGestureRecognizerStateEnded
minimumPressDuration
có thể là 0 tho.
Đây là một phiên bản Swift tương tự như câu trả lời Objective-C của Rob Caraway .
Ý tưởng là sử dụng trình nhận dạng cử chỉ nhấn và giữ minimumPressDuration
được đặt thành 0 thay vì sử dụng trình nhận dạng cử chỉ nhấn. Điều này là do trình nhận dạng cử chỉ nhấn và giữ báo cáo các sự kiện chạm đã bắt đầu trong khi cử chỉ nhấn thì không.
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var myView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
// Add "long" press gesture recognizer
let tap = UILongPressGestureRecognizer(target: self, action: #selector(tapHandler))
tap.minimumPressDuration = 0
myView.addGestureRecognizer(tap)
}
// called by gesture recognizer
@objc func tapHandler(gesture: UITapGestureRecognizer) {
// handle touch down and touch up events separately
if gesture.state == .began {
// do something...
print("tap down")
} else if gesture.state == .ended { // optional for touch up event catching
// do something else...
print("tap up")
}
}
}
Đây là một giải pháp khác. Tạo lớp con của UIControl. Bạn có thể sử dụng nó như UIView ngay cả trong Storyboard vì UIControl là lớp con của UIView.
class TouchHandlingView: UIControl {
}
Và addTarget vào nó:
@IBOutlet weak var mainView: TouchHandlingView!
...
mainView.addTarget(self, action: "startAction:", forControlEvents: .TouchDown)
...
Sau đó, hành động được chỉ định sẽ được gọi như UIButton:
func startAction(sender: AnyObject) {
print("start")
}
Tôi cần khả năng kích hoạt tóc để chế độ xem của tôi có thể phản hồi ngay khi chạm vào. Sử dụng cả câu trả lời @LESANG đều hiệu quả và sử dụng câu trả lời @RobCaraway cũng vậy . Vấn đề tôi gặp phải với cả hai câu trả lời là tôi mất khả năng nhận dạng các lần vuốt. Tôi cần chế độ xem của mình xoay khi được vuốt nhưng ngay khi ngón tay tôi chạm vào chế độ xem, chỉ có vòi được nhận dạng. TapRecognizer quá nhạy cảm và không thể phân biệt giữa một lần nhấn và một lần vuốt.
Đây là những gì tôi nghĩ ra dựa trên câu trả lời @LESANG kết hợp với câu trả lời này và câu trả lời này .
Tôi đặt 6 bình luận trong mỗi sự kiện.
import UIKit.UIGestureRecognizerSubclass
class SingleTouchDownGestureRecognizer: UIGestureRecognizer {
var wasSwiped = false
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent) {
guard let view = self.view else { return }
guard let touches = event.touches(for: view) else { return } // 1. compare that event in touchesBegan has touches for the view that is the same as the view to which your gesture recognizer was assigned
if touches.first != nil {
print("Finger touched!") // 2. this is when the user's finger first touches the view and is at locationA
wasSwiped = false // 3. it would seem that I didn't have to set this to false because the property was already set to false but for some reason when I didn't add this it wasn't responding correctly. Basically set this to false
}
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent) {
guard let touch = touches.first else { return }
let newLocation = touch.location(in: self.view)
let previousLocation = touch.previousLocation(in: self.view)
if (newLocation.x > previousLocation.x) || (newLocation.x < previousLocation.x) {
print("finger touch went right or left") // 4. when the user's finger first touches it's at locationA. If the the user moves their finger to either the left or the right then the finger is no longer at locationA. That means it moved which means a swipe occurred so set the "wasSwiped" property to true
wasSwiped = true // 5. set the property to true because the user moved their finger
}
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent) {
print("finger is no longer touching.") // 6. the user has lifted their finger off of the view. If "wasSwiped" is true then ".fail" but if it wasn't swiped then ".recognize"
if wasSwiped {
self.state = .failed
} else {
self.state = .recognized
}
}
}
Và để sử dụng nó để chế độ xem sử dụng nó sẽ nhận được phản hồi kích hoạt tóc và các cử chỉ vuốt sang trái và phải:
let tapGesture = SingleTouchDownGestureRecognizer(target: self, action: #selector(viewWasTapped(_:)))
myView.addGestureRecognizer(tapGesture)
let rightGesture = UISwipeGestureRecognizer(target: self, action: #selector(respondToSwipeGesture(recognizer:)))
rightGesture.direction = .right
myView.addGestureRecognizer(rightGesture)
let leftGesture = UISwipeGestureRecognizer(target: self, action: #selector(respondToSwipeGesture(recognizer:)))
leftGesture.direction = .left
myView.addGestureRecognizer(leftGesture)