【问题标题】:Partial Screen not Scrolling in FlutterFlutter 中部分屏幕不滚动
【发布时间】:2019-01-21 04:02:42
【问题描述】:

我正在尝试创建一个屏幕,其中 ListView 通过 API 响应填充,但我面临的问题是屏幕仅在滚动指向 ListView 上方时垂直滚动,但滚动时屏幕不滚动指向 ListView 上的任何其他点。

    import 'package:flutter/material.dart';
    import 'package:walk_himalaya/pages/Test/TestPlaceAttr.dart';
    import 'package:walk_himalaya/utils/UserConstants.dart';
    import 'package:walk_himalaya/utils/himayan_walk_constant.dart';
    import 'package:http/http.dart' as http;
    import 'dart:convert';
    void main() {
    runApp(new MaterialApp(
    home: TravelHomePage(),
    ));
    }

    class TravelHomePage extends StatefulWidget {
    TravelHomePageState createState() => new TravelHomePageState();
    }

    class TravelHomePageState extends State<TravelHomePage> {
    String access_token = UserConstants.userAccessToken;
    String token_type = UserConstants.bearerType;

    Future<List<dynamic>> getCategories() async {
    http.Response response =
        await http.get(HimalayanWalkConstant.baseURL + "places", headers: {
      'Accept': 'application/json',
      'Content-type': 'application/json',
      'Authorization': '$token_type' + ' $access_token'
    });
    Map<String, dynamic> decodedCategories = json.decode(response.body);
    return decodedCategories['data'];
   }

   @override
   Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.white,
      appBar: new AppBar(
        title: new Text("Destination Page"),
      ),
      body: ListView(
        scrollDirection: Axis.vertical,
        children: <Widget>[
          Container(
            padding: EdgeInsets.all(16.0),
            child: Row(
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
              children: <Widget>[
                Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: <Widget>[
                    Text(UserConstants.userDisplayName,
                        style: TextStyle(
                            fontSize: 18.0, fontWeight: FontWeight.bold)),
                    Text(
                      "Where do you want to go?",
                      style: TextStyle(color: Colors.grey.shade700),
                    )
                  ],
                ),
                CircleAvatar(
                  backgroundImage:
                      new NetworkImage(UserConstants.userProfileUrl),
                  radius: 40,
                )
              ],
            ),
          ),
          Container(
            padding: EdgeInsets.only(left: 16.0, right: 16.0, bottom: 8.0),
            child: Material(
              elevation: 5.0,
              child: TextField(
                decoration: InputDecoration(
                    hintText: "Find destination",
                    prefixIcon: Icon(Icons.location_on),
                    border: InputBorder.none),
              ),
            ),
          ),
          Container(
            child: FutureBuilder(
              future: getCategories(),
              builder: (BuildContext context,
                  AsyncSnapshot<List<dynamic>> snapshot) {
                if (snapshot.connectionState == ConnectionState.done) {
                  return ListView.builder(
                    shrinkWrap: true,
                    scrollDirection: Axis.vertical,
                    itemBuilder: (context, index) {
                      Map<String, String> data =
                          snapshot.data[index].cast<String, String>();
                      return SingleChildScrollView(
                        child: new SingleChildScrollView(
                          child: GestureDetector(
                            onTap: () => _openDestinationPage(context),
                            child: _buildFeaturedItem(
                              image: data['featured_image_url'],
                              title: data['title'],
                              subtitle: data['slug'],
                            ),
                          ),
                        ),
                      );
                    },
                    itemCount: snapshot.data.length,
                  );
                } else {
                  return Center(
                    child: CircularProgressIndicator(),
                  );
                }
              },
            ),
          )
        ],
      ),
    );
   }
   }

   Container _buildFeaturedItem({String image, String title, String subtitle}) {
   return Container(
    padding: EdgeInsets.only(left: 16.0, top: 8.0, right: 16.0, bottom: 16.0),
    child: Material(
      elevation: 5.0,
      shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(5.0)),
      child: Stack(
        children: <Widget>[
          ClipRRect(
              borderRadius: BorderRadius.circular(5.0),
              child: Image.network(
                image,
                fit: BoxFit.cover,
              )),
          Positioned(
            right: 10.0,
            top: 10.0,
            child: IconButton(
              onPressed: () {},
              icon: Icon(Icons.favorite_border, color: Colors.white),
            ),
          ),
          Positioned(
            bottom: 20.0,
            child: Container(
              padding: EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0),
              color: Colors.black.withOpacity(0.7),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                mainAxisAlignment: MainAxisAlignment.end,
                children: <Widget>[
                  Text(title,
                      style: TextStyle(
                          color: Colors.white,
                          fontSize: 20.0,
                          fontWeight: FontWeight.bold)),
                  Text(subtitle, style: TextStyle(color: Colors.white))
                ],
              ),
            ),
          ),
        ],
      ),
    ),
   );
   }

   _openDestinationPage(BuildContext context) {
   Navigator.push(context, MaterialPageRoute(builder: (_) => 
   DestinationPage()));
   }

总结我想要做的是垂直滚动整个屏幕。

