map type is added to the maps already present

maptype
tahaalam 17 hours ago
parent 973fdc3692
commit c716490b0e

@ -4,60 +4,263 @@ import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/core/app_export.dart';
import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:huawei_map/huawei_map.dart' ;
import 'package:huawei_map/huawei_map.dart';
class HMSMap extends StatefulWidget{
class HMSMap extends StatefulWidget {
final CameraPosition currentLocation;
final Function(CameraPosition) onCameraMoved;
final VoidCallback onCameraIdle;
final MapType mapType;
final MapType initialMapType;
final bool compassEnabled;
final bool myLocationEnabled;
final bool showCenterMarker;
final Completer<HuaweiMapController>? inputController;
HMSMap({super.key, required this.currentLocation ,required this.onCameraMoved,required this.onCameraIdle,
this.mapType = MapType.normal,this.compassEnabled = false,this.showCenterMarker = false,
this.myLocationEnabled = true, this.inputController});
const HMSMap({
super.key,
required this.currentLocation,
required this.onCameraMoved,
required this.onCameraIdle,
this.initialMapType = MapType.normal,
this.compassEnabled = false,
this.showCenterMarker = false,
this.myLocationEnabled = true,
this.inputController,
});
@override
State<HMSMap> createState() => _HMSMapState();
}
class _HMSMapState extends State<HMSMap> {
Completer<HuaweiMapController>? controller;
Completer<HuaweiMapController>? controller;
late MapType _selectedMapType;
bool _showMapTypeSelector = false;
static const List<_MapTypeOption> _mapTypeOptions = [
_MapTypeOption(type: MapType.normal, label: 'Default', icon: Icons.map_outlined),
_MapTypeOption(type: MapType.terrain, label: 'Terrain', icon: Icons.terrain_outlined),
];
@override
void initState() {
super.initState();
HuaweiMapInitializer.initializeMap();
controller = widget.inputController ?? Completer<HuaweiMapController>();
super.initState();
_selectedMapType = widget.initialMapType;
}
void _onMapTypeSelected(MapType type) {
setState(() {
_selectedMapType = type;
_showMapTypeSelector = false;
});
}
// @override
void _toggleSelector() =>
setState(() => _showMapTypeSelector = !_showMapTypeSelector);
@override
Widget build(BuildContext context) =>
Stack(
children: [
HuaweiMap(
mapType: widget.mapType,
zoomControlsEnabled: false,
myLocationEnabled: widget.myLocationEnabled,
myLocationButtonEnabled: false,
compassEnabled: widget.compassEnabled,
onCameraIdle:()=> widget.onCameraIdle(),
initialCameraPosition: widget.currentLocation,
onCameraMove: (value) => widget.onCameraMoved(value),
onMapCreated: (HuaweiMapController controller) {
this.controller?.complete(controller);
},
Widget build(BuildContext context) {
return Stack(
children: [
// Huawei Map
HuaweiMap(
mapType: _selectedMapType,
zoomControlsEnabled: false,
myLocationEnabled: widget.myLocationEnabled,
myLocationButtonEnabled: false,
compassEnabled: widget.compassEnabled,
onCameraIdle: widget.onCameraIdle,
initialCameraPosition: widget.currentLocation,
onCameraMove: widget.onCameraMoved,
onMapCreated: (HuaweiMapController ctrl) {
controller?.complete(ctrl);
},
),
// Centre pin marker
if (widget.showCenterMarker)
Align(
alignment: Alignment.center,
child: Icon(
Icons.location_pin,
size: 36.h,
color: AppColors.primaryRedColor,
).paddingOnly(bottom: 24.h),
),
// Map-type toggle + panel
Positioned(
top: 16.h,
right: 16.w,
child: Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
_MapTypeToggleButton(
isActive: _showMapTypeSelector,
onTap: _toggleSelector,
),
Visibility(
visible: widget.showCenterMarker,
child: Align(
alignment: Alignment.center,
child: Icon(Icons.location_pin, size: 36.h, color: AppColors.primaryRedColor).paddingOnly(bottom: 24.h),
),
)
AnimatedSwitcher(
duration: const Duration(milliseconds: 220),
transitionBuilder: (child, animation) => FadeTransition(
opacity: animation,
child: SizeTransition(
sizeFactor: animation,
axisAlignment: -1,
child: child,
),
),
child: _showMapTypeSelector
? _MapTypeSelectorPanel(
options: _mapTypeOptions,
selected: _selectedMapType,
onSelected: _onMapTypeSelected,
)
: const SizedBox.shrink(),
),
],
),
),
],
);
}
}
// Toggle button
class _MapTypeToggleButton extends StatelessWidget {
final bool isActive;
final VoidCallback onTap;
const _MapTypeToggleButton({required this.isActive, required this.onTap});
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: onTap,
child: AnimatedContainer(
duration: const Duration(milliseconds: 200),
width: 42.w,
height: 42.h,
decoration: BoxDecoration(
color: isActive ? AppColors.primaryRedColor : Colors.white,
borderRadius: BorderRadius.circular(8.r),
boxShadow: const [
BoxShadow(color: Colors.black26, blurRadius: 6, offset: Offset(0, 2)),
],
),
child: Icon(
Icons.layers,
size: 22.h,
color: isActive ? Colors.white : Colors.black87,
),
),
);
}
}
// Selector panel
class _MapTypeSelectorPanel extends StatelessWidget {
final List<_MapTypeOption> options;
final MapType selected;
final ValueChanged<MapType> onSelected;
const _MapTypeSelectorPanel({
required this.options,
required this.selected,
required this.onSelected,
});
@override
Widget build(BuildContext context) {
return Container(
key: const ValueKey('map_type_panel'),
margin: EdgeInsets.only(top: 8.h),
padding: EdgeInsets.symmetric(vertical: 8.h, horizontal: 6.w),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(12.r),
boxShadow: const [
BoxShadow(color: Colors.black26, blurRadius: 8, offset: Offset(0, 3)),
],
);
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: options
.map((opt) => _MapTypeItem(
option: opt,
isSelected: selected == opt.type,
onTap: () => onSelected(opt.type),
))
.toList(),
),
);
}
}
// Single row item
class _MapTypeItem extends StatelessWidget {
final _MapTypeOption option;
final bool isSelected;
final VoidCallback onTap;
const _MapTypeItem({
required this.option,
required this.isSelected,
required this.onTap,
});
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: onTap,
child: AnimatedContainer(
duration: const Duration(milliseconds: 180),
margin: EdgeInsets.symmetric(vertical: 3.h),
padding: EdgeInsets.symmetric(horizontal: 10.w, vertical: 8.h),
decoration: BoxDecoration(
color: isSelected
? AppColors.primaryRedColor.withOpacity(0.1)
: Colors.transparent,
borderRadius: BorderRadius.circular(8.r),
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(
option.icon,
size: 18.h,
color: isSelected ? AppColors.primaryRedColor : Colors.black54,
),
SizedBox(width: 8.w),
Text(
option.label,
style: TextStyle(
fontSize: 14.f,
fontWeight: isSelected ? FontWeight.w600 : FontWeight.w400,
color: isSelected ? AppColors.primaryRedColor : Colors.black87,
),
),
],
),
),
);
}
}
// Data class
class _MapTypeOption {
final MapType type;
final String label;
final IconData icon;
const _MapTypeOption({
required this.type,
required this.label,
required this.icon,
});
}

