Flutter蓝牙设备列表渲染错误求助:RenderFlex hasSize断言失败
问题分析
你的渲染错误核心原因是外层Column没有明确的高度约束,导致它的高度被评估为无限大,进而内部的Flexible和ListView无法正确计算布局空间,触发了无限高度的断言失败。从错误日志里的BoxConstraints(0.0<=w<=360.0, 0.0<=h<=Infinity)也能验证这一点——当前Column的高度没有上限。
解决方案
将整个页面结构包裹在Scaffold中,利用Scaffold的body提供屏幕级的高度约束;同时调整组件布局逻辑,确保内部元素能正确分配空间。
修改后的完整代码
import 'package:flutter/material.dart'; import 'package:flutter_blue_plus/flutter_blue_plus.dart'; class BluetoothScreen extends StatefulWidget { @override _BluetoothScreenState createState() => _BluetoothScreenState(); } class _BluetoothScreenState extends State<BluetoothScreen> { List<BluetoothDevice> devicesList = []; BluetoothDevice? connectedDevice; bool isScanning = false; @override void initState() { super.initState(); scanForDevices(); } void scanForDevices() async { setState(() { isScanning = true; devicesList.clear(); }); // 利用startScan的timeout自动停止扫描,无需额外延迟 FlutterBluePlus.startScan(timeout: const Duration(seconds: 4)); final subscription = FlutterBluePlus.scanResults.listen((results) { setState(() { devicesList = results.map((r) => r.device).toList(); }); }); // 监听扫描状态,结束后取消订阅避免内存泄漏 await FlutterBluePlus.isScanning.firstWhere((isScanning) => !isScanning); subscription.cancel(); setState(() { isScanning = false; }); } void connectToDevice(BluetoothDevice device) async { await device.connect(); setState(() { connectedDevice = device; }); } void disconnectFromDevice() async { if (connectedDevice != null) { await connectedDevice!.disconnect(); setState(() { connectedDevice = null; }); } } @override Widget build(BuildContext context) { // 用Scaffold作为页面根Widget,提供正确的布局约束 return Scaffold( appBar: AppBar(title: const Text('蓝牙设备连接')), body: Column( children: <Widget>[ // 用Expanded确保设备列表区域占据剩余可用高度 Expanded( child: isScanning ? const Center(child: CircularProgressIndicator()) : devicesList.isEmpty ? const Center(child: Text('未找到设备')) : ListView.builder( itemCount: devicesList.length, itemBuilder: (context, index) { final device = devicesList[index]; return ListTile( title: Text(device.name.isNotEmpty ? device.name : '无名称设备'), subtitle: Text(device.id.toString()), onTap: () { connectToDevice(device); }, ); }, ), ), if (connectedDevice != null) Padding( padding: const EdgeInsets.all(10.0), child: Column( mainAxisSize: MainAxisSize.min, children: [ Text('已连接至 ${connectedDevice!.name}'), ElevatedButton( onPressed: disconnectFromDevice, child: const Text('断开连接'), ), ], ), ), Padding( padding: const EdgeInsets.all(8.0), child: ElevatedButton( onPressed: scanForDevices, child: const Text('扫描设备'), ), ), ], ), ); } }
关键修改点
- 用
Scaffold作为页面根组件,通过它的body提供屏幕高度约束,彻底解决无限高度问题 - 将外层的
Flexible替换为Expanded,确保设备列表区域能占据屏幕剩余可用高度 - 优化扫描逻辑:利用
FlutterBluePlus.isScanning流监听扫描结束,取消订阅避免内存泄漏,同时去掉冗余的Future.delayed
内容的提问来源于stack exchange,提问作者marco
相关产品推荐
相关产品推荐

