반응형

안녕하세요.

 

Flutter Bug에 대한 해결책을 정리해볼까 합니다.

https://spikez.tistory.com/456

 

[Flutter] flutter 3.7 google map 버그 (frame이 남아있는 문제)

(2023년1월28일) 어제 시간이 좀 나서 flutter 3.2 버전으로 개발 진행해오던 프로젝트를 3.7로 업그레이드 해봤습니다. 아.. 뭔가 달라진게 있는지 custom 으로 작성한 theme 쪽에서 deprecated 된 것이 보이

spikez.tistory.com

 

 

일단 문제는 위 링크에 있는 내용인데요.

 

화면전환시에 한프래임이 남아서 화면전환을 어색하게 만듭니다.

google map을 dispose 시키기 위해서 여러가지 방법을 사용해봤는데, 방법을 찾지 못하다가, 문제 올린 링크의 내용중에 개발자 한분(AdrienGannerie)이 임시 해결책을 제시해주셨습니다.

 

그래서 그 코드로 테스트 해보고 문제가 사라진것을 확인했네요 ^^

 

코드는 다음과 같습니다.

import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';

class NewMap extends StatefulWidget {
  const NewMap({super.key});

  @override
  State<NewMap> createState() => _NewMapState();
}

class _NewMapState extends State<NewMap> {


  late Widget googleMap;
  bool showMap = true;

  late GoogleMapController mapController;

  @override
  void initState() {
    super.initState();
  }


  @override
  void dispose(){
    print("_NewMapState:dispose()");

    mapController.dispose();  // Map 을 Dispose 시키는 부분
    super.dispose();
  }



  @override
  Widget build(BuildContext context) {

    googleMap = GoogleMap(
      mapType: MapType.normal,
      mapToolbarEnabled: false,
      zoomControlsEnabled: false,
      myLocationEnabled: true,
      trafficEnabled: false,
      onMapCreated:  (GoogleMapController controller){
        mapController = controller;
      }, initialCameraPosition: const CameraPosition(target: LatLng(0,0)),

    );
    return PopScope(
        onPopInvoked: (bool didPop) {   //<-- 이부분이 핵심인데, pop 될때 showMap을 false로 변경하고,
            setState(() {  // 상태가 변경되어 google map이 사라지고 빈 container만 남기는것입니다.
            showMap = false; 
          });
        },
        child:showMap?googleMap:Container()
    );   
//Old version : WillPopScope 이 deprecated 되었습니다. ㅠ_ㅠ
//    return WillPopScope(
//        onWillPop: () {   //<-- 이부분이 핵심인데, pop 될때 showMap을 false로 변경하고,
//            setState(() {  // 상태가 변경되어 google map이 사라지고 빈 container만 남기는것입니다.
//            showMap = false; 
//          });
//          return Future.value(true);
//        },
//        child:showMap?googleMap:Container()
//    );
  }
}

 

 

 

위의 WillPopScope 부분이 핵심이 되는데요.

WillPopScope을 걸어서 back navigation 될때 map widget을 build 에서 제거 하는 형태로 문제를 해결한 것입니다.

=> WillPopScope 이 deprecated 됬고 PopScope 을 사용해야 해서 위에 코드에도 반영했습니다.

 

물론 위 코드를 보셔서 알겠지만, 만약 GoogleMap widget이 정상적으로 동작했다면 필요없는 코드입니다.

하지만 당장 앱의 퀄리티를 위해서 ㅠ_ㅠ 개발자가 회피코드(Workaround)를 작성할 수 밖에 없겠네요....

 

저는 이렇게 해서 flutter 3.2를 3.7로 업그레이드 할 수 있게 되었습니다. 

 

 

!!! 해피코딩!! 

 

반응형

Flutter 에서 구글맵을 사용할때 2가지 패키지를 추가해서 사용합니다.

 

google_maps_flutter: ^2.2.3
geocoding: ^2.0.5

 

google map 사용방법은 google cloud service에서 api key를 발급 받고 사용해야합니다.

