他の多くのビューの上にビューがオーバーレイされています。私は画面上のいくつかのタッチを検出するためだけに使用していますが、それ以外は、スクロールビューなどの下にある他のビューの動作をビューで停止させたくないです。すべてのタッチをどのように転送できますかこのオーバーレイビュー? UIViewのサブカルです。
オーバーレイビューからその下のビューにタッチを渡すには、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;
}
迅速:
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
}
myWebView.userInteractionEnabled = NO;
必要なのはこれだけでした!
これは古いスレッドですが、検索で出てきたので、2cを追加すると思いました。サブビューでカバーするUIViewがあり、サブビューの1つにヒットするタッチのみをインターセプトするため、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;
}
@fresidue answerの改善されたバージョン。この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)
})
}
}
タッチを転送したいビューがサブビュー/スーパービューではない場合、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;
UIStackViewでも同様の問題がありました(他のビューでもかまいません)。私の構成は次のとおりでした:
これは、ボタンを横に置いて、背景に配置する必要があるコンテナがある古典的なケースです。レイアウトの目的のために、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
}
}
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
}
}
このようなものを試してみてください...
for (UIView *view in subviews)
[view touchesBegan:touches withEvent:event];
たとえば、上記のコードのtouchesBeganメソッドでは、ビューのすべてのサブビューにタッチを渡します。