Home > UIKit Dynamics

UIKit Dynamics

UIKit์˜ ๋ฌผ๋ฆฌ ์—”์ง„์œผ๋กœ UI ์š”์†Œ์— ์ค‘๋ ฅ, ์ถฉ๋Œ, ํƒ„์„ฑ, ์Šค๋ƒ… ๋“ฑ ๋ฌผ๋ฆฌ ๊ธฐ๋ฐ˜ ๋™์ž‘์„ ๋ถ€์—ฌํ•ฉ๋‹ˆ๋‹ค. ์ž์—ฐ์Šค๋Ÿฌ์šด ์ธํ„ฐ๋ž™์…˜๊ณผ ์œ ๊ธฐ์ ์ธ UI ๋ชจ์…˜์„ ๋งŒ๋“ค์–ด ๋ด…๋‹ˆ๋‹ค.

๊ฐœ์š”

UIKit Dynamics๋Š” UIKit ๋ทฐ์— ์‹ค์‹œ๊ฐ„ ๋ฌผ๋ฆฌ ์‹œ๋ฎฌ๋ ˆ์ด์…˜์„ ์ ์šฉํ•˜๋Š” ํ”„๋ ˆ์ž„์›Œํฌ์ž…๋‹ˆ๋‹ค. UIDynamicAnimator๊ฐ€ ๋ฌผ๋ฆฌ ์—”์ง„ ์—ญํ• ์„ ํ•˜๋ฉฐ, ๋‹ค์–‘ํ•œ UIDynamicBehavior(์ค‘๋ ฅ, ์ถฉ๋Œ, ๋ถ€์ฐฉ, ์Šค๋ƒ…, ํ‘ธ์‹œ)๋ฅผ ์กฐํ•ฉํ•˜์—ฌ UI ์š”์†Œ์˜ ๋™์ž‘์„ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค.

SpriteKit๊ณผ ๋‹ฌ๋ฆฌ ์ผ๋ฐ˜ UIView๋ฅผ ๋ฌผ๋ฆฌ ๊ฐ์ฒด๋กœ ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์—, ๊ธฐ์กด UI ์ปดํฌ๋„ŒํŠธ์— ๋ฌผ๋ฆฌ ๊ธฐ๋ฐ˜ ์ธํ„ฐ๋ž™์…˜์„ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. SwiftUI์—์„œ๋Š” UIViewRepresentable์„ ํ†ตํ•ด ํ†ตํ•ฉํ•ฉ๋‹ˆ๋‹ค.

์–ธ์ œ ์‚ฌ์šฉํ•˜๋‚˜์š”?

ํ•ต์‹ฌ API

UIDynamicAnimator์™€ Behavior

class PhysicsViewController: UIViewController {
    var animator: UIDynamicAnimator!

    override func viewDidLoad() {
        super.viewDidLoad()
        animator = UIDynamicAnimator(referenceView: view)

        let card = UIView(frame: CGRect(x: 150, y: 50, width: 80, height: 80))
        card.backgroundColor = .systemBlue
        card.layer.cornerRadius = 12
        view.addSubview(card)

        // ์ค‘๋ ฅ
        let gravity = UIGravityBehavior(items: [card])
        // ์ถฉ๋Œ (ํ™”๋ฉด ๊ฒฝ๊ณ„)
        let collision = UICollisionBehavior(items: [card])
        collision.translatesReferenceBoundsIntoBoundary = true
        // ํƒ„์„ฑ
        let itemBehavior = UIDynamicItemBehavior(items: [card])
        itemBehavior.elasticity = 0.6

        animator.addBehavior(gravity)
        animator.addBehavior(collision)
        animator.addBehavior(itemBehavior)
    }
}

์ฃผ์š” Behavior ์ •๋ฆฌ

