Sistem dokunuşun hangi görünüme ait olduğunu nasıl belirler?
sobes.tech yapay zeka
AI'dan gelen yanıt
Sistem iki temel mekanizmayı kullanır: hit-test (dokunma testi) ve görünüm hiyerarşisi.
-
Hit-test (Dokunma Testi): UIKit framework'ü, pencerenin kök görünümünün
hitTest(_:with:)metodunu kullanarak, dokunma noktasının altında hangi görünümün olduğunu belirler. Bu yöntem, kök görünümden başlayarak hiyerarşiyi rekürsif olarak dolaşır. -
Görünüm Hiyerarşisi:
hitTest(_:with:)yöntemi önce dokunma noktasının mevcut görünüm sınırları içinde olup olmadığını kontrol eder. Değilse,nildöner.- Nokta sınırlar içindeyse, çocuk görünümleri ters sırayla (son eklenenden ilk eklenene) inceler. Her çocuk görünüm için, aynı noktayı kullanarak
hitTest(_:with:)çağrısı yapılır (koordinatlar çocuk görünümüne dönüştürülerek). hitTest(_:with:)yönteminilolmayan bir sonuç döndürürse (yani, nokta bu görünüm veya alt görünümleri tarafından içeriliyorsa), bu sonuç yukarı doğru geri döndürülür.- Hiçbir çocuk görünüm nokta ile ilgilenmiyorsa ve mevcut görünüm nokta içeriyorsa ve
userInteractionEnabledfalsedeğilse,selfdöndürülür. - Eğer
userInteractionEnabledfalseise, veyahiddentrueise, veyaalpha0.01'den küçükse,nildöndürülür, nokta sınırlar içinde olsa bile.
İşlem, en alttaki görünüm bulunana kadar aşağı doğru devam eder. Bu görünüm, hit-test view veya hit-test result olur ve olayların yönetimi ona (veya en yakın uygun atasına) devredilir (touchesBegan, touchesMoved vb. metodlar).
İşte hitTest veya point(inside:with:) metodunu özelleştirilmiş davranışlar için nasıl geçersiz kılacağınız:
import UIKit
class CustomView: UIView {
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
// Noktanın bu görünüm içinde olup olmadığını kontrol et.
if !self.point(inside: point, with: event) {
return nil
}
// Çocuk görünümleri ters sırayla dolaşır.
for subview in subviews.reversed() {
// Noktayı çocuk görünümün koordinatlarına dönüştür.
let convertedPoint = subview.convert(point, from: self)
// Rekürsif olarak hitTest çağrısı yap.
if let hitTestView = subview.hitTest(convertedPoint, with: event) {
// Çocuk görünüm veya onun alt görünümleri noktayı içeriyorsa, sonucu döndür.
return hitTestView
}
}
// Hiçbir çocuk görünüm olayla ilgilenmediyse,
// ve bu görünüm etkileşimliyse ve nokta içeriyorsa, kendisini döndür.
return self
}
override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
// Temel uygulama, noktanın sınırlar içinde olup olmadığını ve görünümün etkileşimli olup olmadığını kontrol eder.
// return super.point(inside: point, with: event)
// Özelleştirilmiş şekiller veya boşluklar için yeniden tanımlanabilir, örneğin dokunma alanını genişletmek.
let extendedBounds = bounds.insetBy(dx: -20, dy: -20) // Tüm taraflara 20pt ekle
return extendedBounds.contains(point)
}
}
point(inside:with:) metodu, hitTest(_:with:) tarafından çağrılır ve noktayı görünüm alanı içinde hızlıca kontrol eder, çocuk görünümleri kontrol etmeden önce.
Sonuç olarak, hiyerarşide en alttaki ve dokunma noktasını içeren, userInteractionEnabled değeri true, hidden false ve alpha 0.01'den büyük olan görünüm, hit-test view olarak kabul edilir.