首页 > 解决方案 > 部分屏幕在 Flutter 中不滚动

问题描述

我正在尝试创建一个屏幕,其中 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()));
   }

仅通过指向红色表面滚动屏幕时,屏幕正在滚动。

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

标签: flutterflutter-layout

解决方案


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

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()));
}

推荐阅读