Dlaczego tak się dzieje?
Dzieje się tak, ponieważ gdy widok podrzędny znajduje się poza granicami podglądu, zdarzenia dotykowe, które faktycznie mają miejsce w tym podglądzie, nie zostaną do niego dostarczone. Jednakże BĘDZIE być dostarczony do SuperView.
Bez względu na to, czy podglądy są przycinane wizualnie, czy nie, zdarzenia dotykowe zawsze uwzględniają prostokąt z granicami superwidoku docelowego widoku. Innymi słowy, zdarzenia dotykowe występujące w części widoku, która znajduje się poza prostokątem granic superwizji, nie są dostarczane do tego widoku. Połączyć
Co musisz zrobić?
Kiedy Twój nadzór otrzyma wspomniane powyżej zdarzenie dotyku, musisz wyraźnie powiedzieć UIKit, że moja subview powinna otrzymywać to zdarzenie dotykowe.
A co z kodem?
W swoim nadzorze, zaimplementuj func hitTest(_ point: CGPoint, with event: UIEvent?)
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
if isHidden || alpha == 0 || clipsToBounds { return super.hitTest(point, with: event) }
let subviewPoint = self.convert(point, to: subview)
if !subview.isHidden && subview.bounds.contains(subviewPoint) { return subview }
return super.hitTest(point, with: event)
}
Fascynująca gotchya: musisz przejść do „najwyższego zbyt małego superwizji”
Musisz wejść „w górę” do „najwyższego” widoku, którego widok problemu znajduje się na zewnątrz.
Typowy przykład:
Powiedzmy, że masz ekran S z widokiem kontenera C. Widok kontrolera widoku kontenera to V. (Przypomnij sobie, że V będzie znajdować się w C i będzie identycznego rozmiaru). V ma widok podrzędny (może przycisk) B. B to problem widok, który faktycznie znajduje się poza V.
Ale pamiętaj, że B jest również poza C.
W tym przykładzie trzeba zastosować rozwiązanie override hitTest
w rzeczywistości do C, a nie V . Jeśli zastosujesz to do V - to nic nie robi.