Sobes.tech
Middle

Sistem toxunuşun hansı görünüşə aid olduğunu necə müəyyən edir?

sobes.tech Süni İntellekt

AI-dan cavab

Sistem iki əsas mexanizm istifadə edir: hit-test və view hierarxiyası.

  1. Hit-test (Dəymə test): UIKit çərçivəsi hitTest(_:with:) metodundan istifadə edir, bu metod pəncərə (UIWindow) kök view-inin altında hansı view-in olduğunu müəyyən etmək üçün. Bu metod rekursiv olaraq view hierarxiyasını yoxlayır, kök view-dən başlayaraq.

  2. View hierarxiyası:

    • hitTest(_:with:) metodu əvvəlcə yoxlayır ki, toxunma nöqtəsi cari view-in sərhədləri daxilindədir ya yox. Əgər yoxdursa, nil qaytarır.
    • Əgər daxilindədirsə, metod uşaqlarını tərsinə (son əlavə olunan ilk) yoxlayır. Hər bir uşaq üçün hitTest(_:with:) metodu çağırılır, bu zaman eyni toxunma nöqtəsi istifadə olunur (uşağın koordinatlarına çevrilmiş).
    • Əgər uşaqlardan biri hitTest(_:with:) metodundan nil olmayan nəticə qaytarırsa, bu, həmin uşaq və ya onun altındakı view-in toxunma nöqtəsini ehtiva etdiyini göstərir və nəticə yuxarıya qaytarılır.
    • Əgər heç bir uşaq toxunma nöqtəsini ehtiva etmirsə, və cari view daxilindədirsə və userInteractionEnabled truedirsə, onda self qaytarılır.
    • Əgər cari view-in userInteractionEnabled false və ya hidden true və ya alpha 0.01-dən kiçikdirsə, metod nil qaytarır, hətta nöqtə daxilində olsa belə.

Proses aşağıya doğru davam edir, ən aşağı view tapılana qədər, və bu view hit-test view və ya hit-test result olur, və ona (və ya ən yaxın valideyninə) hadisənin idarə olunması üçün vəzifə verilir (touchesBegan, touchesMoved və s.).

Budur hitTest və ya point(inside:with:) metodlarının xüsusi davranış üçün necə yenidən yazıla biləcəyi:

import UIKit

class CustomView: UIView {

    override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
        // Yoxlayırıq, nöqtə bizim view daxilindədir ya yox.
        if !self.point(inside: point, with: event) {
            return nil
        }

        // Uşaqları tərsinə yoxlayırıq.
        for subview in subviews.reversed() {
            let convertedPoint = subview.convert(point, from: self)
            if let hitTestView = subview.hitTest(convertedPoint, with: event) {
                return hitTestView
            }
        }
        return self
    }

    override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
        // Əsasən, nöqtənin view daxilində olub-olmadığını və interaktiv olub-olmadığını yoxlayır.
        let extendedBounds = bounds.insetBy(dx: -20, dy: -20) // 20pts artır
        return extendedBounds.contains(point)
    }
}

point(inside:with:) metodu hitTest(_:with:) tərəfindən çağırılır və nöqtənin ümumiyyətlə view sahəsində olub-olmadığını yoxlamaq üçün istifadə olunur, uşaqları yoxlamadan əvvəl.

Nəticədə, ən aşağı interaktiv view tapılır ki, onun geometrisi nöqtəni ehtiva edir və userInteractionEnabled true, hidden false, və alpha 0.01-dən böyükdür, və ona hadisə idarəetməsi təyin edilir.