반응형

뷰 화면 내에서 플로팅 및 드레깅 가능한 버튼을 만들어 보았다.

draggableView 사이즈는 50x50으로 설정하였다.

 

import UIKit

class ViewController: UIViewController {
    
    @IBOutlet weak var draggableView: UIView!
    
    var isStickyEffect: Bool! = false       // 좌우측으로 자동으로 벽에 붙도록 처리 flag
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // 팬 제스처 및 탭 제스처 추가
        let panGesture = UIPanGestureRecognizer(target: self, action: #selector(handler))
        let tapGesture = UITapGestureRecognizer(target: self, action: #selector(draggableViewTapped))
        
        draggableView.addGestureRecognizer(panGesture)
        draggableView.addGestureRecognizer(tapGesture)
    }
    
    @objc func handler(gesture: UIPanGestureRecognizer) {
        let location = gesture.location(in: self.view)
        let draggedView = gesture.view
        
        // 뷰의 반너비와 반높이 계산
        let halfWidth = draggedView!.bounds.width / 2
        let halfHeight = draggedView!.bounds.height / 2
        
        // Safe Area를 고려한 화면 경계에 도달하면 뷰를 화면 안쪽으로 이동시킴
        let minX = halfWidth
        let maxX = view.safeAreaLayoutGuide.layoutFrame.width - halfWidth
        let minY = view.safeAreaInsets.top + halfHeight
        let maxY = view.bounds.height - halfHeight
        
        // 좌표 제한
        draggedView?.center.x = max(minX, min(location.x, maxX))
        draggedView?.center.y = max(minY, min(location.y, maxY))
        
        // 드레그 상태 종료시 이벤트
        if gesture.state == .ended {
            stickyEffect()
        }
    }
}



extension ViewController {
    // 좌우측으로 자동으로 벽에 붙도록 처리
    func stickyEffect() {
        let halfWidth = draggableView.bounds.width / 2
        if isStickyEffect == true {
            // 이동이 끝났을 때 특별한 효과 없이 뷰가 그 자리에 고정됨
            if self.draggableView.frame.midX >= self.view.layer.frame.width / 2 {
                UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 1, options: .curveEaseIn, animations: {
                    self.draggableView.center.x = self.view.layer.frame.width - halfWidth//40
                }, completion: nil)
            } else {
                UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 1, options: .curveEaseIn, animations: {
                    self.draggableView.center.x = halfWidth//40
                }, completion: nil)
            }
        }
    }
    
    // 버튼 텝 이벤트
    @objc func draggableViewTapped() {
        let message = "버튼 텝 이벤트"
        let alertController = UIAlertController(title: "Alert", message: message, preferredStyle: .alert)
        let okAction = UIAlertAction(title: "OK", style: .default, handler: nil)
        alertController.addAction(okAction)
        present(alertController, animated: true, completion: nil)
    }
}

 

 

 

2024.01.11 - [Note] - BLE, Beacon, iBeacon

2024.01.11 - [Note] - BLE Advertising Payload format 샘플 분석

2024.01.09 - [Note] - Packet Format for the LE Uncoded PHYs

2024.01.04 - [iOS] - Floating, Dragging Button

2023.12.27 - [Bark Bark] - 말이 통하지 않는 사람과 싸우지 말라.

2023.12.27 - [Server] - Push Notification

2023.12.27 - [AI,ML,ALGORITHM] - A star

2023.12.07 - [iOS] - XOR 연산을 이용한 문자열 비교

2023.11.03 - [AI,ML,ALGORITHM] - Gomoku(Five in a Row, Omok) (5/5) - 3x3 체크 추가

2023.10.29 - [AI,ML,ALGORITHM] - Gomoku(Five in a Row, Omok) (5/5) - 머신러닝으로 게임 구현

 

반응형
블로그 이미지

SKY STORY

,