UIView에 터치 이벤트를 추가하는 방법은 무엇입니까?


280

UIView에 터치 이벤트를 어떻게 추가합니까?
나는 시도 :

UIView *headerView = [[[UIView alloc] initWithFrame:CGRectMake(0, 0, tableView.bounds.size.width, nextY)] autorelease];
[headerView addTarget:self action:@selector(myEvent:) forControlEvents:UIControlEventTouchDown];
// ERROR MESSAGE: UIView may not respond to '-addTarget:action:forControlEvents:'

서브 클래스를 만들고 덮어 쓰고 싶지 않습니다.

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event

신속하게 여기에서 얻을 수 있습니다 : stackoverflow.com/questions/28675209/…
Mr.Javed Multani

답변:


578

iOS 3.2 이상에서는 제스처 인식기를 사용할 수 있습니다. 예를 들어 다음은 탭 이벤트를 처리하는 방법입니다.

//The setup code (in viewDidLoad in your view controller)
UITapGestureRecognizer *singleFingerTap = 
  [[UITapGestureRecognizer alloc] initWithTarget:self 
                                          action:@selector(handleSingleTap:)];
[self.view addGestureRecognizer:singleFingerTap];

//The event handling method
- (void)handleSingleTap:(UITapGestureRecognizer *)recognizer
{
  CGPoint location = [recognizer locationInView:[recognizer.view superview]];

  //Do stuff here...
}

내장 된 제스처도 많이 있습니다. iOS 이벤트 처리 및에 대한 문서를 확인하십시오 UIGestureRecognizer. 또한 도움이 될만한 github 에 많은 샘플 코드 가 있습니다.


그러나 그것은 뷰의 터치 defautlt 액션을 덮어 쓰고 있습니다. ¿보기의 기본 터치 동작을 호출 할 수 있습니까?
M Penades

2
CGPoint 라인은 무엇을합니까?
zakdances

2
@yourfriendzak은 CGPoint탭된보기의 수퍼 뷰에서 탭의 위치를 ​​나타냅니다. 이 지점을 사용하여 탭된보기 (또는 형제보기)를 탭된 위치로 이동할 수 있습니다. 이것은 UIPanGestureRecognizer화면에서 뷰를 드래그 할 때 핸들러에서 더 유용합니다 .
Nathan Eror

5
간결한 답변, 감사합니다. 그러나 esh, 이것이 좀 더 쉬웠다면 좋지 않을까요?! :)
natbro

나쁘지는 않지만 github.com/neror/ftutils/blob/master/Headers/FTUtils/… 와 같은 블록 기반 API가 있었으면 좋겠습니다 . Xcode 4는 Interface Builder에서 제스처 인식기를 추가 / 구성하는 기능도 지원합니다.
Nathan Eror

126

제스처 인식기

뷰에 제스처 인식기 를 추가 할 때 알림을받을 수있는 일반적으로 사용되는 터치 이벤트 (또는 제스처)가 많이 있습니다. 기본적으로 다음 제스처 유형이 지원됩니다.

  • UITapGestureRecognizer 누르기 (화면을 한 번 이상 짧게 터치)
  • UILongPressGestureRecognizer 길게 터치 (화면을 오랫동안 터치 )
  • UIPanGestureRecognizer (화면을 가로 질러 손가락 이동)
  • UISwipeGestureRecognizer 스 와이프 (손가락을 빠르게 움직입니다)
  • UIPinchGestureRecognizer 핀치 (두 손가락을 함께 또는 따로 이동-일반적으로 확대)
  • UIRotationGestureRecognizer 회전 (두 손가락을 원 방향으로 이동)

이외에도 사용자 정의 제스처 인식기를 만들 수도 있습니다.

인터페이스 빌더에서 제스처 추가

제스처 인식기를 객체 라이브러리에서 뷰로 드래그합니다.

여기에 이미지 설명을 입력하십시오

콘센트와 액션을 만들기 위해 문서 개요의 제스처에서 View Controller 코드로 드래그를 제어합니다.

여기에 이미지 설명을 입력하십시오

기본적으로 설정되어 있어야하지만보기에 User Action Enabled 가 true로 설정되어 있는지 확인하십시오 .

여기에 이미지 설명을 입력하십시오

프로그래밍 방식으로 제스처 추가

프로그래밍 방식으로 제스처를 추가하려면 (1) 제스처 인식기를 만들고 (2) 뷰에 추가하고 (3) 제스처가 인식 될 때 호출되는 메서드를 만듭니다.

