在 SliverAppBar 内实现 GoogleMap

HPr*_*ure 3 dart flutter

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

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

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

}
Run Code Online (Sandbox Code Playgroud)

重要的部分在这里:

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);
                },
              ),
            ),
          ),
        ];
      },
Run Code Online (Sandbox Code Playgroud)

有3个问题:

  1. 我不明白如何阻止用户用手势滚动。

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

  1. 可滚动小部件内的地图手势检测行为异常

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

  1. 每次在应用程序栏中重建它时,它似乎都会导致某种内存泄漏,我会收到下一个警告。
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)  
...
Run Code Online (Sandbox Code Playgroud)

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

mot*_*tia 7

我遇到了同样的问题,并在这里找到了解决方案。

                background: GoogleMap(
                  gestureRecognizers: [
                    Factory<OneSequenceGestureRecognizer>(
                      () => EagerGestureRecognizer(),
                    ),
                  ].toSet(),
Run Code Online (Sandbox Code Playgroud)