|
|
@ -72,6 +72,11 @@ class HomeView extends GetView<HomeController> { |
|
|
|
|
|
|
|
|
@override |
|
|
@override |
|
|
Widget build(BuildContext context) { |
|
|
Widget build(BuildContext context) { |
|
|
|
|
|
// 预缓存图片 |
|
|
|
|
|
precacheImage( |
|
|
|
|
|
const AssetImage('assets/images/headphone_new3.png'), context); |
|
|
|
|
|
precacheImage( |
|
|
|
|
|
const AssetImage('assets/images/headphone_new4.png'), context); |
|
|
final bool isDarkMode = Theme.of(context).brightness == Brightness.dark; |
|
|
final bool isDarkMode = Theme.of(context).brightness == Brightness.dark; |
|
|
return Scaffold( |
|
|
return Scaffold( |
|
|
backgroundColor: isDarkMode ? Colors.black : const Color(0xFFF9FAFC), |
|
|
backgroundColor: isDarkMode ? Colors.black : const Color(0xFFF9FAFC), |
|
|
@ -83,77 +88,79 @@ class HomeView extends GetView<HomeController> { |
|
|
children: [ |
|
|
children: [ |
|
|
// 顶部标题栏 |
|
|
// 顶部标题栏 |
|
|
_buildAppBar(isDarkMode), |
|
|
_buildAppBar(isDarkMode), |
|
|
|
|
|
// 可变高度的顶部图片区域 - 使用Expanded让它占用剩余空间 |
|
|
// 可变高度的顶部图片区域 |
|
|
|
|
|
Obx(() => _buildAdaptiveEarbudsImage()), |
|
|
|
|
|
|
|
|
|
|
|
SizedBox(height: 20.h), |
|
|
|
|
|
|
|
|
|
|
|
// 设备状态卡片 - 使用 AnimatedContainer 实现平滑过渡 |
|
|
|
|
|
IntroStepBuilder( |
|
|
|
|
|
group: 'home', |
|
|
|
|
|
order: 1, |
|
|
|
|
|
onWidgetLoad: () { |
|
|
|
|
|
controller.noviceGuideService.startHomeGuide(); |
|
|
|
|
|
}, |
|
|
|
|
|
overlayBuilder: (params) { |
|
|
|
|
|
return IntroOverlayBuilder.aiBuilder( |
|
|
|
|
|
params, |
|
|
|
|
|
'欢迎使用Voitrans!首先,让我们唤醒你的专属 AI—— 小言', |
|
|
|
|
|
onNext: () { |
|
|
|
|
|
controller.noviceGuideService.startWakeupListen(); |
|
|
|
|
|
}, |
|
|
|
|
|
); |
|
|
|
|
|
}, |
|
|
|
|
|
builder: (BuildContext context, GlobalKey key) => SizedBox( |
|
|
|
|
|
key: key, |
|
|
|
|
|
child: _buildAnimatedDeviceStatusCard(isDarkMode), |
|
|
|
|
|
), |
|
|
|
|
|
), |
|
|
|
|
|
|
|
|
|
|
|
SizedBox(height: 20.h), |
|
|
|
|
|
|
|
|
|
|
|
IntroStepBuilder( |
|
|
|
|
|
group: 'home', |
|
|
|
|
|
order: 2, |
|
|
|
|
|
getOverlayPosition: ({ |
|
|
|
|
|
required Offset offset, |
|
|
|
|
|
required Size screenSize, |
|
|
|
|
|
required Size size, |
|
|
|
|
|
}) { |
|
|
|
|
|
return OverlayPosition( |
|
|
|
|
|
top: 200.h, |
|
|
|
|
|
width: screenSize.width, |
|
|
|
|
|
crossAxisAlignment: CrossAxisAlignment.end, |
|
|
|
|
|
); |
|
|
|
|
|
}, |
|
|
|
|
|
overlayBuilder: (params) { |
|
|
|
|
|
return Obx( |
|
|
|
|
|
() => IntroOverlayBuilder.homeBuilder( |
|
|
|
|
|
params, |
|
|
|
|
|
controller.noviceGuideService.isWakeup.value, |
|
|
|
|
|
onNext: () { |
|
|
|
|
|
controller.noviceGuideService.closeWakeupListen(); |
|
|
|
|
|
}, |
|
|
|
|
|
), |
|
|
|
|
|
); |
|
|
|
|
|
}, |
|
|
|
|
|
builder: (BuildContext context, GlobalKey key) => SizedBox( |
|
|
|
|
|
key: key, |
|
|
|
|
|
), |
|
|
|
|
|
), |
|
|
|
|
|
|
|
|
|
|
|
// 热门AI体验 - 使用 Expanded 确保始终在可视范围内 |
|
|
|
|
|
Expanded( |
|
|
Expanded( |
|
|
child: Column( |
|
|
child: Column( |
|
|
crossAxisAlignment: CrossAxisAlignment.start, |
|
|
|
|
|
children: [ |
|
|
children: [ |
|
|
_buildSectionTitle(isDarkMode), |
|
|
Obx(() => _buildAdaptiveEarbudsImage()), |
|
|
SizedBox(height: 16.h), |
|
|
SizedBox(height: 20.h), |
|
|
Expanded(child: _buildPremiumAILayout()), |
|
|
// 设备状态卡片 |
|
|
|
|
|
IntroStepBuilder( |
|
|
|
|
|
group: 'home', |
|
|
|
|
|
order: 1, |
|
|
|
|
|
onWidgetLoad: () { |
|
|
|
|
|
controller.noviceGuideService.startHomeGuide(); |
|
|
|
|
|
}, |
|
|
|
|
|
overlayBuilder: (params) { |
|
|
|
|
|
return IntroOverlayBuilder.aiBuilder( |
|
|
|
|
|
params, |
|
|
|
|
|
'欢迎使用Voitrans!首先,让我们唤醒你的专属 AI—— 小言', |
|
|
|
|
|
onNext: () { |
|
|
|
|
|
controller.noviceGuideService.startWakeupListen(); |
|
|
|
|
|
}, |
|
|
|
|
|
); |
|
|
|
|
|
}, |
|
|
|
|
|
builder: (BuildContext context, GlobalKey key) => |
|
|
|
|
|
SizedBox( |
|
|
|
|
|
key: key, |
|
|
|
|
|
child: _buildAnimatedDeviceStatusCard(isDarkMode), |
|
|
|
|
|
), |
|
|
|
|
|
), |
|
|
|
|
|
SizedBox(height: 20.h), |
|
|
|
|
|
IntroStepBuilder( |
|
|
|
|
|
group: 'home', |
|
|
|
|
|
order: 2, |
|
|
|
|
|
getOverlayPosition: ({ |
|
|
|
|
|
required Offset offset, |
|
|
|
|
|
required Size screenSize, |
|
|
|
|
|
required Size size, |
|
|
|
|
|
}) { |
|
|
|
|
|
return OverlayPosition( |
|
|
|
|
|
top: 200.h, |
|
|
|
|
|
width: screenSize.width, |
|
|
|
|
|
crossAxisAlignment: CrossAxisAlignment.end, |
|
|
|
|
|
); |
|
|
|
|
|
}, |
|
|
|
|
|
overlayBuilder: (params) { |
|
|
|
|
|
return Obx( |
|
|
|
|
|
() => IntroOverlayBuilder.homeBuilder( |
|
|
|
|
|
params, |
|
|
|
|
|
controller.noviceGuideService.isWakeup.value, |
|
|
|
|
|
onNext: () { |
|
|
|
|
|
controller.noviceGuideService.closeWakeupListen(); |
|
|
|
|
|
}, |
|
|
|
|
|
), |
|
|
|
|
|
); |
|
|
|
|
|
}, |
|
|
|
|
|
builder: (BuildContext context, GlobalKey key) => |
|
|
|
|
|
SizedBox( |
|
|
|
|
|
key: key, |
|
|
|
|
|
), |
|
|
|
|
|
), |
|
|
], |
|
|
], |
|
|
), |
|
|
), |
|
|
), |
|
|
), |
|
|
|
|
|
// 热门AI体验 - 固定在底部,基于内容的固定高度 |
|
|
|
|
|
Column( |
|
|
|
|
|
crossAxisAlignment: CrossAxisAlignment.start, |
|
|
|
|
|
mainAxisSize: MainAxisSize.min, // 重要:让高度基于内容 |
|
|
|
|
|
children: [ |
|
|
|
|
|
_buildSectionTitle(isDarkMode), |
|
|
|
|
|
SizedBox(height: 16.h), |
|
|
|
|
|
// 给AI布局一个固定的高度,或者让它基于内容自适应 |
|
|
|
|
|
_buildPremiumAILayout(), |
|
|
|
|
|
], |
|
|
|
|
|
), |
|
|
], |
|
|
], |
|
|
), |
|
|
), |
|
|
), |
|
|
), |
|
|
@ -203,40 +210,39 @@ class HomeView extends GetView<HomeController> { |
|
|
); |
|
|
); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 自适应高度的耳机图片 - 根据设备连接状态动态调整高度 |
|
|
// 自适应高度的耳机图片 - 根据设备连接状态动态调整高度 |
|
|
|
|
|
// 在自适应图片组件中添加RepaintBoundary |
|
|
Widget _buildAdaptiveEarbudsImage() { |
|
|
Widget _buildAdaptiveEarbudsImage() { |
|
|
final bool isDarkMode = Get.isDarkMode; |
|
|
final bool isDarkMode = Get.isDarkMode; |
|
|
// 根据设备连接状态调整图片高度 |
|
|
final double imageHeight = |
|
|
// 已连接时高度较小,为设备信息让出空间;未连接时高度较大 |
|
|
controller.isFullyConnectedRx.value ? 160.h : 220.h; |
|
|
final double imageHeight = controller.isFullyConnectedRx.value ? 160.h : 220.h; |
|
|
|
|
|
|
|
|
return RepaintBoundary( |
|
|
return AnimatedContainer( |
|
|
// 添加重绘边界,优化动画性能 |
|
|
duration: const Duration(milliseconds: 500), // 平滑过渡动画 |
|
|
child: AnimatedContainer( |
|
|
curve: Curves.easeInOut, |
|
|
duration: const Duration(milliseconds: 500), |
|
|
height: imageHeight, |
|
|
curve: Curves.easeInOut, |
|
|
child: PageView( |
|
|
height: imageHeight, |
|
|
children: [ |
|
|
child: PageView( |
|
|
Center( |
|
|
children: [ |
|
|
child: ClipRRect( |
|
|
Center( |
|
|
borderRadius: BorderRadius.circular(16.r), |
|
|
child: ClipRRect( |
|
|
child: Image.asset( |
|
|
borderRadius: BorderRadius.circular(16.r), |
|
|
isDarkMode |
|
|
child: Image.asset( |
|
|
? 'assets/images/headphone_new3.png' |
|
|
isDarkMode |
|
|
: 'assets/images/headphone_new4.png', |
|
|
? 'assets/images/headphone_new3.png' |
|
|
height: imageHeight, |
|
|
: 'assets/images/headphone_new4.png', |
|
|
fit: BoxFit.contain, |
|
|
height: imageHeight, |
|
|
|
|
|
fit: BoxFit.contain, |
|
|
|
|
|
), |
|
|
), |
|
|
), |
|
|
), |
|
|
), |
|
|
), |
|
|
], |
|
|
], |
|
|
), |
|
|
), |
|
|
), |
|
|
); |
|
|
); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 带动画的设备状态卡片 - 实现平滑的高度变化过渡 |
|
|
// 带动画的设备状态卡片 - 实现平滑的高度变化过渡 |
|
|
Widget _buildAnimatedDeviceStatusCard(bool isDarkMode) { |
|
|
Widget _buildAnimatedDeviceStatusCard(bool isDarkMode) { |
|
|
return Obx(() { |
|
|
return Obx(() { |
|
|
|