[ios] UICollectionViewCell에서 길게 누르기 제스처

UICollectionView의 (하위 클래스)에 길게 누르기 제스처 인식기를 추가하는 방법을 궁금합니다. 문서에서 기본적으로 추가된다는 것을 읽었지만 방법을 알 수 없습니다.

내가하고 싶은 것은 셀을 길게 누르고 ( github에서 캘린더가 있습니다 ) 어떤 셀을 탭했는지 확인한 다음 작업을 수행합니다. 어떤 세포가 오래 눌 렸는지 알아야합니다. 이 광범위한 질문에 대해 죄송하지만 Google 또는 SO에서 더 나은 것을 찾을 수 없습니다.



답변

목표 -C

당신에 myCollectionViewController.h파일 추가 UIGestureRecognizerDelegate프로토콜을

@interface myCollectionViewController : UICollectionViewController<UIGestureRecognizerDelegate>

당신의 myCollectionViewController.m파일 :

- (void)viewDidLoad
{
    // attach long press gesture to collectionView
    UILongPressGestureRecognizer *lpgr
       = [[UILongPressGestureRecognizer alloc]
                     initWithTarget:self action:@selector(handleLongPress:)];
    lpgr.delegate = self;
    lpgr.delaysTouchesBegan = YES;
    [self.collectionView addGestureRecognizer:lpgr];
}

-(void)handleLongPress:(UILongPressGestureRecognizer *)gestureRecognizer
{
    if (gestureRecognizer.state != UIGestureRecognizerStateEnded) {
        return;
    }
    CGPoint p = [gestureRecognizer locationInView:self.collectionView];

    NSIndexPath *indexPath = [self.collectionView indexPathForItemAtPoint:p];
    if (indexPath == nil){
        NSLog(@"couldn't find index path");
    } else {
        // get the cell at indexPath (the one you long pressed)
        UICollectionViewCell* cell =
        [self.collectionView cellForItemAtIndexPath:indexPath];
        // do stuff with the cell
    }
}

빠른

class Some {

    @objc func handleLongPress(gesture : UILongPressGestureRecognizer!) {
        if gesture.state != .Ended {
            return
        }
        let p = gesture.locationInView(self.collectionView)

        if let indexPath = self.collectionView.indexPathForItemAtPoint(p) {
            // get the cell at indexPath (the one you long pressed)
            let cell = self.collectionView.cellForItemAtIndexPath(indexPath)
            // do stuff with the cell
        } else {
            print("couldn't find index path")
        }
    }
}

let some = Some()
let lpgr = UILongPressGestureRecognizer(target: some, action: #selector(Some.handleLongPress))

스위프트 4

class Some {

    @objc func handleLongPress(gesture : UILongPressGestureRecognizer!) {
        if gesture.state != .ended {
            return
        }

        let p = gesture.location(in: self.collectionView)

        if let indexPath = self.collectionView.indexPathForItem(at: p) {
            // get the cell at indexPath (the one you long pressed) 
            let cell = self.collectionView.cellForItem(at: indexPath)
            // do stuff with the cell 
        } else {
            print("couldn't find index path")
        }
    }
}

let some = Some()
let lpgr = UILongPressGestureRecognizer(target: some, action: #selector(Some.handleLongPress))


답변

Swift에 대한 동일한 코드 @abbood의 코드 :

viewDidLoad에서 :

let lpgr : UILongPressGestureRecognizer = UILongPressGestureRecognizer(target: self, action: "handleLongPress:")
lpgr.minimumPressDuration = 0.5
lpgr.delegate = self
lpgr.delaysTouchesBegan = true
self.collectionView?.addGestureRecognizer(lpgr)

그리고 기능 :

func handleLongPress(gestureRecognizer : UILongPressGestureRecognizer){

    if (gestureRecognizer.state != UIGestureRecognizerState.Ended){
        return
    }

    let p = gestureRecognizer.locationInView(self.collectionView)

    if let indexPath : NSIndexPath = (self.collectionView?.indexPathForItemAtPoint(p))!{
        //do whatever you need to do
    }

}

대표자를 잊지 마세요 UIGestureRecognizerDelegate


답변

UICollectionView의 대리자를 사용하여 길게 누르기 이벤트 수신

아래 3 가지 방법을 단순화해야합니다.

//UICollectionView menu delegate
- (BOOL)collectionView:(UICollectionView *)collectionView shouldShowMenuForItemAtIndexPath:(NSIndexPath *)indexPath{

   //Do something

   return YES;
}
- (BOOL)collectionView:(UICollectionView *)collectionView canPerformAction:(SEL)action forItemAtIndexPath:(NSIndexPath *)indexPath withSender:(nullable id)sender{
    //do nothing
    return NO;
}

- (void)collectionView:(UICollectionView *)collectionView performAction:(SEL)action forItemAtIndexPath:(NSIndexPath *)indexPath withSender:(nullable id)sender{
    //do nothing
}


답변

여기 답변은 올바른 인식 사용자 정의 길게 누르 제스처 추가 그러나 문서에 따라 여기를 :의 부모 클래스 UICollectionView클래스가 설치 default long-press gesture recognizer당신이 당신의 콜렉션 뷰와 관련된 기본 인식에 사용자 정의 탭 제스처 인식기를 연결해야합니다 있도록 스크롤 상호 작용을 처리합니다.

다음 코드는 사용자 정의 제스처 인식기가 기본 인식기를 방해하지 않도록합니다.

UILongPressGestureRecognizer* longPressGesture = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handleLongPressGesture:)];

