Ինչպես է համակարգը որոշում, թե որ տեսարանն է հպում:
sobes.tech AI
Պատասխան AI-ից
Սիստեմը օգտագործում է երկու հիմնական մեխանիզմ՝ հիթ-տեստավորում (hit-testing) և դիտման հիերարխիա:
-
Հիթ-տեստավորում (Hit-testing): UIKit ֆրեյմվորկը օգտագործում է
hitTest(_:with:)մեթոդը UIWindow-ի հիմնական դիտման համար՝ որոշելու, թե որ դիտը գտնվում է հպման կետում: Այս մեթոդը ռեկուրսիվ անցնում է դիտների հիերարխիան՝ սկսած հիմնականից: -
Դիտների հիերարխիա:
hitTest(_:with:)մեթոդը առաջին հերթին ստուգում է, արդյոք հպման կետը գտնվում է ներկայիս դիտի սահմաններում: Եթե ոչ, վերադարձնում էnil:- Եթե հպման կետը ներսում է, այն անցնում է երեխաների դիտների վրա հակառակ հերթականությամբ (վերջին ավելացվածից առաջինին): Յուրաքանչյուր երեխայի համար կանչում է իր
hitTest(_:with:)մեթոդը նույն հպման կետով (այն փոխակերպելով երեխայի կոորդինատների համակարգին): - Առաջին երեխա, որի
hitTest(_:with:)մեթոդը վերադարձնում է ոչ-nilարդյունք, համարվում է "հարվածված" և այդ արդյունքը վերադառնում է վերև: - Եթե ոչ մի երեխա չի պարունակում հպման կետը, իսկ ներկայիս դիտը պարունակում է այն և
userInteractionEnabledհավասար էtrue, ապա համակարգը համարում է, որ հպումը տեղի է ունեցել ներկայիս դիտում, և մեթոդը վերադարձնում էself: - Եթե
userInteractionEnabledներկայիս դիտում հավասար էfalse, կամhiddenհավասար էtrue, կամalphaփոքր է 0.01-ից, մեթոդը վերադարձնում էnil, նույնիսկ եթե կետը ներսում է:
Ընթացքը շարունակվում է հիերարխիայով ներքև՝ մինչև գտնվի ամենաթույլ դիտը, որը պարունակում է հպման կետը: Այս դիտը դառնում է hit-test view կամ hit-test result, և հենց նրան (կամ նրա ամենամոտ համապատասխան նախորդին) կհանձնվի հետագա կառավարման միջոցառումը (մեթոդներ touchesBegan, touchesMoved և այլն):
Ինչպես կարելի է վերագրել hitTest կամ point(inside:with:) հարմարեցված վարքագծի համար՝
import UIKit
class CustomView: UIView {
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
// Ստուգում ենք, արդյոք կետը գտնվում է մեր դիտում ներսում:
if !self.point(inside: point, with: event) {
return nil
}
// Դիտում ենք երեխաներին հակառակ հերթականությամբ:
for subview in subviews.reversed() {
let convertedPoint = subview.convert(point, from: self)
if let hitTestView = subview.hitTest(convertedPoint, with: event) {
return hitTestView
}
}
// Եթե ոչ մեկը չի պարունակում կետը, վերադարձնում ենք self:
return self
}
override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
// Ստանդարտը ստուգում է, արդյոք կետը ներսում է bounds-ի և ակտիվ է:
// return super.point(inside: point, with: event)
// Կարող ենք վերագրել հարմարեցված ձևով՝
let extendedBounds = bounds.insetBy(dx: -20, dy: -20) // 20 պիքսել ընդլայնում
return extendedBounds.contains(point)
}
}
point(inside:with:) մեթոդը կանչվում է hitTest(_:with:)-ից՝ արագ ստուգելու համար, արդյոք կետը בכלל գտնվում է դիտի տարածքում՝ նախքան երեխաներին ստուգելը:
Վերջում գտնում ենք ամենաթույլ ինտերակտիվ դիտը, որի գեոմետրիան պարունակում է հպման կետը և որի userInteractionEnabled-ը true, hidden-ը false, և alpha-ն ավելի մեծ է 0.01-ից: