Một vài phương pháp xử lý chạm từ ngoài vào trong đối với view

Bài này mình sẽ giới thiệu một số phương pháp xử lý việc chạm và di ngón tay đối với 1 view trong swift 😄 Đầu tiên lôi ra 1 UIView và mình để background màu xanh.

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
    }
    
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        //Tạo View
        let v:UIView = UIView(frame: CGRect(x: 0, y: 0, width: self.view.frame.size.width/3, height: self.view.frame.size.width/3))
        
        //Đặt vào giữa màn hình
        v.center = CGPoint(x: self.view.frame.size.width/2, y: self.view.frame.size.height/2)
        
        //chuyển background sang blue
        v.backgroundColor = UIColor.blue
        
        //để tag = 1
        v.tag = 1
        
        //Hiển thị
        self.view.addSubview(v)
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

}

touchesMoved(){}

Hàm này bắt sự kiện khi chạm tay vào UIView tạo bên trên và trượt trên màn hình Ở ví dụ này mình chuyển từ background xanh sang đỏ

override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
        super.touchesMoved(touches, with: event)
        //Lấy toạ độ chạm
        let touch = touches.first
        let point:CGPoint = touch!.location(in: self.view)
        
        //lấy View Target
        let v:UIView = self.view.viewWithTag(1)!
        
        //Nếu toạ độ nằm trong target thì v sẽ chuyển sang màu đỏ
        if v.frame.contains(point){
            v.backgroundColor = UIColor.red
        }
    }

Sử dụng hàm hitTest() trong touchesMoved()

Sử dụng hàm hitTest để tạo ra kết quả tương tự

override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
        super.touchesMoved(touches, with: event)
        
        //Lấy toạ độ chạm
        let touch = touches.first
        let point:CGPoint = touch!.location(in: self.view)
        
        //lấy subview nếu có trong toạ độ
        let v:UIView? = self.view.hitTest(point, with: event)
        
        //Nếu toạ độ thuộc view và tag == 1 thì chuyển background sang đỏ
        if v != nil && v?.tag == 1 {
            v!.backgroundColor = UIColor.red
        }
    }

touchesBegan() Và touchesMove()

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        super.touchesBegan(touches, with: event)
        // Lấy toạ độ lúc bắt đầu chạm
        let touch = touches.first
        let point:CGPoint = touch!.location(in: self.view)
        
        //đặt view 5x5 vào toạ độ chạm và để background trắng cho dễ nhìn
        let finger:UIView = UIView(frame: CGRect(x:0, y:0, width:5, height:5))
        finger.backgroundColor = UIColor.white
        finger.center = point
        self.view.addSubview(finger)
        
        //đặt tag = 2
        finger.tag = 2
        
    }
    
    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
        super.touchesMoved(touches, with: event)
        //Lấy toạ độ chạm
        let touch = touches.first
        let point:CGPoint = touch!.location(in: self.view)
        
        //lấy view
        let v:UIView = self.view.viewWithTag(1)!
        
        //lấy view khi bắt đầu chạm
        let finger:UIView = self.view.viewWithTag(2)!
        
        //Toạ độ sẽ thay đổi khi di chuyển ngón tay
        finger.center = point
        
        //chuyển background sang màu đỏ
        if v.frame.intersects(finger.frame) {
            v.backgroundColor = UIColor.red
        }
        
    }

Và cũng không thể quên kết thúc sự kiện bằng touchesEnded()

override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
        super.touchesEnded(touches, with: event)
        
        //Lấy View khi bắt đầu chạm
        let finger:UIView = self.view.viewWithTag(2)!
        
        //Xoá
        finger.removeFromSuperview()
    }

Sử dụng UIDynamics

Tham khảo thêm về UIDynamics của bạn hungbv tại: https://viblo.asia/p/tim-hieu-ve-uikit-dynamics-zNPVMaa6MQOk

import UIKit

class ViewController: UIViewController,UICollisionBehaviorDelegate {
    
    var animator:UIDynamicAnimator!
    var behavior:UICollisionBehavior!
    var snap:UISnapBehavior!
    
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        
        //Welcome to Physical world >:)
        animator = UIDynamicAnimator(referenceView: self.view)
        
    }
    
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        
        //tạo View
        let v:UIView = UIView(frame: CGRect(x:0, y:0, width:self.view.frame.size.width/3, height:self.view.frame.size.width/3))
        //Đặt vào giữa màn hình
        v.center = CGPoint(x:self.view.frame.size.width/2, y:self.view.frame.size.height/2)
        //Blue background
        v.backgroundColor = UIColor.blue
        //set tag = 1
        v.tag = 1
        //Hiển thị
        self.view.addSubview(v)
        
        //Đưa view vào UICollisionBehavior
        behavior = UICollisionBehavior(items: [v])
        behavior.translatesReferenceBoundsIntoBoundary = true
        
        //Không để sự kiện gì sảy ra khi chạm vào view
        behavior.addBoundary(withIdentifier: "v" as NSCopying, for: UIBezierPath(rect:v.frame))
        
        //setting delegate
        behavior.collisionDelegate = self
        
    }
    
    
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        super.touchesBegan(touches, with: event)
        //Lấy toạ độ khi bắt đầu chạm
        let touch = touches.first
        let point:CGPoint = touch!.location(in: self.view)
        
        //đặt một view nhỏ 5x5 vào toạ độ bắt đầu chạm
        let finger:UIView = UIView(frame: CGRect(x:0, y:0, width:5, height:5))
        finger.center = point
        finger.backgroundColor = UIColor.yellow
        self.view.addSubview(finger)
        //set tag = 2
        finger.tag = 2
        
        //Đưa view vừa tạo vào UICollisionBehavior bên trên
        behavior.addItem(finger)
        
        //Định nghĩa vật lý cho cả 2 view
        animator.addBehavior(behavior)
        
    
        if snap != nil {
            animator.removeBehavior(snap)
        }
        
        //đưa finger vào UISnapBehavior và có thể có va chạm với point
        snap = UISnapBehavior(item: finger, snapTo: point)
        
        //Cuối cùng animator sẽ xử lý va chạm
        animator.addBehavior(snap)
        
    }
    
    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
        super.touchesMoved(touches, with: event)
        //Lấy toạ độ khi bắt đầu chạm
        let touch = touches.first
        let point:CGPoint = touch!.location(in: self.view)
        
        
        //lấy view khi bắt đầu chạm
        let finger:UIView = self.view.viewWithTag(2)!
        //point sẽ di chuyển theo ngón tay trong khi đang chạm trên màn hình
        finger.center = point
        
        
        if snap != nil {
            animator.removeBehavior(snap)
        }
        
        //đưa finger vào UISnapBehavior và có thể có va chạm với point
        snap = UISnapBehavior(item: finger, snapTo: point)
        
        //Cuối cùng animator sẽ xử lý va chạm
        animator.addBehavior(snap)
        
    }
    
    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
        super.touchesEnded(touches, with: event)
        
        //lấy view khi bắt đầu chạm
        let finger:UIView = self.view.viewWithTag(2)!
        
        //remove
        behavior.removeItem(finger)
        finger.removeFromSuperview()
        
        
    }
    
    //Khi chạm nhau sẽ sảy ra collisionBehavior
    func collisionBehavior(_ behavior: UICollisionBehavior, endedContactFor item1: UIDynamicItem, with item2: UIDynamicItem) {
        //background của v sẽ chuyển sang màu đỏ
        let v:UIView = self.view.viewWithTag(1)!
        v.backgroundColor = UIColor.red
    }
    
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    
}

Khi bỏ dòng code này behavior.addBoundary(withIdentifier: "v" as NSCopying, for: UIBezierPath(rect:v.frame)) thì view hình vuông ban đầu sẽ trôi nổi khi bị chạm vào. KIhild

Tham khảo: http://qiita.com/SAB/items/782ce76e72865995dd07


All Rights Reserved