UIKit Dynamics — framework de animație fizică în iOS (UIKit), care permite View-urilor să interacționeze conform legilor fizicii reale: gravitație, coliziuni, elasticitate și forțe de atracție. Articolul explică componentele UIDynamicAnimator, tipurile de comportamente (behavior) și scenariile practice de aplicare.
Esențial
UIKit Dynamics — un framework de modelare fizică, introdus de Apple în iOS 7 (2013). Spre deosebire de UIView.animate (tranziții liniare) și Core Animation (animația straturilor), UIKit Dynamics modelează interacțiuni fizice reale: gravitație, coliziuni, forțe, elasticitate și frecare. Dezvoltatorul adaugă comportamente (behaviors) la UIDynamicAnimator, iar sistemul calculează automat fizica pentru fiecare cadru.
Framework-ul funcționează la 60/120 FPS și utilizează un motor fizic integrat bazat pe simularea corpurilor rigide (rigid body simulation). UIKit Dynamics nu necesită cunoștințe de fizică sau matematică — este suficient să aplici un comportament gata făcut și să configurezi parametrii.
Conform Apple, UIKit Dynamics este potrivit pentru efecte UI (animația unui teanc de cărți, „tremuratul” iconițelor, fizica interfeței), dar nu este destinat jocurilor — pentru jocuri utilizați SceneKit sau SpriteKit.
UIDynamicAnimator — clasa centrală a UIKit Dynamics. Se inițializează cu un reference view (de obicei view-ul controlerului) și gestionează toate comportamentele active. În fiecare cadru, UIDynamicAnimator recalculează pozițiile, vitezele și accelerațiile tuturor elementelor adăugate, ținând cont de legile fizicii.
Metoda addBehavior adaugă un comportament (sau un UIDynamicBehavior complex), removeBehavior — îl elimină. Animatorul se oprește automat când toate obiectele ajung în stare de repaus (fără coliziuni și forțe). Metoda delegate — UIDynamicAnimatorDelegate — notifică despre pauză și reluarea simulării.
Orice obiect care participă la fizică trebuie să implementeze protocolul UIDynamicItem. UIView și UICollectionViewLayoutAttributes îl implementează deja. Protocolul necesită proprietățile: bounds, center, transform. Dacă obiectul este personalizat — implementați protocolul manual.
UIKit Dynamics include șapte tipuri încorporate de comportamente, fiecare modelând un efect fizic specific. Comportamentele pot fi combinate: de exemplu, gravitația + coliziunile + elasticitatea creează efectul de obiecte care cad și se ciocnesc.
| Behavior | Efect fizic | Parametri cheie |
|---|---|---|
| UIGravityBehavior | Gravitație (vector de forță) | gravityDirection (dx, dy), magnitude |
| UICollisionBehavior | Coliziuni ale obiectelor și granițelor | collisionMode, translucence, collisionDelegate |
| UIAttachmentBehavior | Legătură (arc/cablu) | anchorPoint, length, damping, frequency |
| UISnapBehavior | Atracție către un punct cu amortizare | snapPoint, damping (0-1) |
| UIPushBehavior | Împingere/impuls (continuu sau instantaneu) | pushDirection, magnitude, mode |
| UIDynamicItemBehavior | Proprietăți fizice ale obiectului | elasticity, friction, density, resistance |
| UIFieldBehavior | Câmpuri de forță (vârtej, magnet, rază) | position, strength, falloff, region |
Pentru o fizică realistă a unui obiect sunt necesare mai multe comportamente simultan. De exemplu, pentru o carte care cade: UIGravityBehavior (forța gravitațională), UICollisionBehavior (coliziunea cu fundul), UIDynamicItemBehavior (elasticity: 0.4 pentru ricoșeu). Toate comportamentele se adaugă la un singur UIDynamicAnimator.
Codul Swift pentru UIKit Dynamics creează un UIDynamicAnimator și adaugă comportamente. Exemplul de mai jos demonstrează gravitația cu mai multe obiecte, coliziuni și proprietăți fizice personalizate.
import UIKit
class PhysicsViewController: UIViewController {
var animator: UIDynamicAnimator!
override func viewDidLoad() {
super.viewDidLoad()
// 1. Creăm animatorul cu reference view
animator = UIDynamicAnimator(referenceView: view)
// 2. Creăm obiecte care cad
let redView = UIView(frame: CGRect(x: 100, y: 50, width: 60, height: 60))
redView.backgroundColor = .systemRed
redView.layer.cornerRadius = 8
view.addSubview(redView)
let blueView = UIView(frame: CGRect(x: 200, y: 30, width: 60, height: 60))
blueView.backgroundColor = .systemBlue
blueView.layer.cornerRadius = 8
view.addSubview(blueView)
// 3. Gravitare
let gravity = UIGravityBehavior(items: [redView, blueView])
gravity.gravityDirection = CGVector(dx: 0, dy: 1)
gravity.magnitude = 0.8
animator.addBehavior(gravity)
// 4. Coliziuni
let collision = UICollisionBehavior(items: [redView, blueView])
collision.translatesReferenceBoundsIntoBoundary = true
collision.collisionDelegate = self
animator.addBehavior(collision)
// 5. Proprietăți fizice
let itemBehavior = UIDynamicItemBehavior(items: [redView, blueView])
itemBehavior.elasticity = 0.6
itemBehavior.friction = 0.3
itemBehavior.density = 1.0
animator.addBehavior(itemBehavior)
// 6. Comportament Snap la atingere
let tap = UITapGestureRecognizer(target: self, action: #selector(handleTap))
view.addGestureRecognizer(tap)
}
@objc
func handleTap(_ gesture: UITapGestureRecognizer) {
let point = gesture.location(in: view)
// Comportament Snap pentru fiecare obiect
for subview in view.subviews where subview is UIView {
animator.removeAllBehaviors()
let snap = UISnapBehavior(item: subview, snapTo: point)
snap.damping = 0.5
animator.addBehavior(snap)
}
}
}
extension PhysicsViewController: UICollisionBehaviorDelegate {
func collisionBehavior(_ behavior: UICollisionBehavior,
beganContactFor item1: UIDynamicItem,
with item2: UIDynamicItem,
at point: CGPoint) {
print("Coliziune la: (point)")
}
}Exemplul creează două View-uri cu gravitație, coliziuni și proprietăți fizice. UISnapBehavior la atingere atrage obiectele către punctul de atingere cu amortizare 0.5. UICollisionBehaviorDelegate urmărește începutul coliziunilor pentru efecte sonore și vizuale.
UIKit Dynamics se aplică în aplicațiile iOS pentru fizica non-joc a interfeței. Scenarii populare: animația unui teanc de cărți (UISnapBehavior pentru atracția către centru), scuturarea ecranului la eroare (UIDynamicItemBehavior + UIPushBehavior), efectul de „stele căzătoare” în onboarding (gravity + collision + field behavior).
Pentru performanță, UIKit Dynamics recomandă nu mai mult de 15-20 de obiecte simultane cu fizică. Fiecare obiect necesită calculul coliziunilor și forțelor în fiecare cadru. La depășirea limitei, utilizați CALayer în loc de UIView — Core Animation procesează straturile mai eficient.
Întrebări frecvente
UIKit Dynamics modelează interacțiuni fizice (gravitație, coliziuni, forțe) pe baza simulării corpurilor rigide. Core Animation — animația proprietăților CALayer (position, opacity, transform) după o curbă temporală dată. Dynamics este potrivit pentru fizică interactivă, Core Animation — pentru tranziții predefinite.
Suportul direct pentru UIKit Dynamics în SwiftUI nu există. Pentru efecte fizice, utilizați UIKitView + UIDynamicAnimator în interiorul UIViewRepresentable sau animații personalizate prin Animation.spring() și withAnimation() în SwiftUI.
Apelați animator.removeAllBehaviors() — aceasta va elimina toate comportamentele fizice active. Animatorul se oprește automat când toate obiectele ajung în repaus. Pentru pauză temporară, utilizați proprietatea animator.isPaused sau eliminați comportamente individuale.
Apple recomandă nu mai mult de 15-20 de obiecte cu fizică completă (gravitație + coliziuni + forțe). Pentru animații în masă, utilizați UIFieldBehavior — acesta calculează forțele centralizat, fără coliziuni perechi, reducând încărcarea CPU.
Concluzii
Vom dezvolta o aplicație mobilă la cheie
IT Sectr creează aplicații iOS și Android pentru startup-uri și afaceri din 2017. Vă vom consilia și vă vom propune cea mai bună soluție.
Citiți și