AppBar
的bottom属性的类型为PreferredSizeWidget
,因此我提供了PreferredSize
小部件,该小部件要求preferredSize
属性中指定要使用的实际大小。但是我不需要静态数,而是根据子项自动计算,在我的情况下是Wrap
小部件。问题在于,只有在使用Wrap
调用build
方法之后才能确定RenderObject
的高度。
我所拥有的:
我想要的(由gif编辑软件制作):
代码:
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
final items = List.generate(400, (index) => '$index');
final filterOptions = <IntType>[];
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: buildBody(),
appBar: AppBar(
title: Text('Simple filtering'),
bottom: buildAppBarBottom(),
),
),
);
}
Widget buildBody() {
return Scrollbar(
child: ListView.builder(
itemCount: items.length,
itemBuilder: (context, index) {
final item = items[index];
if (filterOptions.every((option) => item.contains(option.symbol))) {
return ListTile(title: Text(item));
}
return Container(height: 0.0001);
},
),
);
}
PreferredSizeWidget buildAppBarBottom() {
return PreferredSize(
preferredSize: Size.fromHeight(100), // change height depending on the child height
child: Wrap(
spacing: 8,
children: IntType.values.map((option) {
return FilterChip(
selectedColor: Colors.white,
selected: filterOptions.contains(option),
onSelected: (isSelected) {
setState(() {
if (isSelected) {
filterOptions.add(option);
} else {
filterOptions.remove(option);
}
});
},
label: Text(option.name),
);
}).toList(),
),
);
}
}
class IntType {
static const IntType one = const IntType._('One', '1');
static const IntType two = const IntType._('Two', '2');
static const IntType three = const IntType._('Three', '3');
static const IntType four = const IntType._('Four', '4');
static const IntType five = const IntType._('Five', '5');
static const IntType six = const IntType._('Six', '6');
static const IntType seven = const IntType._('Seven', '7');
static const IntType eight = const IntType._('Eight', '8');
static const IntType nine = const IntType._('Nine', '9');
static const IntType zero = const IntType._('Zero', '0');
final String name;
final String symbol;
const IntType._(this.name, this.symbol);
static const values = [
IntType.one,
IntType.two,
IntType.three,
IntType.four,
IntType.five,
IntType.six,
IntType.seven,
IntType.eight,
IntType.nine,
IntType.zero,
];
}
编辑:
感谢AKS回答
解决方法是将Wrap
移至Scaffold
的身体
更新的代码:
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
final items = List.generate(400, (index) => '$index');
final filterOptions = <IntType>[];
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(appBarTheme: AppBarTheme(elevation: 0)),
home: Scaffold(
body: buildBody(),
appBar: AppBar(
title: Text('Simple filtering'),
),
),
);
}
Widget buildBody() {
return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Material(
elevation: 4,
child: Container(
color: Theme.of(context).primaryColor,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Wrap(
alignment: WrapAlignment.center,
spacing: 8,
children: IntType.values.map((option) {
return FilterChip(
selectedColor: Colors.white,
selected: filterOptions.contains(option),
onSelected: (isSelected) {
setState(() {
if (isSelected) {
filterOptions.add(option);
} else {
filterOptions.remove(option);
}
});
},
label: Text(option.name),
);
}).toList(),
),
),
),
),
Expanded(
child: Scrollbar(
child: ListView.builder(
itemCount: items.length,
itemBuilder: (context, index) {
final item = items[index];
if (filterOptions
.every((option) => item.contains(option.symbol))) {
return ListTile(title: Text(item));
}
return Container(height: 0.0001);
},
),
),
),
],
);
}
}
class IntType {
static const IntType one = const IntType._('One', '1');
static const IntType two = const IntType._('Two', '2');
static const IntType three = const IntType._('Three', '3');
static const IntType four = const IntType._('Four', '4');
static const IntType five = const IntType._('Five', '5');
static const IntType six = const IntType._('Six', '6');
static const IntType seven = const IntType._('Seven', '7');
static const IntType eight = const IntType._('Eight', '8');
static const IntType nine = const IntType._('Nine', '9');
static const IntType zero = const IntType._('Zero', '0');
final String name;
final String symbol;
const IntType._(this.name, this.symbol);
static const values = [
IntType.one,
IntType.two,
IntType.three,
IntType.four,
IntType.five,
IntType.six,
IntType.seven,
IntType.eight,
IntType.nine,
IntType.zero,
];
}
答案 0 :(得分:1)
您应该制作一列,而不是使用bottomAppbar属性,并添加两个子对象,其中一个用于模拟 bottom appBar ,另一个用于 actual body ,然后添加{ {1}}内的小部件,
通过这种方式,您可以获得完全相同的窗口小部件结构,而不会妨碍Appbar小部件中的文本。
希望此解决方案有帮助。