Інтеграція Rive-анімацій у мобільні додатки
Rive принципово відрізняється від Lottie: це не експорт «випеченої» анімації, а runtime-рушій з State Machine. Анімація реагує на введення з коду—натискання кнопки змінює стан State Machine, плавно переходячи між анімаційними клипами. Це потужно й вимагає розуміння того, як Rive Runtime працює всередину вашого додатка.
Архітектура Rive Runtime
Файл Rive (.riv) містить артборди, анімаційні клипи та State Machine. Runtime завантажує файл, створює інстанс Artboard та керує ним через StateMachineController або SimpleAnimation. Рендеринг використовує власний Rive Renderer, який використовує Metal на iOS та OpenGL ES 3.0 / Vulkan на Android.
Важливо: Rive Renderer та стандартний Canvas renderer існують паралельно. На Android до версії runtime 9.x за замовчуванням використовувався Canvas renderer—повільніше, але більш сумісний. З 9.x Rive Renderer увімкнено за замовчуванням і значно швидший для складних mesh-анімацій, але вимагає OpenGL ES 3.0 (API 18+, що охоплює >99% пристроїв).
Інтеграція Android
// build.gradle
implementation "app.rive:rive-android:9.6.0"
// Ініціалізація в Application.onCreate() - обов'язково!
RiveInitializer.initializer(context)
// У layout XML:
// <app.rive.runtime.kotlin.RiveAnimationView
// android:id="@+id/riveView"
// app:riveResource="@raw/my_animation"
// app:riveStateMachineName="StateMachine" />
// У Activity/Fragment:
val riveView = findViewById<RiveAnimationView>(R.id.riveView)
// Передавання вводу до State Machine:
riveView.setNumberState("StateMachine", "progress", 0.75f)
riveView.setBooleanState("StateMachine", "isActive", true)
riveView.fireState("StateMachine", "triggerName")
RiveInitializer.initializer() має бути викликаний один раз перед створенням будь-якого RiveAnimationView—інакше ви отримуєте IllegalStateException: Rive not initialized. Поширена помилка з ледачою ініціалізацією фреймворків DI.
Інтеграція iOS
// SPM: https://github.com/rive-app/rive-ios, версія 6.x
import RiveRuntime
let riveView = RiveView()
let model = RiveModel(fileName: "my_animation")
let viewModel = RiveViewModel(model, stateMachineName: "StateMachine")
viewModel.setView(riveView)
// Управління State Machine:
try? viewModel.setInput("isActive", value: true)
try? viewModel.setInput("progress", value: 0.75)
try? viewModel.triggerInput("tapTrigger")
Для SwiftUI використовуйте RiveViewModel як ObservableObject:
struct AnimatedButton: View {
@StateObject private var rvm = RiveViewModel(fileName: "button_animation",
stateMachineName: "ButtonSM")
var body: some View {
rvm.view()
.onTapGesture { try? rvm.triggerInput("pressed") }
}
}
Flutter
// pubspec.yaml: rive: ^0.13.0
import 'package:rive/rive.dart';
RiveAnimation.asset(
'assets/animations/my_animation.riv',
stateMachines: ['StateMachine'],
onInit: (artboard) {
final controller = StateMachineController.fromArtboard(artboard, 'StateMachine');
artboard.addController(controller!);
final isActive = controller.findInput<bool>('isActive') as SMIBool;
isActive.value = true;
},
)
Поширені проблеми інтеграції
Файл Rive створений для одного артборду, але runtime намагається отримати доступ до іншого—NullPointerException без чіткого повідомлення. Завжди явно вказуйте назву артборду через параметр artboardName.
Імена State Machine input чутливі до регістру та пробілів. "Is Active" і "isActive" — різні inputs. Перевіряйте в Rive Editor перед інтеграцією.
Великі файли .riv (>5 МБ) з вбудованими растровими текстурами мають завантажуватися асинхронно. На iOS ініціалізуйте RiveModel з об'єктом Data, завантаженим у фоновому потоці через URLSession або FileManager.
Час розробки
Інтеграція одного файлу Rive з базовою State Machine займає від 4 годин. З двосторонньою синхронізацією між State Machine та бізнес-логікою додатка (прогрес, стани автентифікації, ігрові події), виділіть 1–2 дні. Вартість розраховується індивідуально.







