import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:flutter_blue_plus/flutter_blue_plus.dart' as fbp; import '../controllers/ble_controller.dart'; class BleView extends GetView { const BleView({Key? key}) : super(key: key); @override Widget build(BuildContext context) { final bool isDarkMode = Theme.of(context).brightness == Brightness.dark; return Scaffold( backgroundColor: isDarkMode ? Colors.black : Colors.white, appBar: AppBar( title: Text( 'BLE设备扫描', style: TextStyle( color: isDarkMode ? Colors.white : Colors.black, fontSize: 18.sp, fontWeight: FontWeight.bold, ), ), backgroundColor: isDarkMode ? Colors.grey[900] : Colors.white, elevation: 0, iconTheme: IconThemeData( color: isDarkMode ? Colors.white : Colors.black, ), actions: [ Obx(() => IconButton( onPressed: controller.isScanning.value ? controller.stopScan : controller.startScan, icon: Icon( controller.isScanning.value ? Icons.stop : Icons.refresh, color: controller.isScanning.value ? Colors.red : (isDarkMode ? Colors.white : Colors.black), ), )), ], ), body: SafeArea( child: Column( children: [ // 状态栏 _buildStatusBar(isDarkMode), // 连接的设备信息 _buildConnectedDevice(isDarkMode), // 设备列表 Expanded( child: _buildDeviceList(isDarkMode), ), ], ), ), floatingActionButton: Obx(() => FloatingActionButton( onPressed: controller.isScanning.value ? controller.stopScan : controller.startScan, backgroundColor: controller.isScanning.value ? Colors.red : Colors.blue, child: Icon( controller.isScanning.value ? Icons.stop : Icons.bluetooth_searching, color: Colors.white, ), )), ); } // 状态栏 Widget _buildStatusBar(bool isDarkMode) { return Obx(() => Container( width: double.infinity, padding: EdgeInsets.all(16.w), margin: EdgeInsets.all(16.w), decoration: BoxDecoration( color: isDarkMode ? Colors.grey[800] : Colors.grey[100], borderRadius: BorderRadius.circular(12.r), ), child: Column( children: [ Row( children: [ Icon( controller.isBluetoothOn.value ? Icons.bluetooth : Icons.bluetooth_disabled, color: controller.isBluetoothOn.value ? Colors.blue : Colors.red, size: 24.w, ), SizedBox(width: 8.w), Text( controller.isBluetoothOn.value ? '蓝牙已开启' : '蓝牙已关闭', style: TextStyle( color: isDarkMode ? Colors.white : Colors.black, fontSize: 16.sp, fontWeight: FontWeight.w500, ), ), Spacer(), if (controller.isScanning.value) SizedBox( width: 20.w, height: 20.w, child: CircularProgressIndicator( strokeWidth: 2, valueColor: AlwaysStoppedAnimation(Colors.blue), ), ), ], ), if (controller.errorMessage.value.isNotEmpty) ...[ SizedBox(height: 8.h), Text( controller.errorMessage.value, style: TextStyle( color: Colors.red, fontSize: 14.sp, ), ), ], if (controller.isScanning.value) ...[ SizedBox(height: 8.h), Text( '正在扫描设备...', style: TextStyle( color: Colors.blue, fontSize: 14.sp, ), ), ], ], ), )); } // 已连接设备信息 Widget _buildConnectedDevice(bool isDarkMode) { return Obx(() { if (controller.connectedDevice.value == null) { return SizedBox.shrink(); } final device = controller.connectedDevice.value!; return Container( width: double.infinity, padding: EdgeInsets.all(16.w), margin: EdgeInsets.symmetric(horizontal: 16.w, vertical: 8.h), decoration: BoxDecoration( color: Colors.green.withOpacity(0.1), border: Border.all(color: Colors.green, width: 1), borderRadius: BorderRadius.circular(12.r), ), child: Row( children: [ Icon( Icons.bluetooth_connected, color: Colors.green, size: 24.w, ), SizedBox(width: 12.w), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( '已连接设备', style: TextStyle( color: Colors.green, fontSize: 12.sp, fontWeight: FontWeight.w500, ), ), Text( device.platformName.isNotEmpty ? device.platformName : '未知设备', style: TextStyle( color: isDarkMode ? Colors.white : Colors.black, fontSize: 16.sp, fontWeight: FontWeight.bold, ), ), Text( device.remoteId.toString(), style: TextStyle( color: isDarkMode ? Colors.white70 : Colors.black54, fontSize: 12.sp, ), ), ], ), ), IconButton( onPressed: controller.disconnectDevice, icon: Icon( Icons.close, color: Colors.red, size: 20.w, ), ), ], ), ); }); } // 设备列表 Widget _buildDeviceList(bool isDarkMode) { return Obx(() { if (controller.scanResults.isEmpty) { return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon( Icons.bluetooth_searching, size: 64.w, color: isDarkMode ? Colors.white54 : Colors.black54, ), SizedBox(height: 16.h), Text( controller.isScanning.value ? '正在搜索设备...' : '点击扫描按钮开始搜索BLE设备', style: TextStyle( color: isDarkMode ? Colors.white54 : Colors.black54, fontSize: 16.sp, ), textAlign: TextAlign.center, ), ], ), ); } return ListView.builder( padding: EdgeInsets.symmetric(horizontal: 16.w), itemCount: controller.scanResults.length, itemBuilder: (context, index) { final result = controller.scanResults[index]; return _buildDeviceItem(result, isDarkMode); }, ); }); } // 设备项 Widget _buildDeviceItem(fbp.ScanResult result, bool isDarkMode) { final deviceName = controller.getDeviceName(result); final isConnected = controller.connectedDevice.value?.remoteId == result.device.remoteId; return Container( margin: EdgeInsets.only(bottom: 12.h), decoration: BoxDecoration( color: isDarkMode ? Colors.grey[800] : Colors.white, borderRadius: BorderRadius.circular(12.r), border: Border.all( color: isConnected ? Colors.green : (isDarkMode ? Colors.grey[700]! : Colors.grey[300]!), width: isConnected ? 2 : 1, ), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.05), blurRadius: 8, offset: Offset(0, 2), ), ], ), child: ListTile( contentPadding: EdgeInsets.all(16.w), leading: Container( width: 48.w, height: 48.w, decoration: BoxDecoration( color: isConnected ? Colors.green.withOpacity(0.1) : Colors.blue.withOpacity(0.1), borderRadius: BorderRadius.circular(24.r), ), child: Icon( isConnected ? Icons.bluetooth_connected : Icons.bluetooth, color: isConnected ? Colors.green : Colors.blue, size: 24.w, ), ), title: Text( deviceName, style: TextStyle( color: isDarkMode ? Colors.white : Colors.black, fontSize: 16.sp, fontWeight: FontWeight.bold, ), ), subtitle: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ SizedBox(height: 4.h), Text( result.device.remoteId.toString(), style: TextStyle( color: isDarkMode ? Colors.white70 : Colors.black54, fontSize: 12.sp, ), ), SizedBox(height: 4.h), Row( children: [ Icon( controller.getSignalStrengthIcon(result.rssi), size: 16.w, color: isDarkMode ? Colors.white70 : Colors.black54, ), SizedBox(width: 4.w), Text( '${result.rssi} dBm (${controller.getSignalStrengthText(result.rssi)})', style: TextStyle( color: isDarkMode ? Colors.white70 : Colors.black54, fontSize: 12.sp, ), ), ], ), ], ), trailing: isConnected ? Icon( Icons.check_circle, color: Colors.green, size: 24.w, ) : IconButton( onPressed: () => controller.connectToDevice(result.device), icon: Icon( Icons.connect_without_contact, color: Colors.blue, size: 24.w, ), ), onTap: isConnected ? null : () => controller.connectToDevice(result.device), ), ); } }