import UIKit
class ViewController: UIViewController {

    @IBOutlet weak var myView: UIView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // 1. create a gesture recognizer (tap gesture)
        let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleTap(sender:)))
        
        // 2. add the gesture recognizer to a view
        myView.addGestureRecognizer(tapGesture)
    }
    
    // 3. this method is called when a tap is recognized
    @objc func handleTap(sender: UITapGestureRecognizer) {
        print("tap")
    }
}

노트

  • sender매개 변수는 선택 사항입니다. 제스처에 대한 참조가 필요하지 않으면 그대로 둘 수 있습니다. 그렇게하는 경우 (sender:)에는 조치 후 메소드 이름을 제거하십시오 .
  • handleTap방법 의 이름 은 임의적이었습니다. 원하는대로 이름을 지정하십시오 .action: #selector(someMethodName(sender:))

더 많은 예

이 뷰에 추가 한 동작 인식기를 연구하여 작동 방식을 확인할 수 있습니다.

여기에 이미지 설명을 입력하십시오

해당 프로젝트의 코드는 다음과 같습니다.

import UIKit
class ViewController: UIViewController {
    
    @IBOutlet weak var tapView: UIView!
    @IBOutlet weak var doubleTapView: UIView!
    @IBOutlet weak var longPressView: UIView!
    @IBOutlet weak var panView: UIView!
    @IBOutlet weak var swipeView: UIView!
    @IBOutlet weak var pinchView: UIView!
    @IBOutlet weak var rotateView: UIView!
    @IBOutlet weak var label: UILabel!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // Tap
        let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleTap))
        tapView.addGestureRecognizer(tapGesture)
        
        // Double Tap
        let doubleTapGesture = UITapGestureRecognizer(target: self, action: #selector(handleDoubleTap))
        doubleTapGesture.numberOfTapsRequired = 2
        doubleTapView.addGestureRecognizer(doubleTapGesture)
        
        // Long Press
        let longPressGesture = UILongPressGestureRecognizer(target: self, action: #selector(handleLongPress(gesture:)))
        longPressView.addGestureRecognizer(longPressGesture)
        
        // Pan
        let panGesture = UIPanGestureRecognizer(target: self, action: #selector(handlePan(gesture:)))
        panView.addGestureRecognizer(panGesture)
        
        // Swipe (right and left)
        let swipeRightGesture = UISwipeGestureRecognizer(target: self, action: #selector(handleSwipe(gesture:)))
        let swipeLeftGesture = UISwipeGestureRecognizer(target: self, action: #selector(handleSwipe(gesture:)))
        swipeRightGesture.direction = UISwipeGestureRecognizerDirection.right
        swipeLeftGesture.direction = UISwipeGestureRecognizerDirection.left
        swipeView.addGestureRecognizer(swipeRightGesture)
        swipeView.addGestureRecognizer(swipeLeftGesture)
        
        // Pinch
        let pinchGesture = UIPinchGestureRecognizer(target: self, action: #selector(handlePinch(gesture:)))
        pinchView.addGestureRecognizer(pinchGesture)
        
        // Rotate
        let rotateGesture = UIRotationGestureRecognizer(target: self, action: #selector(handleRotate(gesture:)))
        rotateView.addGestureRecognizer(rotateGesture)
        
    }
    
    // Tap action
    @objc func handleTap() {
        label.text = "Tap recognized"
        
        // example task: change background color
        if tapView.backgroundColor == UIColor.blue {
            tapView.backgroundColor = UIColor.red
        } else {
            tapView.backgroundColor = UIColor.blue
        }
        
    }
    
    // Double tap action
    @objc func handleDoubleTap() {
        label.text = "Double tap recognized"
        
        // example task: change background color
        if doubleTapView.backgroundColor == UIColor.yellow {
            doubleTapView.backgroundColor = UIColor.green
        } else {
            doubleTapView.backgroundColor = UIColor.yellow
        }
    }
    
    // Long press action
    @objc func handleLongPress(gesture: UILongPressGestureRecognizer) {
        label.text = "Long press recognized"
        
        // example task: show an alert
        if gesture.state == UIGestureRecognizerState.began {
            let alert = UIAlertController(title: "Long Press", message: "Can I help you?", preferredStyle: UIAlertControllerStyle.alert)
            alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.default, handler: nil))
            self.present(alert, animated: true, completion: nil)
        }
    }
    
    // Pan action
    @objc func handlePan(gesture: UIPanGestureRecognizer) {
        label.text = "Pan recognized"
        
        // example task: drag view
        let location = gesture.location(in: view) // root view
        panView.center = location
    }
    
    // Swipe action
    @objc func handleSwipe(gesture: UISwipeGestureRecognizer) {
        label.text = "Swipe recognized"
        
        // example task: animate view off screen
        let originalLocation = swipeView.center
        if gesture.direction == UISwipeGestureRecognizerDirection.right {
            UIView.animate(withDuration: 0.5, animations: {
                self.swipeView.center.x += self.view.bounds.width
            }, completion: { (value: Bool) in
                self.swipeView.center = originalLocation
            })
        } else if gesture.direction == UISwipeGestureRecognizerDirection.left {
            UIView.animate(withDuration: 0.5, animations: {
                self.swipeView.center.x -= self.view.bounds.width
            }, completion: { (value: Bool) in
                self.swipeView.center = originalLocation
            })
        }
    }
    
    // Pinch action
    @objc func handlePinch(gesture: UIPinchGestureRecognizer) {
        label.text = "Pinch recognized"
        
        if gesture.state == UIGestureRecognizerState.changed {
            let transform = CGAffineTransform(scaleX: gesture.scale, y: gesture.scale)
            pinchView.transform = transform
        }
    }
    
    // Rotate action
    @objc func handleRotate(gesture: UIRotationGestureRecognizer) {
        label.text = "Rotate recognized"
        
        if gesture.state == UIGestureRecognizerState.changed {
            let transform = CGAffineTransform(rotationAngle: gesture.rotation)
            rotateView.transform = transform
        }
    }
}

노트

  • 단일보기에 여러 제스처 인식기를 추가 할 수 있습니다. 단순화를 위해, 나는 그것을하지 않았습니다 (스 와이프 제스처 제외). 프로젝트에 필요한 경우 제스처 인식기 설명서를 읽어야합니다 . 상당히 이해하기 쉽고 도움이됩니다.
  • 위의 예제에서 알려진 문제 : (1) 팬보기는 다음 동작 이벤트에서 프레임을 재설정합니다. (2) 스 와이프보기는 첫 번째 스 와이프에서 잘못된 방향에서 나옵니다. (제 예제에서 이러한 버그는 제스처 인식기 작동 방식에 대한 이해에 영향을 미치지 않습니다.)

2
귀하의 답변은 정말 훌륭하고 자세한 설명에 도움이됩니다. 그리고 그것이 내가 투표를 한 이유는 당신도 대답합니다. 그러나 당신은 당신이 그것을 자세히 설명 할 때 답에 포함시켜야한다고 생각하는 한 가지 지침을 놓쳤습니다. 이 지침은 "<yourView> .EnableUserInteraction = TRUE"설정에 관한 것입니다. 나는 당신이 저에게 동의하기를 바랍니다.
어. Vihar

3
이 작업을 수행 UIView하려면 다음을 추가해야합니다.self.isUserInteractionEnabled = true;
neiker

52

간단하게 사용할 수 있다고 생각합니다

UIControl *headerView = ...
[headerView addTarget:self action:@selector(myEvent:) forControlEvents:UIControlEventTouchDown];

나는 headerView가 UIControl에서 확장된다는 것을 의미합니다.


7
이것이 더 나은 대답입니다. UITapGestureRecognizer의 대체품이 아닙니다 UIControlEventTouchDown. A는 Tap일반적으로 작곡 UIControlEventTouchDown하고 UIControlEventTouchUpInside.
ohho

62
A UIView는 a 가 아니므로에 UIControl액세스 할 수 없습니다 addTarget:action:forControlEvents:.
RobertJoseph

9
또한 UIControl은 UIView에서 상속합니다. 내 목적을 위해 서브 클래스 유형의 간단한 스위치였습니다.
pretzels1337

1
클래스를 UIControl @RobertJoseph로 설정할 수 있습니다. xib 파일로 이동하여 View Custom 클래스를 UIControl로 설정하십시오. 이제 이벤트를 처리 할 수 ​​있습니다 ..
Zar E Ahmer

2
그렇다면 탭을 처리하기 위해 상속을 변경했기 때문에 왜 이것이 더 나은 솔루션입니까?
Anthony Glyadchenko

21

스위프트 3 & 스위프트 4

import UIKit

extension UIView {
  func addTapGesture(tapNumber: Int, target: Any, action: Selector) {
    let tap = UITapGestureRecognizer(target: target, action: action)
    tap.numberOfTapsRequired = tapNumber
    addGestureRecognizer(tap)
    isUserInteractionEnabled = true
  }
}

사용하다

yourView.addTapGesture(tapNumber: 1, target: self, action: #selector(yourMethod))

감사. 잘 작동합니다!
Mikrasya

1
이거 너무 좋아! 모든 프로젝트에 추가;)
budidino

17

허용 된 답변 에 따라 매크로를 정의 할 수 있습니다.

#define handle_tap(view, delegate, selector) do {\
    view.userInteractionEnabled = YES;\
    [view addGestureRecognizer: [[UITapGestureRecognizer alloc] initWithTarget:delegate action:selector]];\
} while(0)

이 매크로는 ARC를 사용하므로 release호출 이 없습니다 .

매크로 사용 예 :

handle_tap(userpic, self, @selector(onTapUserpic:));

4
스토리 보드에서보기를 작성하는 경우 "사용자 상호 작용 사용"옵션을 사용하는 것을 잊지 마십시오.
david

여기서 .h 또는 .m에 매크로를 정의하고 매개 변수의 이름은 무엇이어야합니까? 평균 I #DEFINE handle_tap (UIView의 뷰 위임 대리인, SEL 선택기) 할 ..
자르 E Ahmer

8

코드에 Gesture Recogniser를 추가하여이를 달성 할 수 있습니다.

1 단계 : ViewController.m :

// Declare the Gesture.
UITapGestureRecognizer *gesRecognizer = [[UITapGestureRecognizer alloc] 
                                          initWithTarget:self 
                                          action:@selector(handleTap:)];
gesRecognizer.delegate = self;

// Add Gesture to your view.
[yourView addGestureRecognizer:gesRecognizer]; 

2 단계 : ViewController.m :

// Declare the Gesture Recogniser handler method.
- (void)handleTap:(UITapGestureRecognizer *)gestureRecognizer{
   NSLog(@"Tapped");
}

참고 : 여기 내 경우의 yourView는 @property (strong, nonatomic) IBOutlet UIView *localView;

편집 : * localView는 Main.storyboard의 흰색 상자입니다.

여기에 이미지 설명을 입력하십시오

여기에 이미지 설명을 입력하십시오


여러보기가 있으므로 발신자 ID를 사용할 수 있습니까 ??
Moin Shirazi

내부 하위 뷰로 이동 한 다음 발신자를 일시 중지 할 수 있습니다. [UIButton class]]) {// 특정 뷰로 이동 // 여기까지 도달했습니다. }}
Annu

8

에서 스위프트 4.2 및 엑스 코드 (10)

터치 이벤트를 추가 하려면 UITapGestureRecognizer 를 사용하십시오.

//Add tap gesture to your view
let tap = UITapGestureRecognizer(target: self, action: #selector(handleGesture))
yourView.addGestureRecognizer(tap)

// GestureRecognizer
@objc func handleGesture(gesture: UITapGestureRecognizer) -> Void {
//Write your code here
}

SharedClass 를 사용하려는 경우

//This is my shared class
import UIKit

class SharedClass: NSObject {

    static let sharedInstance = SharedClass()

    //Tap gesture function
    func addTapGesture(view: UIView, target: Any, action: Selector) {
        let tap = UITapGestureRecognizer(target: target, action: action)
        view.addGestureRecognizer(tap)
    }
} 

ViewController에 view1, view2 및 view3이라는 3 개의보기가 있습니다.

override func viewDidLoad() {
    super.viewDidLoad()
    //Add gestures to your views
    SharedClass.sharedInstance.addTapGesture(view: view1, target: self, action: #selector(handleGesture))
    SharedClass.sharedInstance.addTapGesture(view: view2, target: self, action: #selector(handleGesture))
    SharedClass.sharedInstance.addTapGesture(view: view3, target: self, action: #selector(handleGesture2))

}

// GestureRecognizer
@objc func handleGesture(gesture: UITapGestureRecognizer) -> Void {
    print("printed 1&2...")
}
// GestureRecognizer
@objc func handleGesture2(gesture: UITapGestureRecognizer) -> Void {
    print("printed3...")
}

6

스위프트 버전은 다음과 같습니다.

// MARK: Gesture Extensions
extension UIView {

    func addTapGesture(#tapNumber: Int, target: AnyObject, action: Selector) {
        let tap = UITapGestureRecognizer (target: target, action: action)
        tap.numberOfTapsRequired = tapNumber
        addGestureRecognizer(tap)
        userInteractionEnabled = true
    }

    func addTapGesture(#tapNumber: Int, action: ((UITapGestureRecognizer)->())?) {
        let tap = BlockTap (tapCount: tapNumber, fingerCount: 1, action: action)
        addGestureRecognizer(tap)
        userInteractionEnabled = true
    }
}

무엇 BlockTap입니까?
He Yifei 何 一 非

1
오, 그 부분을 잊었 어 사용자 정의 기능입니다. 여기 : github.com/goktugyil/EZSwiftExtensions/blob/master/Sources/…
Esqarrouth

5

스위프트 3 :

let tapGestureRecognizer: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(handleTapGestureRecognizer(_:)))
view.addGestureRecognizer(tapGestureRecognizer)

func handleTapGestureRecognizer(_ gestureRecognizer: UITapGestureRecognizer) {

}

1

요즘 꽤 간단한 것 같습니다. 이것은 스위프트 버전입니다.

let tap = UITapGestureRecognizer(target: self, action: #selector(viewTapped))
    view.addGestureRecognizer(tap)

@objc func viewTapped(recognizer: UIGestureRecognizer)
{
    //Do what you need to do!
}

0

여기 ios tapgesture가 있습니다. 먼저 아래와 같이 동작 아래에 아래 코드를 작성한 후 GestureRecognizer에 대한 동작을 만들어야합니다.

- (IBAction)tapgesture:(id)sender

{


[_password resignFirstResponder];


[_username resignFirstResponder];

NSLog(@" TapGestureRecognizer  tapped");

}

0

또 다른 방법은 투명 버튼을 뷰에 추가하는 것입니다

UIButton *b = [UIButton buttonWithType:UIButtonTypeCustom];
b.frame = CGRectMake(0, 0, headerView.width, headerView.height);
[headerView addSubview:b];
[b addTarget:self action:@selector(buttonClicked:) forControlEvents:UIControlEventTouchDown];

그런 다음 클릭을 처리하십시오.

- (void)buttonClicked:(id)sender
{}

0

와 같은 터치 이벤트를 구현할 제스처 인식기 (하위 클래스)를 만듭니다 touchesBegan. 그 후에 뷰에 추가 할 수 있습니다.

이 방법으로 컴포지션을 서브 클래 싱 (요청) 대신 사용합니다.


0

SSEventListener를 사용해보십시오 .

제스처 인식기를 만들고 로직을 다른 방법으로 분리 할 필요가 없습니다. SSEventListener단일 탭 제스처, 더블 탭 제스처 및 원하는 경우 N 탭 제스처, 길게 누르기 제스처를 수신하도록보기에서 리스너 블록 설정을 지원합니다. 단일 탭 제스처 리스너를 설정하면 다음과 같이됩니다.

[view ss_addTapViewEventListener:^(UITapGestureRecognizer *recognizer) { ... } numberOfTapsRequired:1];


0

목표 -C :

UIControl *headerView = [[UIControl alloc] initWithFrame:CGRectMake(0, 0, tableView.bounds.size.width, nextY)];
[headerView addTarget:self action:@selector(myEvent:) forControlEvents:UIControlEventTouchDown];

빠른:

let headerView = UIControl(frame: CGRect(x: 0, y: 0, width: tableView.bounds.size.width, height: nextY))
headerView.addTarget(self, action: #selector(myEvent(_:)), for: .touchDown)

질문은 다음과 같이 묻습니다.

UIView에 터치 이벤트를 어떻게 추가 합니까?

이벤트를 요구하지 않습니다 .

특히 OP는 구현을 원합니다 UIControlEventTouchDown

전환 UIView에를 UIControl정답이 여기 이유로 인해 사용 Gesture Recognisers에 대해 아무것도 모르는 .touchDown, .touchUpInside, .touchUpOutside

또한 UIControl은 UIView에서 상속되므로 기능을 잃지 않습니다.

원하는 것이 탭이면 제스처 인식기를 사용할 수 있습니다. 그러나이 질문에서와 같이 더 세밀한 제어를 원하면 UIControl이 필요합니다.

https://developer.apple.com/documentation/uikit/uicontrol?language=objc https://developer.apple.com/documentation/uikit/uigesturerecognizer?language=objc

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.