클라우드 설정이 끝나고 Goecoding을 사용하는 방법은 매우 간단합니다.

 

Geo Coding

geocoding, GeoCode, geocoder등의 용어는  주소를 위도, 경도로 변환하거나 위도,경도로 주소를 넘겨받는 기능을 의미하는 표현으로 많이 사용됩니다.

 

 

주소로  위도, 경도를 받아올때

 

List<Location> locations = await locationFromAddress(address);
Location location = locations[0];
print("locations : ${locations}");

 

위도 경도로, 주소 목록을 받아올때

_placemarks = await placemarkFromCoordinates(location.latitude, location.longitude);
print("placemarks : ${_placemarks}");

 

google geocoding 으로 위도 경도를 입력해서 주소 결과물의 형태는 다음과 같습니다.

2023-05-11 17:02:01.282 1519-1584/com.example I/flutter: placemarks : [
Name: 131, 
          Street: 대한민국 경기도 수원시 팔달구 팔달산로 131, 
          ISO Country Code: KR, 
          Country: 대한민국, 
          Postal code: 16440, 
          Administrative area: 경기도, 
          Subadministrative area: ,
          Locality: 수원시,
          Sublocality: 팔달구,
          Thoroughfare: ,
          Subthoroughfare: 131,       
Name: 16440, 
          Street: 대한민국 경기도 수원시 팔달구, 
          ISO Country Code: KR, 
          Country: 대한민국, 
          Postal code: 16440, 
          Administrative area: 경기도, 
          Subadministrative area: ,
          Locality: 수원시,
          Sublocality: 팔달구,
          Thoroughfare: ,
          Subthoroughfare: ,       
Name: 화서1동, 
          Street: 대한민국 경기도 수원시 팔달구 화서1동, 
          ISO Country Code: KR, 
          Country: 대한민국, 
          Postal code: , 
          Administrative area: 경기도, 
          Subadministrative area: ,
          Locality: 수원시,
          Sublocality: 팔달구,
          :

 

반응형

 

어플리케이션 개발시에 google map을 사용해야 하는 경우 종종 있는데요.

google map 사용시 한가지 불편한 부분에 대한 팁입니다.

 

pubspec.yaml

google_maps_flutter: ^2.2.3

 

GoogleMap(
  mapType: MapType.normal,
  mapToolbarEnabled: false,
  zoomControlsEnabled: false,
  myLocationEnabled: true,
  trafficEnabled: false,
  gestureRecognizers:{
    Factory<OneSequenceGestureRecognizer>(() => EagerGestureRecognizer())
  },
  markers: {Marker(markerId: MarkerId("위치"),position: controller.location.toLatLng())},
  onMapCreated:  (GoogleMapController mapController){
    controller.mapController.complete(mapController);
    },

  onTap: (loc) async {
    controller.location = MapLocation.fromLatLng(loc);
    dprint("loc: (${controller.latitude}, ${controller.longitude})");
    final mc = await controller.mapController.future;
    mc.animateCamera(CameraUpdate.newCameraPosition(CameraPosition(target: loc, zoom: await mc.getZoomLevel())));
    setState(() {});
    WMapUtils.getAddress(loc.latitude, loc.longitude).then((value){
      setState(() {
        controller.addressEditController.text = value;
      });
    });
  },
  initialCameraPosition: CameraPosition(target: controller.location.toLatLng(),zoom: 15),

)),

 

googlemap이 SingleChildScrollView 의 child로 들어갈 경우, pinch zoom, panning 등의 gesture 동작이 Scroller에 우선되어서 googlemap에 전달이 안되는 불상사가 있습니다.

그래서 아래와 같이 GoogleMap에 gestureRecognizers 에 설정을 EagerGestureRecognizer 로 세팅해서 처리하면 google map이 우선되어 동작하게 됩니다.

 

gestureRecognizers:{
  Factory<OneSequenceGestureRecognizer>(() => EagerGestureRecognizer())
},

 

 

해피 코딩!

+ Recent posts