@ -1,3 +1,58 @@
// import 'dart:async';
//
// import 'package:flutter/material.dart';
// import 'package:google_maps_flutter/google_maps_flutter.dart';
// import 'package:hmg_patient_app_new/core/utils/size_utils.dart';
// import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
// import 'package:hmg_patient_app_new/theme/colors.dart';
//
// class GMSMap extends StatelessWidget{
// Completer<GoogleMapController>? controller;
// final CameraPosition currentLocation;
// final Function(CameraPosition) onCameraMoved;
// final VoidCallback onCameraIdle;
// final MapType mapType;
// final bool compassEnabled;
// final bool myLocationEnabled;
// final bool showCenterMarker;
//
//
// GMSMap({super.key, required this.currentLocation ,required this.onCameraMoved,required this.onCameraIdle,
// this.mapType = MapType.normal,this.compassEnabled = false,this.showCenterMarker = false,
// this.myLocationEnabled = true,Completer<GoogleMapController>? inputController}){
// controller = inputController ?? Completer<GoogleMapController>();
// }
//
// @override
// Widget build(BuildContext context) {
// return Stack(
// children: [
// GoogleMap(
// mapType: mapType,
// zoomControlsEnabled: true,
// myLocationEnabled: myLocationEnabled,
// myLocationButtonEnabled: false,
// compassEnabled: compassEnabled,
// initialCameraPosition: currentLocation,
// onCameraMove: (value) => onCameraMoved(value),
// onCameraIdle: ()=>onCameraIdle(),
// // padding: EdgeInsets.only(bottom: 300.h),
// onMapCreated: (GoogleMapController controller) {
// this.controller?.complete(controller);
// },
// ),
// Visibility(
// visible: showCenterMarker,
// child: Align(
// alignment: Alignment.center,
// child: Icon(Icons.location_pin, size: 36.h, color: AppColors.primaryRedColor).paddingOnly(bottom: 24.h),
// ),
// )
// ],
// );
// }
// }
import 'dart:async';
import 'package:flutter/material.dart';
@ -6,49 +61,298 @@ import 'package:hmg_patient_app_new/core/utils/size_utils.dart';
import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
import 'package:hmg_patient_app_new/theme/colors.dart';
class GMSMap extends StatelessWidget{
Completer<GoogleMapController>? controller;
class GMSMap extends StatefulWidget {
final CameraPosition currentLocation;
final Function(CameraPosition) onCameraMoved;
final VoidCallback onCameraIdle;
final MapType mapType;
final MapType initialMapType;
final bool compassEnabled;
final bool myLocationEnabled;
final bool showCenterMarker;
final Completer<GoogleMapController>? inputController;
const GMSMap({
super.key,
required this.currentLocation,
required this.onCameraMoved,
required this.onCameraIdle,
this.initialMapType = MapType.normal,
this.compassEnabled = false,
this.showCenterMarker = false,
this.myLocationEnabled = true,
this.inputController,
});
@override
State<GMSMap> createState() => _GMSMapState();
}
class _GMSMapState extends State<GMSMap> {
late Completer<GoogleMapController> _controller;
late MapType _selectedMapType;
bool _showMapTypeSelector = false;
/// All supported map types with display labels and icons
static const List<_MapTypeOption> _mapTypeOptions = [
_MapTypeOption(
type: MapType.normal,
label: 'Default',
icon: Icons.map_outlined,
),
_MapTypeOption(
type: MapType.satellite,
label: 'Satellite',
icon: Icons.satellite_alt_outlined,
),
_MapTypeOption(
type: MapType.terrain,
label: 'Terrain',
icon: Icons.terrain_outlined,
),
_MapTypeOption(
type: MapType.hybrid,
label: 'Hybrid',
icon: Icons.layers_outlined,
),
];
@override
void initState() {
super.initState();
_controller = widget.inputController ?? Completer<GoogleMapController>();
_selectedMapType = widget.initialMapType;
}
void _onMapTypeSelected(MapType type) {
setState(() {
_selectedMapType = type;
_showMapTypeSelector = false;
});
}
GMSMap({super.key, required this.currentLocation ,required this.onCameraMoved,required this.onCameraIdle,
this.mapType = MapType.normal,this.compassEnabled = false,this.showCenterMarker = false,
this.myLocationEnabled = true,Completer<GoogleMapController>? inputController}){
controller = inputController ?? Completer<GoogleMapController>();
void _toggleMapTypeSelector() {
setState(() => _showMapTypeSelector = !_showMapTypeSelector);
}
@override
Widget build(BuildContext context) {
return Stack(
children: [
GoogleMap(
mapType: mapType,
return Stack(
children: [
// Google Map
GoogleMap(
mapType: _selectedMapType,
zoomControlsEnabled: true,
myLocationEnabled: myLocationEnabled,
myLocationEnabled: widget.myLocationEnabled,
myLocationButtonEnabled: false,
compassEnabled: compassEnabled,
initialCameraPosition: currentLocation,
onCameraMove: (value) => onCameraMoved(value),
onCameraIdle: ()=>onCameraIdle(),
// padding: EdgeInsets.only(bottom: 300.h),
compassEnabled: widget.compassEnabled,
initialCameraPosition: widget.currentLocation,
onCameraMove: widget.onCameraMoved,
onCameraIdle: widget.onCameraIdle,
onMapCreated: (GoogleMapController controller) {
this.controller?.complete(controller);
_controller.complete(controller);
},
),
Visibility(
visible: showCenterMarker,
child: Align(
alignment: Alignment.center,
child: Icon(Icons.location_pin, size: 36.h, color: AppColors.primaryRedColor).paddingOnly(bottom: 24.h),
),
// Centre pin marker
if (widget.showCenterMarker)
Align(
alignment: Alignment.center,
child: Icon(
Icons.location_pin,
size: 36.h,
color: AppColors.primaryRedColor,
).paddingOnly(bottom: 24.h),
),
)
// Map-type toggle button
Positioned(
top: 48.h,
left: 16.w,
child: Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
// Toggle button
_MapTypeToggleButton(
isActive: _showMapTypeSelector,
onTap: _toggleMapTypeSelector,
),
// Expandable selector panel
AnimatedSwitcher(
duration: const Duration(milliseconds: 220),
transitionBuilder: (child, animation) => FadeTransition(
opacity: animation,
child: SizeTransition(
sizeFactor: animation,
axisAlignment: -1,
child: child,
),
),
child: _showMapTypeSelector
? _MapTypeSelectorPanel(
options: _mapTypeOptions,
selected: _selectedMapType,
onSelected: _onMapTypeSelected,
)
: const SizedBox.shrink(),
),
],
),
),
],
);
}
}
// Toggle button
class _MapTypeToggleButton extends StatelessWidget {
final bool isActive;
final VoidCallback onTap;
const _MapTypeToggleButton({
required this.isActive,
required this.onTap,
});
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: onTap,
child: AnimatedContainer(
duration: const Duration(milliseconds: 200),
width: 42.w,
height: 42.h,
decoration: BoxDecoration(
color: isActive ? AppColors.primaryRedColor : Colors.white,
borderRadius: BorderRadius.circular(8.r),
boxShadow: const [
BoxShadow(
color: Colors.black26,
blurRadius: 6,
offset: Offset(0, 2),
),
],
),
child: Icon(
Icons.layers,
size: 22.h,
color: isActive ? Colors.white : Colors.black87,
),
),
);
}
}
// Selector panel
class _MapTypeSelectorPanel extends StatelessWidget {
final List<_MapTypeOption> options;
final MapType selected;
final ValueChanged<MapType> onSelected;
const _MapTypeSelectorPanel({
required this.options,
required this.selected,
required this.onSelected,
});
@override
Widget build(BuildContext context) {
return Container(
key: const ValueKey('map_type_panel'),
margin: EdgeInsets.only(top: 8.h),
padding: EdgeInsets.symmetric(vertical: 8.h, horizontal: 6.w),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(12.r),
boxShadow: const [
BoxShadow(
color: Colors.black26,
blurRadius: 8,
offset: Offset(0, 3),
),
],
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: options
.map(
(opt) => _MapTypeItem(
option: opt,
isSelected: selected == opt.type,
onTap: () => onSelected(opt.type),
),
)
.toList(),
),
);
}
}
// Single row item
class _MapTypeItem extends StatelessWidget {
final _MapTypeOption option;
final bool isSelected;
final VoidCallback onTap;
const _MapTypeItem({
required this.option,
required this.isSelected,
required this.onTap,
});
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: onTap,
child: AnimatedContainer(
duration: const Duration(milliseconds: 180),
margin: EdgeInsets.symmetric(vertical: 3.h),
padding: EdgeInsets.symmetric(horizontal: 10.w, vertical: 8.h),
decoration: BoxDecoration(
color: isSelected
? AppColors.primaryRedColor.withOpacity(0.1)
: Colors.transparent,
borderRadius: BorderRadius.circular(8.r),
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(
option.icon,
size: 18.h,
color: isSelected ? AppColors.primaryRedColor : Colors.black54,
),
SizedBox(width: 8.w),
Text(
option.label,
style: TextStyle(
fontSize: 13.f,
fontWeight:
isSelected ? FontWeight.w600 : FontWeight.w400,
color:
isSelected ? AppColors.primaryRedColor : Colors.black87,
),
),
],
),
),
);
}
}
// Data class
class _MapTypeOption {
final MapType type;
final String label;
final IconData icon;
const _MapTypeOption({
required this.type,
required this.label,
required this.icon,
});
}
Loading…
Cancel
Save