在Flutter应用中,我具有如下的窗口小部件结构:
Container(
height: variable,
child: ListView(
children: <Widget>[
...,
ListView(),
],
),
),
如何设置最后一个ListView的高度,使其完全占据外部Container的剩余空间? 内部ListView的剩余高度也是可变的,因为ListView定位在另一个ListView内,可以位于不同的滚动位置。
提到的ListView是您在底部看到的最后一个。问题在于,由于其尺寸太大,它实际上仍在屏幕外继续显示,因此无法从外部ListView的滚动位置滚动浏览整个列表。我该如何更改(在屏幕末尾剪切内部的ListView)? 代码是:
SnappingSheet(
// fixed part of sheet (dragable on this widget)
grabbingHeight: 90,
grabbing: Container(
decoration: BoxDecoration(
color: theme.backgroundColor,
boxShadow: [
BoxShadow(
blurRadius: 10.0,
color: Colors.black.withOpacity(0.3),
),
],
borderRadius: BorderRadius.only(
topLeft: Radius.circular(30.0),
topRight: Radius.circular(30.0),
),
),
child: Column(
children: <Widget>[
// drag indicator bar
Container(
width: 30.0,
height: 5.0,
margin: const EdgeInsets.only(
top: 8.8,
),
decoration: BoxDecoration(
color: theme.hintColor.withOpacity(0.2),
borderRadius: BorderRadius.all(
Radius.circular(
2.5,
),
),
),
),
// search field
Container(
padding: EdgeInsets.only(
top: 4.0,
),
child: ListTile(
title: TextFormField(
decoration: InputDecoration(
border: OutlineInputBorder(
borderRadius: BorderRadius.all(
Radius.circular(10.0),
),
borderSide: BorderSide(
color: theme.hintColor,
),
),
hintText: 'search for city/item/shop/category',
// TODO: turn into flexible icon to delete text
suffixIcon: Icon(Icons.search),
),
),
),
),
],
),
),
// dynamic part of sheet (scrollable)
sheetBelow: Container(
color: theme.backgroundColor,
child: ListView(
padding: const EdgeInsets.only(
top: 10.0,
),
children: <Widget>[
// label for recommended items
Padding(
padding: const EdgeInsets.symmetric(
horizontal: 18.0,
),
child: Text(
'Recommended items',
style: theme.textTheme.headline6,
),
),
// recommended items list view
Container(
height: 150.0,
margin: const EdgeInsets.only(
bottom: 10.0,
),
child: ListView.builder(
padding: const EdgeInsets.symmetric(
horizontal: 10.0,
),
scrollDirection: Axis.horizontal,
itemCount: globals.searchReturn.recommendedItems.length,
itemBuilder: (BuildContext context, int index) {
final ItemResult recommendedItem =
globals.searchReturn.recommendedItems[index];
// TODO: make card selectable
// recommended item card
return Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
color: theme.accentColor,
child: Stack(
children: <Widget>[
// recommended item image
Container(
decoration: BoxDecoration(
boxShadow: [
BoxShadow(
blurRadius: 4.0,
offset: Offset(0.0, 4.0),
color: Colors.black.withOpacity(0.5),
),
],
),
child: ClipRRect(
borderRadius: BorderRadius.circular(10.0),
child: Builder(
builder: (BuildContext context) {
try {
return Image.network(
recommendedItem.imageUrl,
height: 100.0,
width: 100.0,
fit: BoxFit.cover,
);
} catch (_) {
return Image.asset(
'assets/placeholder_image.png',
height: 100.0,
width: 100.0,
fit: BoxFit.cover,
);
}
},
),
),
),
// recommended item label
Positioned(
left: 5.0,
right: 5.0,
top: 107.0,
child: Container(
width: 100.0,
child: Text(
recommendedItem.name,
maxLines: 2,
overflow: TextOverflow.ellipsis,
style: theme.textTheme.subtitle2,
),
),
),
// button to switch to info page (for item)
Positioned(
right: 2.0,
top: 2.0,
child: Container(
height: 25.0,
width: 25.0,
child: CupertinoButton(
padding: const EdgeInsets.all(0.0),
child: Icon(
Icons.info_outline,
color: theme.hintColor,
),
),
),
),
],
),
);
},
),
),
// label for recommended shops
Padding(
padding: const EdgeInsets.symmetric(
horizontal: 18.0,
),
child: Text(
'Recommended shops',
style: theme.textTheme.headline6,
),
),
// recommended shops list view
Container(
height: 150.0,
margin: const EdgeInsets.only(
bottom: 10.0,
),
child: ListView.builder(
padding: const EdgeInsets.symmetric(
horizontal: 10.0,
),
scrollDirection: Axis.horizontal,
itemCount: globals.searchReturn.recommendedShops.length,
itemBuilder: (BuildContext context, int index) {
final ShopResult recommendedShop =
globals.searchReturn.recommendedShops[index];
// TODO: make card selectable
// recommended shop card
return Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
color: theme.accentColor,
child: Stack(
children: <Widget>[
// recommended shop image
Container(
decoration: BoxDecoration(
boxShadow: [
BoxShadow(
blurRadius: 4.0,
offset: Offset(0.0, 4.0),
color: Colors.black.withOpacity(0.5),
),
],
),
child: ClipRRect(
borderRadius: BorderRadius.circular(10.0),
child: Builder(
builder: (BuildContext context) {
try {
return Image.network(
recommendedShop.imageUrl,
height: 100.0,
width: 100.0,
fit: BoxFit.cover,
);
} catch (_) {
return Image.asset(
'assets/placeholder_image.png',
height: 100.0,
width: 100.0,
fit: BoxFit.cover,
);
}
},
),
),
),
// reccomended shop label
Positioned(
left: 5.0,
right: 5.0,
top: 107.0,
child: Container(
width: 100.0,
child: Text(
recommendedShop.name,
maxLines: 2,
overflow: TextOverflow.ellipsis,
style: theme.textTheme.subtitle2,
),
),
),
// button to switch to info page (for shop)
Positioned(
right: 2.0,
top: 2.0,
child: Container(
height: 25.0,
width: 25.0,
child: CupertinoButton(
padding: const EdgeInsets.all(0.0),
child: Icon(
Icons.info_outline,
color: theme.hintColor,
),
),
),
),
],
),
);
},
),
),
// search results label
Padding(
padding: const EdgeInsets.symmetric(
horizontal: 18.0,
),
child: Text(
'Search results',
style: theme.textTheme.headline6,
),
),
// search results list
Container(
// TODO: find right height
height: MediaQuery.of(context).size.height - 522.0,
child: ListView.builder(
padding: EdgeInsets.only(
left: 10.0, right: 10.0, top: 0.0, bottom: 10.0),
itemCount: globals.searchReturn.otherResults.length,
itemBuilder: (BuildContext context, int index) {
final SearchResult searchResult =
globals.searchReturn.otherResults[index];
// TODO: make card selectable
// Card for a search result
return Container(
height: 60.0,
child: Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
color: theme.accentColor,
child: Stack(
children: <Widget>[
// search result image
Container(
decoration: BoxDecoration(
boxShadow: [
BoxShadow(
blurRadius: 4.0,
offset: Offset(4.0, 4.0),
color: Colors.black.withOpacity(0.5),
),
],
),
child: ClipRRect(
borderRadius: BorderRadius.circular(10.0),
child: Builder(
builder: (BuildContext context) {
try {
return Image.network(
searchResult.imageUrl,
height: 60.0,
width: 60.0,
fit: BoxFit.cover,
);
} catch (_) {
return Image.asset(
'assets/placeholder_image.png',
height: 100.0,
width: 100.0,
fit: BoxFit.cover,
);
}
},
),
),
),
// search result name (title)
Positioned(
left: 69.0,
right: 45.0,
top: 4.0,
child: Text(
searchResult.name,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: theme.textTheme.subtitle2,
),
),
// search result address (subtitle)
Positioned(
left: 70.0,
right: 45.0,
top: 22.0,
child: Text(
searchResult.address,
maxLines: 2,
overflow: TextOverflow.ellipsis,
style: theme.textTheme.bodyText1,
),
),
// button to switch to info page
Positioned(
top: 0.0,
bottom: 0.0,
right: 0.0,
child: CupertinoButton(
padding: const EdgeInsets.all(0.0),
child: Icon(
Icons.info_outline,
color: theme.hintColor,
),
),
),
],
),
),
);
},
),
)
],
),
),
snapPositions: <SnapPosition>[
SnapPosition(
positionFactor: 0.0,
),
SnapPosition(
positionFactor: 0.5,
),
SnapPosition(
positionPixelFromTop: 30.0,
),
],
),
答案 0 :(得分:-1)
如果我了解您要实现的目标,我建议您这样做
Container(
height: variable,
child: Column(
children: <Widget>[
...,
Expanded(
child : ListView(),
),
],
),
),