iOS - пересылать все касания через вид - PullRequest
121 голосов
/ 30 сентября 2010

У меня есть вид, наложенный поверх многих других видов.Я использую только избыточно для обнаружения некоторого количества касаний на экране, но кроме этого я не хочу, чтобы представление останавливало поведение других представлений внизу, таких как прокрутки и т.д.это наложение вид?Это подкласс UIView.

Ответы [ 9 ]

103 голосов
/ 10 сентября 2012

Для передачи касаний из наложенного вида в представления внизу, реализуйте следующий метод в UIView:

Objective-C:

- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event {
    NSLog(@"Passing all touches to the next view (if any), in the view stack.");
    return NO;
}

Swift:

override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
    print("Passing all touches to the next view (if any), in the view stack.")
    return false
}
93 голосов
/ 26 августа 2013
myWebView.userInteractionEnabled = NO;

все, что мне было нужно!

51 голосов
/ 29 января 2014

Это старая ветка, но она возникла при поиске, поэтому я решил добавить свой 2c.У меня есть покрытие UIView с подпредставлениями, и я хочу перехватывать только те касания, которые поражают одно из подпредставлений, поэтому я изменил ответ PixelCloudSt на

-(BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
{
    for (UIView* subview in self.subviews ) {
        if ( [subview hitTest:[self convertPoint:point toView:subview] withEvent:event] != nil ) {
            return YES;
        }
    }
    return NO;
}
31 голосов
/ 25 января 2017

Улучшена версия ответа @fresidue. Вы можете использовать этот подкласс UIView в качестве прозрачного представления, передавая прикосновения вне его подпредставления. Реализация в Objective-C :

@interface PassthroughView : UIView

@end

@implementation PassthroughView

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

@end

и Swift:

class PassthroughView: UIView {
  override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
    return subviews.contains(where: {
      !$0.isHidden && $0.point(inside: self.convert(point, to: $0), with: event)
    })
  }
}
5 голосов
/ 30 апреля 2016

У меня была похожая проблема с UIStackView (но может быть любое другое представление). Моя конфигурация была следующей: View controller with containerView and StackView

Это классический случай, когда у меня есть контейнер, который нужно было разместить на заднем плане, с кнопками сбоку. Для макета я включил кнопки в UIStackView, но теперь средняя (пустая) часть stackView перехватывает прикосновения: - (

Что я сделал, так это создал подкласс UIStackView со свойством, определяющим подвид, который должен быть сенсорным. Теперь любое прикосновение к боковым кнопкам (включенным в массив * viewsWithActiveTouch *) будет предоставлено кнопкам, в то время как любое прикосновение к стековому обзору в любом месте, кроме этих представлений, не будет перехвачено и, следовательно, передано любому объекту ниже стека вид.

/** Subclass of UIStackView that does not accept touches, except for specific subviews given in the viewsWithActiveTouch array */
class NoTouchStackView: UIStackView {

  var viewsWithActiveTouch: [UIView]?

  override func hitTest(point: CGPoint, withEvent event: UIEvent?) -> UIView? {

    if let activeViews = viewsWithActiveTouch {
        for view in activeViews {
           if CGRectContainsPoint(view.frame, point) {
                return view

           }
        }
     }
     return nil
   }
}
5 голосов
/ 31 января 2011

Если представление, которому вы хотите переслать касания, не является подпредставлением / суперпредставлением, вы можете настроить собственное свойство в своем подклассе UIView следующим образом:

@interface SomeViewSubclass : UIView {

    id forwardableTouchee;

}
@property (retain) id forwardableTouchee;

Убедитесь, чтосинтезируйте его в своем .m:

@synthesize forwardableTouchee;

и затем включите следующее в любой из ваших методов UIResponder, например:

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

    [self.forwardableTouchee touchesBegan:touches withEvent:event];

}

Где бы вы ни создавали свой экземпляр UIView, установите для свойства forwardableTouchee значениена какой бы вид вы не хотели пересылать события:

    SomeViewSubclass *view = [[[SomeViewSubclass alloc] initWithFrame:someRect] autorelease];
    view.forwardableTouchee = someOtherView;
1 голос
/ 29 мая 2019

In Swift 5

class ThroughView: UIView {
    override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
        guard let slideView = subviews.first else {
            return false
        }

        return slideView.hitTest(convert(point, to: slideView), with: event) != nil
    }
}
0 голосов
/ 01 июля 2015

По предложению @PixelCloudStv, если вы хотите перебрасывать прикосновения от одного вида к другому, но с дополнительным контролем над этим процессом - подкласс UIView

* * // 1002 * заголовок * 1003
@interface TouchView : UIView

@property (assign, nonatomic) CGRect activeRect;

@end

// реализация

#import "TouchView.h"

@implementation TouchView

#pragma mark - Ovverride

- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
{
    BOOL moveTouch = YES;
    if (CGRectContainsPoint(self.activeRect, point)) {
        moveTouch = NO;
    }
    return moveTouch;
}

@end

После в interfaceBuilder просто установите класс View в TouchView и установите активный прямоугольник с помощью вашего прямоугольника. Также вы можете изменить и реализовать другую логику.

0 голосов
/ 01 октября 2010

Попробуйте что-то вроде этого ...

for (UIView *view in subviews)
  [view touchesBegan:touches withEvent:event];

Код выше, например, в вашем методе touchesBegan передаст касания всем подпредставлениям представления.

...