[ios] 투명한 UIView 뒤의 버튼을 어떻게 클릭합니까?

하나의 하위보기가있는보기 컨트롤러가 있다고 가정 해 봅시다. 서브 뷰는 모든면에서 100 픽셀의 여백으로 화면 중앙을 차지합니다. 그런 다음 하위 뷰 내부를 클릭하기 위해 작은 것들을 추가합니다. 우리는 새로운 프레임을 이용하기 위해 서브 뷰만을 사용하고 있습니다 (서브 뷰 내에서 x = 0, y = 0은 실제로는 부모 뷰에서 100,100입니다).

그런 다음 메뉴와 같이 하위 뷰 뒤에 무언가가 있다고 상상해보십시오. 사용자가 하위보기에서 “작은 물건”을 선택할 수 있기를 원하지만 아무 것도 없으면 터치가 뒤에 배경으로 전달됩니다 (배경이 분명하기 때문에).

어떻게해야합니까? 터치가 시작된 것처럼 보이지만 버튼이 작동하지 않습니다.



답변

컨테이너에 대한 사용자 지정보기를 만들고 pointInside : 메시지를 재정 의하여 포인트가 다음과 같이 적격 한 자식보기 내에 있지 않은 경우 false를 반환합니다.

빠른:

class PassThroughView: UIView {
    override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
        for subview in subviews {
            if !subview.isHidden && subview.isUserInteractionEnabled && subview.point(inside: convert(point, to: subview), with: event) {
                return true
            }
        }
        return false
    }
}

목표 C :

@interface PassthroughView : UIView
@end

@implementation PassthroughView
-(BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event {
    for (UIView *view in self.subviews) {
        if (!view.hidden && view.userInteractionEnabled && [view pointInside:[self convertPoint:point toView:view] withEvent:event])
            return YES;
    }
    return NO;
}
@end

이 뷰를 컨테이너로 사용하면 모든 자식이 터치를받을 수 있지만 뷰 자체는 이벤트에 투명합니다.


답변

나는 또한 사용

myView.userInteractionEnabled = NO;

서브 클래스 할 필요가 없습니다. 잘 작동합니다.


답변

Apple에서 :

이벤트 전달은 일부 응용 프로그램에서 사용하는 기술입니다. 다른 응답자 오브젝트의 이벤트 처리 메소드를 호출하여 터치 이벤트를 전달합니다. 이것이 효과적인 기술 일 수 있지만주의해서 사용해야합니다. UIKit 프레임 워크의 클래스는 바인딩되지 않은 터치를 수신하도록 설계되지 않았습니다 …. 애플리케이션에서 다른 응답자에게 조건부로 터치를 전달하려면 이러한 응답자는 모두 고유 한 UIView 서브 클래스의 인스턴스 여야합니다.

사과 모범 사례 :

응답자 체인에 이벤트를 명시 적으로 보내지 마십시오 (NextResponder를 통해). 대신, 수퍼 클래스 구현을 호출하고 UIKit이 응답자 체인 탐색을 처리하게하십시오.

대신 다음을 무시할 수 있습니다.

-(BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event

터치를 응답자 체인으로 보내려면 (아니면 아무것도없는 뷰 뒤의 뷰에) 원하는 경우 UIView 하위 클래스에서 NO를 반환하십시오.


답변

훨씬 간단한 방법은 인터페이스 빌더에서 사용자 상호 작용을 “체크 해제”하는 것입니다. “스토리 보드를 사용하는 경우”

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


답변

John이 게시 한 내용을 기반으로 다음은 터치 이벤트가 버튼을 제외한 뷰의 모든 하위 뷰를 통과 할 수있는 예입니다.

-(BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
{
    // Allow buttons to receive press events.  All other views will get ignored
    for( id foundView in self.subviews )
    {
        if( [foundView isKindOfClass:[UIButton class]] )
        {
            UIButton *foundButton = foundView;

            if( foundButton.isEnabled  &&  !foundButton.hidden &&  [foundButton pointInside:[self convertPoint:point toView:foundButton] withEvent:event] )
                return YES;
        }
    }
    return NO;
}


답변

최근에 나는 그것을 도와 줄 수업을 썼습니다. UIButton또는 사용자 정의 클래스로 사용 하거나 UIView투명 픽셀에서 실행 된 터치 이벤트를 전달합니다.

이 솔루션은 UIButton반투명 아래에있는 버튼을 클릭 할 수 있지만 투명 UIView하지 않은 부분은 UIView터치 이벤트에 계속 반응 하므로 허용 된 답변보다 다소 낫습니다 .

GIF

GIF에서 볼 수 있듯이 기린 버튼은 단순한 사각형이지만 투명한 영역의 터치 이벤트는 UIButton아래 의 노란색으로 전달됩니다 .

수업 링크


답변

최고 투표 솔루션이 저에게 완전히 효과가 없었습니다 .TabBarController를 계층 구조에 넣었 기 때문에 (댓글 중 하나가 지적한 것처럼) 실제로 UI의 일부 부분에 대한 터치를 전달했지만 내 엉망이었습니다. 터치 이벤트를 가로 채는 tableView의 기능, 마지막으로 터치 테스트 를 무시하고 있었지만 터치를 무시하고 해당 뷰의 하위 뷰가 처리하도록했습니다.

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event{
    UIView *view = [super hitTest:point withEvent:event];
    if (view == self) {
        return nil; //avoid delivering touch events to the container view (self)
    }
    else{
        return view; //the subviews will still receive touch events
    }
}