UITap 제스처 인식기 - 터치업이 아닌 터치다운에서 작동하도록 합니까?
제가 탭 이벤트를 사용하는 이유는 시간에 매우 민감하기 때문에 사용자가 터치업을 요구하지 않고 터치다운만 하면 UITapGesture Recognizer를 활성화할 수 있는지 궁금합니다.
UILongPress 제스처 인식기 사용 및 설정minimumPressDuration
0까지. 그것은 터치다운처럼 행동할 것입니다.UIGestureRecognizerStateBegan
주.
스위프트 4+용
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()
}
}
목표-C의 경우
-(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];
}
}
사용자 지정 TouchDownGestureRecognizer 하위 클래스를 만들고 터치에서 제스처를 구현합니다.시작:
터치다운 제스처 인식기.h
#import <UIKit/UIKit.h>
@interface TouchDownGestureRecognizer : UIGestureRecognizer
@end
터치다운 제스처 인식기.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)
}
테스트 결과 두 번 이상 호출되지 않습니다.대신 전화를 걸 수 있습니다. 두 통화 사이를 전환하면 됩니다.
스위프트(하위 분류 없음)
다음은 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")
}
}
}
이것은 또 다른 해결책입니다.UI 컨트롤의 하위 클래스를 만듭니다.UI 컨트롤이 UI 뷰의 하위 클래스이기 때문에 스토리보드에서도 UI 뷰처럼 사용할 수 있습니다.
class TouchHandlingView: UIControl {
}
Target을 추가합니다.
@IBOutlet weak var mainView: TouchHandlingView!
...
mainView.addTarget(self, action: "startAction:", forControlEvents: .TouchDown)
...
그러면 지정된 작업이 UIButton과 같이 호출됩니다.
func startAction(sender: AnyObject) {
print("start")
}
저는 제 시각이 머리를 누르는 순간 반응할 수 있는 기능이 필요했습니다.@LESANG 답변과 @RobCaraway 답변을 모두 사용하는 것이 효과적이었습니다.제가 두 대답 모두에서 마주친 문제는 제가 스와이프를 인식하는 능력을 잃었다는 것입니다.스와이프를 할 때 화면이 회전해야 하는데 손가락이 화면에 닿자마자 탭만 인식되었습니다.탭 인식기가 너무 민감하여 탭과 스와이프를 구별할 수 없습니다.
이것은 제가 @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)
다른 접근 방식: UIView 내부에 투명 버튼을 추가하고 그에 따라 touchUp 및 touchDown 작업을 할당합니다.
언급URL : https://stackoverflow.com/questions/15628133/uitapgesturerecognizer-make-it-work-on-touch-down-not-touch-up
'IT' 카테고리의 다른 글
유니파이드 diff 파일에서 문자별 차이를 시각화하려면 어떻게 해야 합니까? (0) | 2023.08.26 |
---|---|
더 나은 리눅스 셸? (0) | 2023.08.26 |
UITableView에서 테이블 헤더의 높이를 설정하는 방법은 무엇입니까? (0) | 2023.08.26 |
mysql(Mariadb)을 다시 시작한 후 다시 시작하는 데 5분이 걸립니다. (0) | 2023.08.26 |
Git의 *safe.directory*에 상위 디렉토리를 추가할 수 없습니다. (0) | 2023.08.26 |