탭 이벤트를 사용하는 것은 매우 시간에 민감하므로 사용자가 터치 업을 요구하는 대신 단순히 터치 다운 할 때 UITapGestureRecognizer를 활성화 할 수 있는지 궁금합니다.
탭 이벤트를 사용하는 것은 매우 시간에 민감하므로 사용자가 터치 업을 요구하는 대신 단순히 터치 다운 할 때 UITapGestureRecognizer를 활성화 할 수 있는지 궁금합니다.
답변:
사용자 지정 TouchDownGestureRecognizer 하위 클래스를 만들고 touchesBegan에서 제스처를 구현합니다.
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
이행:
#import "TouchDownGestureRecognizer.h"
TouchDownGestureRecognizer *touchDown = [[TouchDownGestureRecognizer alloc] initWithTarget:self action:@selector(handleTouchDown:)];
[yourView addGestureRecognizer:touchDown];
-(void)handleTouchDown:(TouchDownGestureRecognizer *)touchDown{
NSLog(@"Down");
}
신속한 구현 :
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
}
}
붙여 넣을 2017 년의 Swift 구문은 다음과 같습니다.
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
}
}
이것은 UITap
. 그래서 코드에서 ...
func add(tap v:UIView, _ action:Selector) {
let t = UITapGestureRecognizer(target: self, action: action)
v.addGestureRecognizer(t)
}
안전하게 교체 할 수 있습니다 ....
func add(hairtriggerTap v:UIView, _ action:Selector) {
let t = SingleTouchDownGestureRecognizer(target: self, action: action)
v.addGestureRecognizer(t)
}
테스트 결과 두 번 이상 호출되지 않습니다. 드롭 인 대체품으로 작동합니다. 두 통화 사이를 전환 할 수 있습니다.
UILongPressGestureRecognizer를 사용하고 minimumPressDuration
0으로 설정합니다 UIGestureRecognizerStateBegan
. 상태 동안 터치 다운처럼 작동합니다 .
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
0도 될 수 있습니다.
다음은 Rob Caraway의 Objective-C 답변 과 유사한 Swift 버전 입니다.
아이디어는 minimumPressDuration
탭 제스처 인식기를 사용하는 대신 0으로 설정된 길게 누르기 제스처 인식기를 사용하는 것입니다. 길게 누르기 제스처 인식기는 터치 시작 이벤트를보고하지만 탭 제스처는보고하지 않기 때문입니다.
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")
}
}
}
이것은 또 다른 해결책입니다. UIControl의 하위 클래스를 만듭니다. UIControl은 UIView의 하위 클래스이기 때문에 Storyboard에서도 UIView처럼 사용할 수 있습니다.
class TouchHandlingView: UIControl {
}
그리고 그것에 addTarget :
@IBOutlet weak var mainView: TouchHandlingView!
...
mainView.addTarget(self, action: "startAction:", forControlEvents: .TouchDown)
...
그러면 지정된 작업이 UIButton과 같이 호출됩니다.
func startAction(sender: AnyObject) {
print("start")
}
머리를 두 드리 자마자 반응 할 수 있도록 뷰에 헤어 트리거가있는 기능이 필요했습니다. 모두 사용 @LESANG 응답하는 일 등 사용했다 @RobCaraway의 대답을 . 두 답변 모두 문제 는 스 와이프를 인식하는 능력을 잃었다는 것입니다. 스 와이프 할 때 뷰를 회전해야했지만 손가락이 뷰에 닿 자마자 탭만 인식되었습니다. tapRecognizer가 너무 민감해서 탭과 스 와이프를 구분할 수 없습니다.
이것은 내가 기반 오프 해낸 것입니다 @LESANG 대답 이 결합 답 이 대답 .
각 이벤트에 6 개의 댓글을 달았습니다.
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
}
}
}
그리고 그것을 사용하는 뷰가 헤어 트리거 응답과 왼쪽 및 오른쪽 스 와이프 제스처를 얻도록 사용하려면 :
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)