Middle
Kā sistēma nosaka, kurā skatā ir noticis pieskāriens?
sobes.tech AI
Atbilde no AI
Sistēma izmanto divus galvenos mehānismus: hit-testēšanu (hit-testing) un skatījumu hierarhiju:
-
Hit-testēšana (Hit-testing): UIKit ietvars izmanto
hitTest(_:with:)metodi UIWindow galvenajam skatījumam, lai noteiktu, kurš skatījums atrodas pie kontakta punkta. Šī metode rekursīvi pārbauda skatījumu hierarhiju, sākot ar galveno: -
Skatījumu hierarhija:
hitTest(_:with:)metode vispirms pārbauda, vai kontakta punkts ir iekšā pašreizējā skatījuma robežās. Ja nē, tā atgriežnil:- Ja ir, tā pārbauda bērnu skatījumus atpakaļejošā secībā (no pēdējā pievienotā līdz pirmajam). Katram bērnam tiek izsaukts tā
hitTest(_:with:)ar to pašu kontakta punktu (pārvēršot to bērna koordinātu sistēmā): - Pirmais bērns, kura
hitTest(_:with:)metode atgriež ne-nilrezultātu, tiek uzskatīts par "sasniegtu" un šis rezultāts tiek atgriezts augšup: - Ja neviens bērns neietver punktu, bet pašreizējais skatījums to ietver un
userInteractionEnabledirtrue, sistēma uzskata, ka kontakts noticis pašreizējā skatījumā, un metode atgriežself: - Ja
userInteractionEnabledpašreizējā skatījumā irfalse, vaihiddenirtrue, vaialphair mazāks par 0.01, metode atgriežnil, pat ja punkts ir robežās:
Process turpinās hierarhijā uz leju, līdz tiek atrasts zemākais skatījums, kas ietver kontakta punktu. Šis skatījums kļūst par hit-test view vai hit-test result, un tieši tam (vai tuvākajam tā priekšā) tiks deleģēta turpmākā notikumu pārvaldība (touchesBegan, touchesMoved utt.):
Šādi var pārdefinēt hitTest vai point(inside:with:) pielāgotai hit-testēšanas uzvedībai:
import UIKit
class CustomView: UIView {
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
// Pārbauda, vai punkts ir mūsu skatījumā.
if !self.point(inside: point, with: event) {
return nil
}
// Pāriet cauri bērniem atpakaļejošā secībā.
for subview in subviews.reversed() {
let convertedPoint = subview.convert(point, from: self)
if let hitTestView = subview.hitTest(convertedPoint, with: event) {
return hitTestView
}
}
// Ja neviens neietver, atgriež self:
return self
}
override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
// Standarta pārbaude: vai punkts ir iekšā bounds un vai skatījums ir aktīvs:
// return super.point(inside: point, with: event)
// Pielāgojums, piemēram, paplašināt kontaktu zonu:
let extendedBounds = bounds.insetBy(dx: -20, dy: -20) // Paplašinām par 20 punktiem
return extendedBounds.contains(point)
}
}