Middle
როგორ განსაზღვრავს სისტემა, რომელ ხედში შეხება მოხდა?
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)
}
}