🦭
【Flutter】Rive アニメーションに Flutter からテキストを入力する
はじめに
インタラクティブなアニメーションを作る場合、Rive を使いたいですよね?
アプリ内で出入りの多い、テキストをアニメーション内に流し込みたい。
そんなことをやっていきます。
サンプルはテキストを Flutter で入力し、Update ボタン で Rive のテキストを更新します。
PUSH(Rive 内のボタン)を押してアニメーションする。
1. Rive でアニメーションを作成
Rive でアニメーションを作成する。
PUSH ボタンを押すとアニメーションするのは Rive 側で実装しています。
テキストのウェーブのような動きは下記が参考になると思います。
次に、
動的に扱いたいテキストの"Text Run"オブジェクトの名前を任意のもの変更する。
今回は"textInput"とする。
右クリックから Export Name を選択する。
表示が"[ ]"形式に変更されれば OK
下記は、今回作成したサンプルアニメーションです。
2. Flutter で実装
上記で作成したアニメーションをインポートします。
基本的な Rive の Flutter での実装は他に譲ります。
Flutter 内では先程指定した任意の名前"textInput"を使って TextRun オブジェクトを取得します。
artboard.component<TextValueRun>('textInput');
初期化時に取得
TextValueRun? _textRun;
void _onRiveInit(Artboard artboard) {
_artboard = artboard;
final controller = StateMachineController.fromArtboard(
artboard,
'State Machine 1',
);
artboard.addController(controller!);
_textRun = artboard.component<TextValueRun>('textInput'); // <-
_resetTrigger = controller.getTriggerInput('reset');
}
あとは任意のテキストを入力して更新するだけです。
void _updateText(String newValue) {
setState(() {
if (_textRun != null) {
_textRun!.text = newValue;
}
});
}
最後に
基本的な実装は下記が参考になるかなと思うので、宜しければ。
機能のアップデートも多い Rive ですので古い情報となっている場合はすいません 🙇
2024/11 v0.8 の情報になります。
コード全文
class RiveTextInputWidget extends StatefulWidget {
const RiveTextInputWidget({super.key});
_RiveTextInputWidgetState createState() => _RiveTextInputWidgetState();
}
class _RiveTextInputWidgetState extends State<RiveTextInputWidget> {
TextValueRun? _textRun;
Artboard? _artboard;
SMITrigger? _resetTrigger;
String _setText = '';
final TextEditingController _textController = TextEditingController();
void _onRiveInit(Artboard artboard) {
_artboard = artboard;
final controller = StateMachineController.fromArtboard(
artboard,
'State Machine 1',
);
artboard.addController(controller!);
_textRun = artboard.component<TextValueRun>('textInput');
_resetTrigger = controller.getTriggerInput('reset');
}
void _updateText(String newValue) {
setState(() {
if (_textRun != null) {
_textRun!.text = newValue;
_setText = newValue;
}
});
_resetTrigger?.fire();
_textController.clear();
}
Widget build(BuildContext context) {
return Column(
children: [
Expanded(
child: RiveAnimation.asset(
'assets/rive/text_input.riv',
onInit: _onRiveInit,
fit: BoxFit.contain,
),
),
Container(
width: double.infinity,
margin: const EdgeInsets.all(24.0),
decoration: const BoxDecoration(
border:
Border(bottom: BorderSide(width: 2, color: Colors.white))),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text("Set Text",
style: TextStyle(fontSize: 24, color: Colors.white)),
Text(_setText, style: const TextStyle(fontSize: 24)),
],
),
),
Padding(
padding: const EdgeInsets.all(24.0),
child: TextField(
controller: _textController,
),
),
ElevatedButton(
onPressed: () => _updateText(_textController.text),
child: const Text('Update')),
],
);
}
}
Discussion