programing

UITapGestureRecognizer가 UITableView didSelectRowAt를 중단합니다.인덱스 패스

i4 2023. 4. 21. 20:13
반응형

UITapGestureRecognizer가 UITableView didSelectRowAt를 중단합니다.인덱스 패스

키보드가 뜨면 텍스트 필드를 위로 스크롤하는 기능을 직접 작성했습니다.스 by드 a a a a a a a a a a a a a a a a a a a a a a를 했습니다.UITapGestureRecognizer텍스트 필드에 있는 긴급 응답자를 탭할 때 사임시키는 역할을 합니다.

그럼 이 에 ''을.UITableView사용자가 텍스트를 입력할 때 텍스트 필드 바로 아래에 항목을 채웁니다.

내의 중 , " " " " 입니다.didSelectRowAtIndexPath을 사용하다대신 탭 제스처 인식기가 호출되어 첫 번째 응답 측만 종료됩니다.

제스처 에 탭 할 수 있는 것 UITableView★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★어떤 도움이라도 주시면 감사하겠습니다.

좋아, 제스처 인식기 문서를 뒤진 끝에 드디어 찾았어

해결방법은 도입하는 것이었습니다.UIGestureRecognizerDelegate다음 항목을 추가합니다.

#pragma mark UIGestureRecognizerDelegate methods
    
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
  if ([touch.view isDescendantOfView:autocompleteTableView]) {
            
    // Don't let selections of auto-complete entries fire the 
    // gesture recognizer
    return NO;
  }
        
  return YES;
}

이제 해결됐네요.이것이 다른 사람들에게도 도움이 되기를 바란다.

이 문제를 해결하는 가장 쉬운 방법은 다음과 같습니다.

UITapGestureRecognizer *tapRec = [[UITapGestureRecognizer alloc] 
    initWithTarget:self action:@selector(tap:)];
[tapRec setCancelsTouchesInView:NO];

에 의해, 「」는UIGestureRecognizer탭을 인식하고 터치를 다음 응답자에게 전달합니다.이 의도하지 않은 를 초래하게 것은, 만약 이 이 방법이 , 라고 하는 것입니다.UITableViewCell른른른사용자가 행을 탭하여 키보드를 해제하면 키보드와 푸시가 모두 인식됩니다.이것이 당신의 의도라고는 생각하지 않지만, 이 방법은 많은 경우에 적합합니다.

또한 Robert의 답변을 확장하면 해당 테이블 뷰에 대한 포인터가 있으면 문자열로 변환하지 않고 클래스를 직접 비교할 수 있으며 애플이 명명법을 변경하지 않기를 바랄 수 있습니다.

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer 
     shouldReceiveTouch:(UITouch *)touch
{
    if([touch.view class] == tableview.class){
        return //YES/NO
    }

    return //YES/NO

}

「」도 할 필요가 있습니다.★★★★★★★★★★★★★★★★★★,UIGestureRecognizer이 코드를 가진 대리인을 불러야 합니다.

★★cancelsTouchesInView이치노그렇지 않으면 터치 자체가 "소비"되어 테이블 뷰에 전달되지 않습니다.★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★

를 들면, 「 」의 경우swift

let tapOnScreen: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: "CheckTheTime")
tapOnScreen.cancelsTouchesInView = false
view.addGestureRecognizer(tapOnScreen)

Swift의 경우(@Jason의 답변에 기초함):

class MyAwesomeClass: UIViewController, UIGestureRecognizerDelegate

private var tap: UITapGestureRecognizer!

override func viewDidLoad() {
   super.viewDidLoad()

   self.tap = UITapGestureRecognizer(target: self, action: "viewTapped:")
   self.tap.delegate = self
   self.view.addGestureRecognizer(self.tap)
}

// UIGestureRecognizerDelegate method
func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldReceiveTouch touch: UITouch) -> Bool {
    if touch.view?.isDescendantOfView(self.tableView) == true {
        return false
    }
    return true
}

테이블 뷰 위에 탭 제스처를 추가하면서도 셀 선택을 동시에 허용하는 더 나은 솔루션이 있을 수 있습니다.

func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldReceiveTouch touch: UITouch) -> Bool {
    if gestureRecognizer is UITapGestureRecognizer {
        let location = touch.locationInView(tableView)
        return (tableView.indexPathForRowAtPoint(location) == nil)
    }
    return true
}

사용자가 탭하고 있는 화면의 포인트에서 셀을 클릭합니다.인덱스 경로를 찾을 수 없는 경우 제스처가 터치를 수신하도록 했습니다.그렇지 않으면 취소하겠습니다.나한테는 잘 돼.