longPressGesture.minimumPressDuration = .5; //seconds
longPressGesture.delegate = self;

// Make the default gesture recognizer wait until the custom one fails.
for (UIGestureRecognizer* aRecognizer in [self.collectionView gestureRecognizers]) {
   if ([aRecognizer isKindOfClass:[UILongPressGestureRecognizer class]])
      [aRecognizer requireGestureRecognizerToFail:longPressGesture];
} 


답변

UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPress:)];

[cell addGestureRecognizer:longPress];

다음과 같은 방법을 추가하십시오.

- (void)longPress:(UILongPressGestureRecognizer*)gesture
{
    if ( gesture.state == UIGestureRecognizerStateEnded ) {

        UICollectionViewCell *cellLongPressed = (UICollectionViewCell *) gesture.view;
    }
}


답변

외부 제스처 인식기를 갖고 UICollectionView에서 내부 제스처 인식기와 충돌하지 않으려면 다음을 수행해야합니다.

제스처 인식기를 추가하고 설정하고 어딘가에 대한 참조를 캡처합니다 (UICollectionView를 서브 클래 싱 한 경우 가장 좋은 옵션은 서브 클래스에 있습니다).

@interface UICollectionViewSubclass : UICollectionView <UIGestureRecognizerDelegate>

@property (strong, nonatomic, readonly) UILongPressGestureRecognizer *longPressGestureRecognizer;

@end

기본 초기화 방법을 재정의 initWithFrame:collectionViewLayout:하고 initWithCoder:길게 누르기 제스처 인식기에 대한 설정 방법 추가

@implementation UICollectionViewSubclass

-(instancetype)initWithFrame:(CGRect)frame collectionViewLayout:(UICollectionViewLayout *)layout
{
    if (self = [super initWithFrame:frame collectionViewLayout:layout]) {
        [self setupLongPressGestureRecognizer];
    }
    return self;
}

-(instancetype)initWithCoder:(NSCoder *)aDecoder
{
    if (self = [super initWithCoder:aDecoder]) {
        [self setupLongPressGestureRecognizer];
    }
    return self;
}

@end

길게 누르기 제스처 인식기를 인스턴스화하고, 대리자를 설정하고, UICollectionView 제스처 인식기를 사용하여 종속성을 설정하도록 설정 메서드를 작성하고 (따라서 기본 제스처가되고 다른 모든 제스처는 해당 제스처가 인식되기 전에 실패 할 때까지 기다림)보기에 제스처를 추가합니다.

-(void)setupLongPressGestureRecognizer
{
    _longPressGestureRecognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self
                                                                                action:@selector(handleLongPressGesture:)];
    _longPressGestureRecognizer.delegate = self;

    for (UIGestureRecognizer *gestureRecognizer in self.collectionView.gestureRecognizers) {
        if ([gestureRecognizer isKindOfClass:[UILongPressGestureRecognizer class]]) {
            [gestureRecognizer requireGestureRecognizerToFail:_longPressGestureRecognizer];
        }
    }

    [self.collectionView addGestureRecognizer:_longPressGestureRecognizer];
}

또한 해당 제스처에 실패하고 동시 인식을 허용하는 UIGestureRecognizerDelegate 메서드를 구현하는 것을 잊지 마십시오 (구현할 필요가있을 수도 있고 필요하지 않을 수도 있으며, 보유한 다른 제스처 인식기 또는 내부 제스처 인식기와의 종속성에 따라 다름).

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
    if ([self.longPressGestureRecognizer isEqual:gestureRecognizer]) {
        return NO;
    }

    return NO;
}

이에 대한 자격 증명은 LXReorderableCollectionViewFlowLayout의 내부 구현으로 이동합니다.


답변

스위프트 5 :

private func setupLongGestureRecognizerOnCollection() {
    let longPressedGesture = UILongPressGestureRecognizer(target: self, action: #selector(handleLongPress(gestureRecognizer:)))
    longPressedGesture.minimumPressDuration = 0.5
    longPressedGesture.delegate = self
    longPressedGesture.delaysTouchesBegan = true
    collectionView?.addGestureRecognizer(longPressedGesture)
}

@objc func handleLongPress(gestureRecognizer: UILongPressGestureRecognizer) {
    if (gestureRecognizer.state != .began) {
        return
    }

    let p = gestureRecognizer.location(in: collectionView)

    if let indexPath = collectionView?.indexPathForItem(at: p) {
        print("Long press at item: \(indexPath.row)")
    }
}

또한 UIGestureRecognizerDelegate를 구현하고 viewDidLoad 또는 호출이 필요한 곳에서 setupLongGestureRecognizerOnCollection을 호출하는 것을 잊지 마십시오.