【问题讨论】:

    标签: flutter flutter-layout


    【解决方案1】:

    这是优化后的代码,请改用它。

    import 'package:flutter/material.dart';
    import 'package:walk_himalaya/pages/Test/TestPlaceAttr.dart';
    import 'package:walk_himalaya/utils/UserConstants.dart';
    import 'package:walk_himalaya/utils/himayan_walk_constant.dart';
    import 'package:http/http.dart' as http;
    import 'dart:convert';
    import 'package:cached_network_image/cached_network_image.dart';
    
    void main() {
      runApp(new MaterialApp(
        home: TravelHomePage(),
      ));
    }
    
    class TravelHomePage extends StatefulWidget {
      TravelHomePageState createState() => new TravelHomePageState();
    }
    
    class TravelHomePageState extends State<TravelHomePage> {
      String access_token = UserConstants.userAccessToken;
      String token_type = UserConstants.bearerType;
    
      Future<List<dynamic>> getCategories() async {
        http.Response response =
            await http.get(HimalayanWalkConstant.baseURL + "places", headers: {
          'Accept': 'application/json',
          'Content-type': 'application/json',
          'Authorization': '$token_type' + ' $access_token'
        });
        Map<String, dynamic> decodedCategories = json.decode(response.body);
        return decodedCategories['data'];
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          backgroundColor: Colors.white,
          appBar: new AppBar(
            title: new Text("Destination Page"),
          ),
          body: ListView(
            scrollDirection: Axis.vertical,
            children: <Widget>[
              Container(
                padding: EdgeInsets.all(16.0),
                child: Row(
                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
                  children: <Widget>[
                    Column(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: <Widget>[
                        Text(UserConstants.userDisplayName,
                            style: TextStyle(
                                fontSize: 18.0, fontWeight: FontWeight.bold)),
                        Text(
                          "Where do you want to go?",
                          style: TextStyle(color: Colors.grey.shade700),
                        )
                      ],
                    ),
                    CircleAvatar(
                      backgroundImage:
                          new NetworkImage(UserConstants.userProfileUrl),
                      radius: 40,
                    )
                  ],
                ),
              ),
              Container(
                padding: EdgeInsets.only(left: 16.0, right: 16.0, bottom: 8.0),
                child: Material(
                  elevation: 5.0,
                  child: TextField(
                    decoration: InputDecoration(
                        hintText: "Find destination",
                        prefixIcon: Icon(Icons.location_on),
                        border: InputBorder.none),
                  ),
                ),
              ),
              new Container(
                padding: EdgeInsets.fromLTRB(8.0, 8.0, 8.0, 8.0),
                child: Material(
                  child: buildListItems(getCategories()),
                ),
              ),
            ],
          ),
        );
      }
    }
    
    Card _buildFeaturedItem({String image, String title, String subtitle}) {
      return Card(
        child: Material(
          elevation: 5.0,
          shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(5.0)),
          child: Stack(
            children: <Widget>[
              ClipRRect(
                  borderRadius: BorderRadius.circular(5.0),
                  child: new Image(
                    image: new CachedNetworkImageProvider(image),
                    fit: BoxFit.cover,
                  )),
              Positioned(
                right: 10.0,
                top: 10.0,
                child: IconButton(
                  onPressed: () {},
                  icon: Icon(Icons.favorite_border, color: Colors.white),
                ),
              ),
              Positioned(
                bottom: 20.0,
                child: Container(
                  padding: EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0),
                  color: Colors.black.withOpacity(0.7),
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    mainAxisAlignment: MainAxisAlignment.end,
                    children: <Widget>[
                      Text(title,
                          style: TextStyle(
                              color: Colors.white,
                              fontSize: 20.0,
                              fontWeight: FontWeight.bold)),
                      Text(subtitle, style: TextStyle(color: Colors.white))
                    ],
                  ),
                ),
              ),
            ],
          ),
        ),
      );
    }
    
    SizedBox buildListItems(Future<List> categories) {
      final ScrollController controller = new ScrollController();
      return SizedBox(
        child: FutureBuilder(
          future: categories,
          builder: (BuildContext context, AsyncSnapshot<List<dynamic>> snapshot) {
            if (snapshot.connectionState == ConnectionState.done) {
              return ListView.builder(
                shrinkWrap: true,
                controller: controller,
                scrollDirection: Axis.vertical,
                itemBuilder: (context, index) {
                  Map<String, String> data =
                      snapshot.data[index].cast<String, String>();
                  return new Container(
                    child: InkWell(
                      onTap: () => _openDestinationPage(context),
                      child: _buildFeaturedItem(
                        image: data['featured_image_url'],
                        title: data['title'],
                        subtitle: data['slug'],
                      ),
                    ),
                  );
                },
                itemCount: snapshot.data.length,
              );
            } else {
              return Center(
                child: CircularProgressIndicator(),
              );
            }
          },
        ),
      );
    }
    
    _openDestinationPage(BuildContext context) {
      Navigator.push(context, MaterialPageRoute(builder: (_) => DestinationPage()));
    }
    

    【讨论】:

      【解决方案2】:

      因为您在列表视图中有一个列表视图,所以滚动会很不稳定。您可以将内部项目的 shrinkWrap 设置为 true,这将使其根据所有项目确定其高度,但这可能会导致包含大量项目的列表中的性能问题。我建议使用 CustomScrollView 作为整体滚动窗格,将 RenderSliv​​erToBoxAdapter 用于顶部,然后将 SliverList 用于图片。不过,我不确定您是否可以使用 sliverlist 中的 futurebuilder 来做到这一点 - 您可能必须将其移到 CustomScrollView 之外。

      【讨论】:

        猜你喜欢
        • 2017-11-17
        • 2019-08-08
        • 1970-01-01
        • 2018-12-06
        • 1970-01-01
        • 2022-09-24
        • 2023-02-25
        • 2020-12-16
        • 2021-12-31
        相关资源
        最近更新 更多