- 新增模型目录占位文件与翻译类型拆分 - 调整路由配置与桌面端窗口初始化 - 移除多处冗余图表配置项 - 重构右侧面板注册表与三栏布局组件 - 添加智能AppBar、拖拽书签等新功能组件 - 优化安卓编译配置与多平台插件注册 - 新增翻译覆盖率测试与共享组件 - 格式化代码与修复静态分析警告
99 lines
2.6 KiB
Dart
99 lines
2.6 KiB
Dart
/// ============================================================
|
||
/// 闲言APP — Rive Tab 动画组件
|
||
/// 创建时间: 2026-05-29
|
||
/// 更新时间: 2026-05-29
|
||
/// 作用: 使用Rive动画替代TabIconSprite,实现更丰富的角色动画
|
||
/// 上次更新: 初始创建
|
||
/// ============================================================
|
||
|
||
import 'package:flutter/cupertino.dart';
|
||
import 'package:rive/rive.dart';
|
||
|
||
/// Rive Tab 动画图标组件
|
||
///
|
||
/// 通过 Rive StateMachine 控制选中/未选中状态切换,
|
||
/// 作为 TabIconSprite 的可选替代方案。
|
||
/// 需要提供 .riv 资源文件,StateMachine 中需包含
|
||
/// 名为 `isSelected` 的布尔输入。
|
||
class RiveTabIcon extends StatefulWidget {
|
||
const RiveTabIcon({
|
||
required this.isSelected,
|
||
required this.assetPath,
|
||
this.stateMachineName = 'State',
|
||
this.size = 32,
|
||
super.key,
|
||
});
|
||
|
||
/// 是否选中
|
||
final bool isSelected;
|
||
|
||
/// Rive 资源路径 (如 'assets/animations/tab_home.riv')
|
||
final String assetPath;
|
||
|
||
/// StateMachine 名称
|
||
final String stateMachineName;
|
||
|
||
/// 图标尺寸
|
||
final double size;
|
||
|
||
@override
|
||
State<RiveTabIcon> createState() => _RiveTabIconState();
|
||
}
|
||
|
||
class _RiveTabIconState extends State<RiveTabIcon> {
|
||
SMIInput<bool>? _selectedInput;
|
||
Artboard? _artboard;
|
||
|
||
@override
|
||
void initState() {
|
||
super.initState();
|
||
_loadRive();
|
||
}
|
||
|
||
/// 加载 Rive 文件并初始化 StateMachine
|
||
Future<void> _loadRive() async {
|
||
try {
|
||
final data = await RiveFile.asset(widget.assetPath);
|
||
final artboard = data.mainArtboard;
|
||
final controller = StateMachineController.fromArtboard(
|
||
artboard,
|
||
widget.stateMachineName,
|
||
);
|
||
if (controller != null) {
|
||
artboard.addController(controller);
|
||
_selectedInput = controller.findInput<bool>('isSelected');
|
||
_selectedInput?.value = widget.isSelected;
|
||
}
|
||
if (mounted) {
|
||
setState(() => _artboard = artboard);
|
||
}
|
||
} catch (e) {
|
||
// Rive文件加载失败时静默处理,不影响其他功能
|
||
}
|
||
}
|
||
|
||
@override
|
||
void didUpdateWidget(RiveTabIcon oldWidget) {
|
||
super.didUpdateWidget(oldWidget);
|
||
if (oldWidget.isSelected != widget.isSelected) {
|
||
_selectedInput?.value = widget.isSelected;
|
||
}
|
||
}
|
||
|
||
@override
|
||
Widget build(BuildContext context) {
|
||
if (_artboard == null) {
|
||
return SizedBox(
|
||
width: widget.size,
|
||
height: widget.size,
|
||
child: const CupertinoActivityIndicator(radius: 8),
|
||
);
|
||
}
|
||
return SizedBox(
|
||
width: widget.size,
|
||
height: widget.size,
|
||
child: Rive(artboard: _artboard!),
|
||
);
|
||
}
|
||
}
|