FittedBox内嵌套的水平ListView无法正常滚动问题咨询
问题原因
- 横向
ListView可滚动的核心前提是:内容总宽度 > ListView自身的视口宽度 - 你为
ListView设置了shrinkWrap: true,该属性会让ListView的视口宽度直接等于所有子项的总宽度,此时内容宽度与视口宽度完全相等,没有可滚动空间,自然无法响应滑动操作。 - 初始滚动偏移回弹的问题同理:布局完成后
ListView计算得到最大可滚动偏移为0,所以会自动回弹到偏移量为0的位置。 - 移除
FittedBox后滚动恢复的原因是:此时ListView的视口宽度等于父容器宽度,远小于20个子项的总宽度,满足滚动条件。
解决方法
核心思路是主动给ListView设置固定视口宽度,保证内容总宽度大于视口宽度,同时适配FittedBox的缩放规则:
- 用
LayoutBuilder获取FittedBox父容器的实际尺寸 - 根据
fit: BoxFit.fitHeight规则计算缩放比例:缩放比例 = FittedBox父容器高度 / 子Container固定高度 - 计算子Container需要设置的宽度:
子Container宽度 = FittedBox父容器宽度 / 缩放比例,该宽度经过FittedBox缩放后会刚好填满父容器的宽度 - 移除
ListView的shrinkWrap: true属性,因为已经为它的父容器设置了固定宽度,不需要自适应内容宽度
修改后的完整代码
import 'dart:ui'; import 'package:flutter/material.dart'; void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( scrollBehavior: MyCustomScrollBehavior(), home: Scaffold( body: Container( height: 200, child: LayoutBuilder( builder: (context, constraints) { // 子组件固定高度 const childFixedHeight = 100.0; // 计算FittedBox的缩放比例 final scale = constraints.maxHeight / childFixedHeight; // 计算子组件需要设置的宽度,缩放后刚好适配父容器宽度 final childWidth = constraints.maxWidth / scale; return FittedBox( alignment: const Alignment(-1, -1), fit: BoxFit.fitHeight, child: Container( height: childFixedHeight, width: childWidth, child: ListView.builder( itemCount: 20, scrollDirection: Axis.horizontal, itemBuilder: (context, index) => Container( width: 100, height: 100, child: Text(index.toString()), decoration: BoxDecoration(border: Border.all(width: 3, color: Colors.red)))), ), ); } ), )), ); } } class MyCustomScrollBehavior extends MaterialScrollBehavior { @override Set<PointerDeviceKind> get dragDevices => { PointerDeviceKind.touch, PointerDeviceKind.mouse, }; }
内容的提问来源于stack exchange,提问作者user2233706
相关产品推荐
相关产品推荐

