Notice
Recent Posts
Recent Comments
Link
관리 메뉴

김종권의 iOS 앱 개발 알아가기

[iOS - swift] 안드로이드 스타일 로딩 뷰 구현 방법 (Circular Loading View, UIBezierPath, CABasicAnimation) 본문

UI 컴포넌트 (swift)

[iOS - swift] 안드로이드 스타일 로딩 뷰 구현 방법 (Circular Loading View, UIBezierPath, CABasicAnimation)

jake-kim 2023. 12. 28. 22:36

* 이미지를 이용한 방법은 이전 포스팅 글 참고

직접 구현한 로딩UI

구현 아이디어

  • UIBezierPath를 통해서 동그란 layer 그리기
  • layer의 lineWith를 1보다 크게하여 테두리를 만들고 이 테두리의 색상(strokeColor)은 blue, 내부에 채워지는 색상(fillColor)은 clear로 설정
  • 테두리가 꽉차 있으면 안되고 중간이 뚫려 있어야 하므로 strokeStart를 0.2정도로 설정하여 20%는 비어지도록 설정
  • 이 뷰를 CABasicAnimation의 transform.rotation을 사용하여 효과를 주면 완성

구현

  • LoadingView 정의
final class LoadingView: UIView {
    init() {
        super.init(frame: .init(origin: .zero, size: .init(width: 50, height: 50)))
        backgroundColor = superview?.backgroundColor
        setupLoader()
    }
    
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        setupLoader()
    }
    
    private func setupLoader() {
    	// TODO...
    }
}
  • setupLoader 구현
    • UIBezierPath를 통해서 동그란 layer 그리기
    • layer의 lineWith를 1보다 크게하여 테두리를 만들고 이 테두리의 색상(strokeColor)은 blue, 내부에 채워지는 색상(fillColor)은 clear로 설정
    • 테두리가 꽉차 있으면 안되고 중간이 뚫려 있어야 하므로 strokeStart를 0.2정도로 설정하여 20%는 비어지도록 설정
private func setupLoader() {
    /// 원형 모양의 경로 생성
    let circularPath = UIBezierPath(ovalIn: bounds.insetBy(dx: 10, dy: 10))
    
    let shapeLayer = {
        let l = CAShapeLayer()
        l.path = circularPath.cgPath
        l.fillColor = UIColor.clear.cgColor
        l.strokeColor = UIColor.blue.cgColor
        l.lineWidth = 5
        l.strokeEnd = 1
        return l
    }()
    
    // 0~1값을 주어 채워지는 시작점을 20%로 설정
    shapeLayer.strokeStart = 0.2
    
    layer.addSublayer(shapeLayer)
}
  • start와 stop 구현
    func startAnimating() {
        // 회전 애니메이션
        let rotationAnimation = CABasicAnimation(keyPath: "transform.rotation")
        rotationAnimation.byValue = 2 * Double.pi
        rotationAnimation.timingFunction = CAMediaTimingFunction(name: .linear)
        rotationAnimation.repeatCount = .infinity
        rotationAnimation.duration = 1
        layer.add(rotationAnimation, forKey: "rotationAnimation")
    }
    
    func stopAnimating() {
        layer.removeAllAnimations()
    }

사용하는쪽)

class ViewController: UIViewController {
    
    var loadingView: LoadingView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        loadingView = LoadingView()
        loadingView.center = view.center
        view.addSubview(loadingView)
    }
    
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        
        loadingView.startAnimating()
    }
    
    override func viewDidDisappear(_ animated: Bool) {
        super.viewDidDisappear(animated)
        
        loadingView.stopAnimating()
    }
}

완성)

직접 구현한 로딩UI

* 전체 코드: https://github.com/JK0369/ExLoadingAnimation

Comments