flutter - 在 SliverAppBar 内实现 GoogleMap

标签 flutter dart

我正在尝试在FlexibleSpaceBar内部使用谷歌地图制作固定的ScrollView。

有带有 SliverAppBar 和正文内容的 NestedScrollView。 SliverAppBar 内部是谷歌地图小部件,应用栏占据了设备的整个 View 。还有 FloatingActionButton,按下时应滚动到 View 底部,显示 NestedScrollView 的正文内容,并将 map 移动到应用栏,反之亦然。它在技术上是有效的,如果有人想看看它是什么样子的话,有一个代码:

@override
State<MapPage> createState() => MapPageState();
}

const LatLng _coordinates = LatLng(37.43296265331129, -122.08832357078792);

class MapPageState extends State<MapPage> with SingleTickerProviderStateMixin {
ScrollController _scrollController;
Completer<GoogleMapController> _controller = Completer();
double _scrollExtent;
bool _buttonState;

static final CameraPosition _kGooglePlex = CameraPosition(
  target: _coordinates,
  zoom: 14.4746,
);

@override
void initState() {
  _buttonState = true;
  _scrollController = ScrollController(initialScrollOffset: 0.0);
  super.initState();
}

@override
void dispose() {
  _scrollController.dispose();
  super.dispose();
}

@override
Widget build(BuildContext context) {
  _scrollExtent = MediaQuery.of(context).size.height;
  return Scaffold(
    floatingActionButton: FloatingActionButton(
      child: Icon(Icons.keyboard_arrow_down),
      backgroundColor: Colors.white,
      foregroundColor: Colors.red,
      onPressed: (){
        if(_buttonState){
          _scrollController.animateTo(_scrollExtent, duration: Duration(seconds: 1), curve: Curves.fastOutSlowIn);
          _buttonState = false;
        }
        else{
          _scrollController.animateTo(-_scrollExtent, duration: Duration(seconds: 1), curve: Curves.fastOutSlowIn);
          _buttonState = true;
        }
      },
    ),
    body: NestedScrollView(
        controller: _scrollController,
        headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
          return <Widget>[
            SliverAppBar(
              expandedHeight: MediaQuery.of(context).size.height,
              floating: false,
              pinned: true,
              flexibleSpace: FlexibleSpaceBar(
                title: Text("Title",
                    style: TextStyle(
                      color: Colors.white,
                      fontSize: 16.0,
                    )),
                background: GoogleMap(
                  mapType: MapType.normal,
                  initialCameraPosition: _kGooglePlex,
                  markers: _createMarker(),
                  onMapCreated: (GoogleMapController controller) {
                    _controller.complete(controller);
                  },
                ),
              ),
            ),
          ];
        },
        body: Container(
          padding: EdgeInsets.all(24.0),
          child: Text(
            'Content'),
        ),
      ),
  );
}
Set<Marker> _createMarker() {
  return <Marker>[
    Marker(
      markerId: MarkerId("marker_1"),
      position: _coordinates,
      infoWindow: InfoWindow(title: 'Marker"'),
    ),
  ].toSet();
}

}

重要的部分在这里:

NestedScrollView(
      controller: _scrollController,
      headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
        return <Widget>[
          SliverAppBar(
            expandedHeight: MediaQuery.of(context).size.height,
            floating: false,
            pinned: true,
            flexibleSpace: FlexibleSpaceBar(
              title: Text("Title",
                  style: TextStyle(
                    color: Colors.white,
                    fontSize: 16.0,
                  )),
              background: GoogleMap(
                mapType: MapType.normal,
                initialCameraPosition: _kGooglePlex,
                markers: _createMarker(),
                onMapCreated: (GoogleMapController controller) {
                  _controller.complete(controller);
                },
              ),
            ),
          ),
        ];
      },

有3个问题:

  1. I dont understand how to prevent user from scrolling with gestures.

我希望它仅由滚动 Controller 控制。我尝试将 NestedScrollView 的物理设置为 NeverScrollableScrollPhysics(),但没有任何效果。

  1. The map gesture detection inside scrollable widget behaving weirdly

您无法正确拖动它,并且它似乎只能通过点击来使用。例如,在 ListView 中,它在 NeverScrollable 物理特性下表现良好。

  1. Every time it's getting rebuilt in app bar it seems to cause some sort of memory leak and I'm getting next warning.
E/flutter (10644): #0      _AsyncCompleter.complete (dart:async/future_impl.dart:39:31)
E/flutter (10644): #1      MapPageState.build.<anonymous closure>.<anonymous closure> (package:flutter_app/map_page2.dart:83:35)
E/flutter (10644): #2      _GoogleMapState.onPlatformViewCreated (package:google_maps_flutter/src/google_map.dart:259:14)
E/flutter (10644): <asynchronous suspension>
E/flutter (10644): #3      AndroidViewController._create (package:flutter/src/services/platform_views.dart:599:15)  
...

如果有人可以帮助解决其中任何一个问题,或者知道此类实现的示例,我将不胜感激。

最佳答案

我遇到了同样的问题,并找到了解决方案here .

                background: GoogleMap(
                  gestureRecognizers: [
                    Factory<OneSequenceGestureRecognizer>(
                      () => EagerGestureRecognizer(),
                    ),
                  ].toSet(),

关于flutter - 在 SliverAppBar 内实现 GoogleMap,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56536065/

相关文章:

flutter - 将 flutter 测试文件定位到源

flutter Riverpod : FutureProvider family never gets resolved

flutter - 如何在不使用镜像的情况下获取 Dart 类的所有静态 const 字段?

dart - 如何在 StatefulWidget 上使用构建器函数

flutter - 如何在调用屏幕时显示 map

listview - 在Flutter中清除ListView

flutter - 无法构建 flutter 工具

dart - 如何检查 Flutter 应用程序是否在前台?

flutter - 使用 Flutter new integration_test 进行示例集成测试?

flutter - 在小部件之间画一条线并使线可点击