을 쓸 만, 설정하기만 됩니다.cancelsTouchesInView로로 합니다.false오브젝트의 로는 """입니다.true 돼요.false 를를 . . . .를 하는 경우UITapGesture및 using use " " " " " 。UIScrollView으로 이 (tableview, collectionview)을 합니다.false

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

은 '실행하다' 입니다.gestureRecognizer:shouldReceiveTouch:보기의 클래스를 사용하여 수행할 작업을 결정합니다.이 접근방식은 테이블을 직접 둘러싼 영역의 탭을 마스킹하지 않는다는 장점이 있습니다(이러한 영역의 뷰는 UITableView인스턴스에서 계속 내려오지만 셀을 나타내지 않습니다).

또한 코드를 추가하지 않고도 단일 뷰에서 여러 테이블을 사용할 수 있다는 이점도 있습니다.

경고: Apple이 클래스 이름을 변경하지 않을 것이라는 가정이 있습니다.

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
    return ![NSStringFromClass([touch.view class]) isEqualToString:@"UITableViewCellContentView"];
}

Swift 4.2의 경우 솔루션은UIGestureRecognizerDelegate다음 항목을 추가합니다.

extension ViewController : UIGestureRecognizerDelegate {
    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
        if touch.view!.isDescendant(of: tblView) {
            return false
        }
        return true
    }
}

하면 이 하고 false가 반환됩니다.didSelectRowAtIndexPath★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★

터치 제스처 기능은 사용자가 테이블 뷰 밖으로 탭 했을 때만 호출하고 싶은 상황이었습니다.사용자가 테이블 뷰 내부를 탭한 경우 터치 제스처 기능을 호출하면 안 됩니다.또한 터치 제스처 기능이 호출된 경우에도 터치 이벤트를 소비하지 않고 터치된 뷰로 전달합니다.

결과 코드는 Abdulrahman Masoud의 답변과 Nikolaj Nielsen의 답변의 조합입니다.

extension MyViewController: UIGestureRecognizerDelegate {
    func addGestureRecognizer() {
        let tapOnScreen = UITapGestureRecognizer(target: self,
                                                action: #selector(functionToCallWhenUserTapsOutsideOfTableView))

        // stop the gesture recognizer from "consuming" the touch event, 
        // so that the touch event can reach other buttons on view.
        tapOnScreen.cancelsTouchesInView = false

        tapOnScreen.delegate = self

        self.view.addGestureRecognizer(tapOnScreen)
    }

    // if your tap event is on the menu, don't run the touch event.
    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
        if touch.view?.isDescendant(of: self.tableView) == true {
            return false
        }
        return true
    }

    @objc func functionToCallWhenUserTapsOutsideOfTableView() {

        print("user tapped outside table view")
    }
}

★★★★★★★★★★★★★★★★★★★★★★★★에MyViewController, '클래스'UITableView , 의onViewDidLoad() 제가 꼭 를 드렸거든요.addGestureRecognizer()

class MyViewController: UIViewController {
    ...
    override func viewDidLoad() {
        super.viewDidLoad()
        ...
        self.addGestureRecognizer()
        ...
    }
    ...
}

★★★★★★★★★★를 설정해 주세요.cancels touches in view로로 합니다.false" " " " 에 있는 제스처에 "(table/collection)View:

- 인터페이스빌더

인터페이스빌더

- 코드

<#gestureRecognizer#>.cancelsTouchesInView = false

스위프트 5, 2020년 5월

텍스트를 입력하면 표시되는 textField와 tableView가 있습니다.

초기 상태 tableViewCell 또는 다른 것을 탭할 때 2개의 다른 이벤트를 원합니다.

키보드와 tableView가 표시됩니다.

먼저 tapGestureRecognizer를 추가합니다.

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

@objc func viewTapped() {
        view.endEditing(true)
}

다음으로 다음 체크를 UIGesture RecognizerDelegate에 추가합니다.

    extension StadtViewController: UIGestureRecognizerDelegate {
    
    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
        if touch.view?.isDescendant(of: self.tableView) == true {
            return false
        } else {
            view.endEditing(true)
            return true
        }
    }
}

먼저 키보드를 숨기려면 tableView가 계속 표시되고 탭이 응답합니다.

여기에 이미지 설명 입력

간단한 솔루션은 UITableViewCell의 UIControl 인스턴스를 사용하여 조작하는 것입니다.사용자와 함께 보기를 추가할 수 있습니다.InteractionEnableds == 탭을 얻기 위해 UIControl에 NO를 사용할 수 있습니다.

Swift 5의 Collection View의 경우:

func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldReceiveTouch touch: UITouch) -> Bool {
    if gestureRecognizer is UITapGestureRecognizer {
        let location = touch.location(in: mCollectionView)
        return (mCollectionView.indexPathForItem(at: location) == nil)
    }
    return true
}

시간이 늦었고 많은 사람들이 위의 제안들이 잘 작동한다고 생각하지만, 저는 Jason이나 Tmilligan의 방법을 사용할 수 없었습니다.

숫자 키보드만 사용하여 숫자 입력을 받는 textFields를 포함하는 여러 셀이 포함된 정적 tableView가 있습니다.이것은 나에게 이상적이었다.

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
    if(![touch.view isKindOfClass:[UITableViewCell class]]){

        [self.firstTF resignFirstResponder];
        [self.secondTF resignFirstResponder];
        [self.thirdTF resignFirstResponder];
        [self.fourthTF resignFirstResponder];

        NSLog(@"Touches Work ");

        return NO;
    }
    return YES;
}

이 기능을 해야 합니다.<UIGestureRecognizerDelegate>h "H" "H"

행 이![touch.view isKindOfClass:[UITableViewCell class]]키보드를 합니다.tableViewCell은 활성화되지 않았습니다.

스위프트를 위한 솔루션은 2021년에 작동한다.이 솔루션에서는 테이블 뷰에 대한 참조가 필요하지 않습니다.

func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
    //return !(touch.view is UITableViewCell) <-- doesn't work, the type of the touched class is not UITableViewCell anymore
    
    var v = touch.view
    while v != nil {
        if v is UITableView { return false }
        v = v?.superview
    }
    return true
}

사용방법:

let gestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(YOUR_METHOD))
gestureRecognizer.delegate = self
YOUR_VIEW.addGestureRecognizer(gestureRecognizer)

다음은 인식자의 shouldReceiveTouch를 키보드의 표시 여부에 직접 연결하는 솔루션입니다.

탭 제스처 인식자 위임:

#pragma mark - UIGestureRecognizerDelegate

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
    if ([PFXKeyboardStateListener sharedInstance].visible) {
        return YES;
    }

    return NO;
}

★★★★★★★★★★★★★★★★.PFXKeyboardStateListener.h:

@interface PFXKeyboardStateListener : NSObject
{
    BOOL _isVisible;
}

+ (PFXKeyboardStateListener *)sharedInstance;

@property (nonatomic, readonly, getter=isVisible) BOOL visible;

@end

★★★★★★★★★★★★★★★★.PFXKeyboardStateListener.m:

static PFXKeyboardStateListener *sharedInstance;

@implementation PFXKeyboardStateListener

+ (PFXKeyboardStateListener *)sharedInstance
{
    return sharedInstance;
}

+ (void)load
{
    @autoreleasepool {
        sharedInstance = [[self alloc] init];
    }
}

- (void)dealloc
{
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

- (BOOL)isVisible
{
    return _isVisible;
}

- (void)didShow
{
    _isVisible = YES;
}

- (void)didHide
{
    _isVisible = NO;
}

- (id)init
{
    if ((self = [super init])) {
        NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
        [center addObserver:self selector:@selector(didShow) name:UIKeyboardDidShowNotification object:nil];
        [center addObserver:self selector:@selector(didHide) name:UIKeyboardWillHideNotification object:nil];
    }
    return self;
}

@end

키보드 청취자의 싱글톤 패턴을 갱신하는 것이 좋을지도 모릅니다만, 아직 잘 모릅니다.나처럼 다른 모든 사람에게도 효과가 있기를 바랍니다.^^

UIGesture Recognizer 위임에 대해 다음 방법을 구현합니다.

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
       shouldReceiveTouch:(UITouch *)touch
{
  UIView *superview = touch.view;
  do {
    superview = superview.superview;
    if ([superview isKindOfClass:[UITableViewCell class]])
      return NO;
  } while (superview && ![superview isKindOfClass:[UITableView class]]);

  return superview != nil;
}

나의 경우는 Uisearch bar와 uitable view on self.view를 포함하여 달랐다.화면을 터치하여 Uisearchbar 키보드를 해제하고 싶었습니다.

var tapGestureRecognizer:UITapGestureRecognizer?

override func viewWillAppear(animated: Bool) {
    tapGestureRecognizer = UITapGestureRecognizer(target: self, action:Selector("handleTap:"))
}

UISearchBar 위임 방식:

func searchBarShouldBeginEditing(searchBar: UISearchBar) -> Bool {
    view.addGestureRecognizer(tapGestureRecognizer!)
    return true
}
func searchBarShouldEndEditing(searchBar: UISearchBar) -> Bool {
    view.removeGestureRecognizer(tapGestureRecognizer!)
    return true
}

사용자가 Self에 터치 시.표시:

func handleTap(recognizer: UITapGestureRecognizer) {
    sampleSearchBar.endEditing(true)
    sampleSearchBar.resignFirstResponder()
}

안에서 바로 사용하실 수 있습니다.

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    if CheckTheTime() == true {
        // do something 
    }else{
    }
}

func CheckTheTime() -> Bool{
    return true
}

이것은 위의 답변에 근거한 저의 해결책입니다.나한테는 효과가 있었어...

//Create tap gesture for menu transparent view
UITapGestureRecognizer *rightTableTransparentViewTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(rightTableTransparentViewTapMethod:)];
[rightTableTransparentViewTap setCancelsTouchesInView:NO];
[_rightTableTransparentView addGestureRecognizer:rightTableTransparentViewTap];

- (void)rightTableTransparentViewTapMethod:(UITapGestureRecognizer *)recognizer {
    //Write your code here
}

문제: 제 경우, 처음에 각 컬렉션에 버튼을 배치하고 셀을 채우도록 제약조건을 설정하여 셀을 클릭하면 해당 셀이 클릭되도록 설정했지만 버튼이 비어 있어 아무 일도 일어나지 않았습니다.

픽스: 컬렉션 뷰 셀에서 버튼을 삭제하여 이 문제를 해결했습니다.

언급URL : https://stackoverflow.com/questions/8192480/uitapgesturerecognizer-breaks-uitableview-didselectrowatindexpath

반응형