728x90
안녕하세요 불망입니다!
피플에서 메인 기능으로 지도 커뮤니티를 기획하게 되어서 지도 개발을 시작 하였습니다.
간단한 아키텍처 구성을 해봤습니다.
- 모든 헌혈의 집 위치를 가져와서 마커 표시
- 마커 눌렀을 때
- 바텀 시트 조금 보여주기
- 바텀 시트 눌렀을 때
- 센터 상세페이지로 이동
- 지도 탭을 눌렀을 때 현재 위치 가져와서 보여주기
- 검색창은 기존 검색창 사용
- 검색 했을 때 검색 결과를 누르면 좌표이동해서 보여주기
- 검색 결과 필터링(지도 완성후 기능추가 & 백엔드)
- 헌혈의 집 버튼 : 헌혈의 집만 마커 표시
- 헌혈의 카페 버튼 : 헌혈의 카페만 마커 표시
- 가까운 헌혈의 집 보여주기(지도 완성 후 기능 추가)
- 내 위치표시 : 내 현재 위치 표시
- 아이콘 커스텀마이징
위 기능들을 하나씩 개발을 하려고 합니다.
지도 환경 설정
google_maps_flutter 패키지를 프로젝트에 추가합니다. 이 패키지는 Google Maps를 플러터에서 사용할 수 있도록 지원합니다
dependencies:
google_maps_flutter: ^2.1.0
geolocator: ^8.0.3 // 유저 위치 가져오기
Android : android/app/src/main/AndroidManifest.xml에 밑에 코드 추가
<manifest ...
<application ...
<meta-data android:name="com.google.android.geo.API_KEY"
android:value="YOUR KEY HERE"/>
iOS : ios/Runner/AppDelegate.swift에 코드 추가
import UIKit
import Flutter
import GoogleMaps
@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
GMSServices.provideAPIKey("YOUR KEY HERE")
GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}
유저 현재 위치 가져오기(설정)
Android : android/app/src/main/AndroidManifest.xml에 밑에 코드 추가
<manifest ...>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
...
</manifest>
iOS : Runner/Info.plist에 추가
<key>NSLocationWhenInUseUsageDescription</key>
<string>유저 위치를 가져와도 될까요?</string>
메엔 함수에다 사용자의 위치 정보 호출 (예시)
밑 코드에서는 checkPermission() 함수를 사용하여 위치 권한 상태를 확인하고, 권한이 거부된 경우 requestPermission() 함수를 사용하여 사용자에게 권한을 요청합니다.
위 코드에서 사용되는 WidgetsFlutterBinding.ensureInitialized() 함수는 runApp() 함수를 호출하기 전에 **WidgetsBinding**을 초기화하는 데 사용됩니다. 이 함수를 호출하지 않으면 **ServicesBinding**을 사용하는 일부 패키지에서 문제가 발생할 수 있습니다.
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
final status = await Geolocator.checkPermission();
if (status == LocationPermission.denied) {
await Geolocator.requestPermission();
}
runApp(MyApp());
}
앱 설명
- 플러터를 사용하여 안드로이도, 아이폰 둘 다 지도를 가져오고 간단한 지도 기능을 사용합니다.
앱 기능
- 유저 현재 위치 가져오는 버튼
- 좌표값을 가져와서 마커 찍기
- 마커를 누르면 바텀시트 나오게 하기
- 바텀시트 누르면 디테일페이지로 이동
다른 코드 내용
개인적인 코드이며 유저 위치 마커 기본적인 코드 내용입니다.
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:geolocator/geolocator.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
final status = await Geolocator.checkPermission();
if (status == LocationPermission.denied) {
await Geolocator.requestPermission();
}
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return CupertinoApp(
home: map_widget(),
);
}
}
class map_widget extends StatefulWidget {
const map_widget({Key? key,required}) : super(key: key);
@override
State<map_widget> createState() => _map_widgetState();
}
class _map_widgetState extends State<map_widget> {
late GoogleMapController _controller;
bool _myLocationEnabled = false;
@override
void dispose() {
_controller.dispose();
super.dispose();
}
Future<void> _getCurrentLocation() async {
final position = await Geolocator.getCurrentPosition();
final cameraPosition = CameraPosition(
target: LatLng(position.latitude, position.longitude),
zoom: 18,
);
_controller.animateCamera(CameraUpdate.newCameraPosition(cameraPosition));
setState(() {
_myLocationEnabled = true;
});
}
@override
Widget build(BuildContext context) {
List<Map<String, dynamic>> places = [ { 'name': 'Place 1', 'latitude': 37.532600, 'longitude': 127.024612, }, { 'name': 'Place 2', 'latitude': 37.532700, 'longitude': 127.024712, }, { 'name': 'Place 3', 'latitude': 37.532800, 'longitude': 127.024812, }, { 'name': 'Place 4', 'latitude': 37.532900, 'longitude': 127.024912, }, { 'name': 'Place 5', 'latitude': 37.533000, 'longitude': 127.025012, }, { 'name': 'Place 6', 'latitude': 37.533100, 'longitude': 127.025112, },];
return CupertinoPageScaffold(
child: Stack(
children: [
GoogleMap(
initialCameraPosition: CameraPosition(
target: LatLng(37.532600, 127.024612), // 서울 시청 위치
zoom: 18,
),
myLocationEnabled: _myLocationEnabled,
myLocationButtonEnabled: false,
markers: Set<Marker>.of(places.map((place) {
return Marker(
markerId: MarkerId(place['name']),
position: LatLng(place['latitude'], place['longitude']),
infoWindow: InfoWindow(title: place['name']),
onTap: () {
Navigator.push(
context,
CupertinoPageRoute(builder: (context) => MarkerDetailScreen())
);
},
);
})),
onMapCreated: (controller) => _controller = controller,
),
Positioned(
bottom: 16,
right: 16,
child: FloatingActionButton(
onPressed: _getCurrentLocation,
foregroundColor: Colors.black,
backgroundColor: Colors.white,
elevation: 8, // 그림자 크기
child: Icon(Icons.my_location),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10), // 버튼 모서리 둥글기
),
),
),
Positioned(
top: 54,
child: CupertinoButton(
onPressed: () {
Navigator.push(
context,
CupertinoPageRoute(builder: (context) => MarkerDetailScreen())
);
},
child: Container(
width: MediaQuery.of(context).size.width - 21,
height: 44,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Padding(
padding: const EdgeInsets.only(left: 16.0),
child: Text('위치 검색',
style: const TextStyle(
fontSize: 18,
fontWeight: FontWeight.w600,
color: Colors.grey,
),
),
),
const Spacer(),
Padding(
padding: const EdgeInsets.only(right: 13.0),
),
],
),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.all(Radius.circular(8))
),
),
),
),
],
),
);
}
}
class MarkerDetailScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Marker Detail'),
),
body: Center(
child: Text('Marker detail screen'),
),
);
}
}
class marker_widget extends StatelessWidget {
const marker_widget({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return const Placeholder();
}
}
728x90
'Flutter' 카테고리의 다른 글
[Flutter] WhiteScreen 해결(iPhone 무선빌드) & Load Sequence Flutter UI (3) | 2024.11.21 |
---|---|
[피플] 디자인 QA (0) | 2023.02.24 |
[피플] 응원해요 기능 수정 (0) | 2023.02.08 |
[피플] - 이슈 수정 (git, 협업능력) (0) | 2023.02.03 |
[Flutter 문법]StatefulWidget parameter 넘겨주기 (0) | 2023.01.20 |