在屏幕底部关闭ListView

时间:2020-03-16 12:47:07

标签: listview flutter dart

在Flutter应用中,我具有如下的窗口小部件结构:

Container(
  height: variable,
  child: ListView(
    children: <Widget>[
      ...,
      ListView(),
    ],
  ),
),

如何设置最后一个ListView的高度,使其完全占据外部Container的剩余空间? 内部ListView的剩余高度也是可变的,因为ListView定位在另一个ListView内,可以位于不同的滚动位置。

屏幕如下所示: enter image description here

提到的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,
              ),
            ],
          ),

1 个答案:

答案 0 :(得分:-1)

如果我了解您要实现的目标,我建议您这样做

Container( height: variable, child: Column( children: <Widget>[ ..., Expanded( child : ListView(), ), ], ), ),