Behavior ์„ค๋ช…
UIGravityBehavior ์•„์ดํ…œ์— ์ค‘๋ ฅ(๋ฐฉํ–ฅ, ์„ธ๊ธฐ) ์ ์šฉ
UICollisionBehavior ์•„์ดํ…œ ๊ฐ„ ๋˜๋Š” ๊ฒฝ๊ณ„์™€์˜ ์ถฉ๋Œ ๊ฐ์ง€
UIAttachmentBehavior ๋‘ ์•„์ดํ…œ ๋˜๋Š” ์•ต์ปค ํฌ์ธํŠธ์— ์Šคํ”„๋ง/๊ณ ์ • ์—ฐ๊ฒฐ
UISnapBehavior ์•„์ดํ…œ์„ ํŠน์ • ์ง€์ ์œผ๋กœ ์Šค๋ƒ… (๊ฐ์‡  ์ง„๋™)
UIPushBehavior ์ˆœ๊ฐ„์ (.instantaneous) ๋˜๋Š” ์ง€์†์ (.continuous) ํž˜ ์ ์šฉ
UIDynamicItemBehavior ๋งˆ์ฐฐ, ํƒ„์„ฑ, ๋ฐ€๋„, ์ €ํ•ญ ๋“ฑ ๋ฌผ๋ฆฌ ์†์„ฑ ์„ค์ •

SwiftUI ํ†ตํ•ฉ

UIKit Dynamics๋Š” UIKit ๊ธฐ๋ฐ˜์ด๋ฏ€๋กœ SwiftUI์—์„œ UIViewRepresentable ๋˜๋Š” UIViewControllerRepresentable๋กœ ๋ž˜ํ•‘ํ•˜์—ฌ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

struct DynamicsView: UIViewControllerRepresentable {
    func makeUIViewController(context: Context) -> PhysicsViewController {
        PhysicsViewController()
    }
    func updateUIViewController(_ vc: PhysicsViewController, context: Context) {}
}

๋ฐ๋ชจ ๋ชฉ๋ก

# ๋ฐ๋ชจ ์„ค๋ช…
1 Gravity Cards ์—ฌ๋Ÿฌ ์นด๋“œ์— ์ค‘๋ ฅ๊ณผ ์ถฉ๋Œ์„ ์ ์šฉํ•ฉ๋‹ˆ๋‹ค. ๋””๋ฐ”์ด์Šค๋ฅผ ๊ธฐ์šธ์ด๋ฉด ์ค‘๋ ฅ ๋ฐฉํ–ฅ์ด ๋ฐ”๋€๋‹ˆ๋‹ค (์ด ๋ทฐ๋Š” Portrait ๋ฐฉํ–ฅ์œผ๋กœ ์ž๋™ ์ž ๊น€).
2 Snap Grid UISnapBehavior๋กœ ๋“œ๋ž˜๊ทธํ•œ ์•„์ด์ฝ˜์ด ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด ๊ทธ๋ฆฌ๋“œ ์œ„์น˜๋กœ ์Šค๋ƒ…๋ฉ๋‹ˆ๋‹ค. damping ์Šฌ๋ผ์ด๋”๋กœ ์Šค๋ƒ… ๋А๋‚Œ์„ ์กฐ์ ˆํ•ฉ๋‹ˆ๋‹ค.
3 Collision Bubbles ์›ํ˜• ๋ฒ„๋ธ”๋“ค์ด ์„œ๋กœ ์ถฉ๋Œํ•˜๋ฉฐ ์ž์œ  ๋ฐฐ์น˜๋˜๋Š” ํƒœ๊ทธ ํด๋ผ์šฐ๋“œ. ํƒญํ•˜๋ฉด ์ฃผ๋ณ€์œผ๋กœ ๋ฐ€์–ด๋‚ด๋Š” UIPushBehavior๊ฐ€ ์ ์šฉ๋ฉ๋‹ˆ๋‹ค.
4 Pendulum (Newtonโ€™s Cradle) UIAttachmentBehavior๋กœ ์ค„์„ ๊ตฌํ˜„ํ•œ ๋‰ดํ„ด์˜ ์š”๋žŒ. UISnapBehavior๋กœ ๊ณต์„ ๋“œ๋ž˜๊ทธํ•ด ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ๋†“์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
5 Elastic Menu UIAttachmentBehavior์˜ spring ์„ค์ •์œผ๋กœ ํƒ„์„ฑ ์žˆ๋Š” ๋ฉ”๋‰ด. ์•„์ดํ…œ ๊ฐ„ ์ฒด์ธ ์—ฐ๊ฒฐ๋กœ ํ•œ ํ•ญ๋ชฉ ๋‹น๊ธฐ๋ฉด ๋‹ค๋ฅธ ํ•ญ๋ชฉ๋„ ๋”ฐ๋ผ์˜ต๋‹ˆ๋‹ค.

์‹ค์ „ ํŒ

Best Practices

์ฃผ์˜ ์‚ฌํ•ญ