[英]How to take screenshot of Google Map in flutter
我正在使用截圖插件在 flutter 中截圖,但問題是當我截圖時,顯示空白屏幕,之后我什么都沒有。每次都會發生這種情況。我正在使用下面的偽執行此任務。
void main() async {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> with WidgetsBindingObserver {
Completer<GoogleMapController> _controller = Completer();
LocationData locationdata;
ScreenshotController screenshotController = ScreenshotController();
var location;
var lat = 0.0;
var lng = 0.0;
CameraController controller;
final Set<Marker> _markers = {};
StreamSubscription<LocationData> locationSubcription;
LatLng _center;
File _imageFile;
static GlobalKey screen = new GlobalKey();
String imagePath;
@override
void initState() {
// TODO: implement initState
super.initState();
// Fetch the available cameras before initializing the app.
WidgetsBinding.instance.addObserver(this);
// _cameraTogglesRowWidget();
onNewCameraSelected(null);
location = new Location();
_getLocation();
locationSubcription = location.onLocationChanged().listen((location) {
setState(() {
locationdata = location;
});
});
}
@override
void dispose() {
WidgetsBinding.instance.removeObserver(this);
super.dispose();
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Maps Sample App'),
backgroundColor: Colors.green[700],
),
body: Container(
margin: EdgeInsets.all(5),
child: Column(children: <Widget>[
Screenshot(
controller: screenshotController,
// RepaintBoundary(
// key: screen,
child:
Row(
children: <Widget>[
Expanded(
child: Container(
width: 200,
height: 200,
child: GoogleMap(
onMapCreated: _onMapCreated,
initialCameraPosition: CameraPosition(
target: _center,
zoom: 15.0,
),
markers: _markers),decoration: BoxDecoration(
color: Colors.black,
border: Border.all(
color: controller != null &&
controller.value.isRecordingVideo
? Colors.redAccent
: Colors.grey,
width: 3.0,
),
)
),),
Expanded(
child: Container(
width: 200,
height: 200,
child: Padding(
padding: const EdgeInsets.all(1.0),
child: Center(
child: _cameraPreviewWidget(),
),
),
decoration: BoxDecoration(
color: Colors.black,
border: Border.all(
color: controller != null &&
controller.value.isRecordingVideo
? Colors.redAccent
: Colors.grey,
width: 3.0,
),
),
),
)
],
)),
// ),
_imageFile != null ? Image.file(_imageFile,height: 200,width: 200,)
: Container(),
// Screenshot(
// controller: screenshotController,
// child:
// imagePath != null ? Image.asset(imagePath,height:
100,width: 100,) : Container(),
// ),
RaisedButton(
onPressed: () {
screenshotController.capture().then((File image) {
//Capture Done
setState(() {
_imageFile = image;
});
}).catchError((onError) {
print(onError);
});
// onTakePictureButtonPressed();
// ScreenShot();
},
child: Text('Capture'),
)
]),
),
));
}
ScreenShot() async{
RenderRepaintBoundary boundary =
screen.currentContext.findRenderObject();
ui.Image image = await boundary.toImage();
ByteData byteData = await image.toByteData(format:
ui.ImageByteFormat.png);
var filePath = await ImagePickerSaver.saveFile(
fileData:byteData.buffer.asUint8List() );
print(filePath);
}
void _onMapCreated(GoogleMapController controller) {
_controller.complete(controller);
}
void _getLocation() async {
var currentLocation;
try {
currentLocation = await location.getLocation();
} catch (e) {
currentLocation = null;
}
setState(() {
locationdata = currentLocation;
lat = locationdata.latitude;
lng = locationdata.longitude;
_center = LatLng(lat, lng);
_markers.add(Marker(
// This marker id can be anything that uniquely identifies each
marker.
markerId: MarkerId(_center.toString()),
position: _center,
infoWindow: InfoWindow(
title: 'Really cool place',
snippet: '5 Star Rating',
),
icon: BitmapDescriptor.defaultMarker,
));
});
}
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
if (state == AppLifecycleState.inactive) {
controller?.dispose();
} else if (state == AppLifecycleState.resumed) {
if (controller != null) {
onNewCameraSelected(controller.description);
}
}
}
Widget _captureControlRowWidget() {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
mainAxisSize: MainAxisSize.max,
children: <Widget>[
IconButton(
icon: const Icon(Icons.camera_alt),
color: Colors.blue,
onPressed: controller != null &&
controller.value.isInitialized
? onTakePictureButtonPressed
: null,
),
],
);
}
String timestamp() => DateTime.now().millisecondsSinceEpoch.toString();
Future<String> takePicture() async {
if (!controller.value.isInitialized) {
// showInSnackBar('Error: select a camera first.');
return null;
}
final Directory extDir = await getApplicationDocumentsDirectory();
final String dirPath = '${extDir.path}/Pictures/flutter_test';
await Directory(dirPath).create(recursive: true);
final String filePath = '$dirPath/${timestamp()}.jpg';
if (controller.value.isTakingPicture) {
// A capture is already pending, do nothing.
return null;
}
try {
await controller.takePicture(filePath);
} on CameraException catch (e) {
// _showCameraException(e);
return null;
}
return filePath;
}
void onTakePictureButtonPressed() {
takePicture().then((String filePath) {
if (mounted) {
setState(() {
imagePath = filePath;
});
// if (filePath != null)
//showInSnackBar('Picture saved to $filePath');
}
});
}
void onNewCameraSelected(CameraDescription cameraDescription) async {
if (controller != null) {
await controller.dispose();
}
controller = CameraController(
CameraDescription(
name: "1",
lensDirection: CameraLensDirection.front,
sensorOrientation: 270),
ResolutionPreset.high,
enableAudio: true,
);
// If the controller is updated then update the UI.
controller.addListener(() {
if (mounted) setState(() {});
if (controller.value.hasError) {
// showInSnackBar('Camera error
${controller.value.errorDescription}');
print(controller.value.errorDescription);
}
});
try {
await controller.initialize();
} on CameraException catch (e) {
print(e);
// _showCameraException(e);
}
if (mounted) {
setState(() {});
}
}
Widget _cameraTogglesRowWidget() {
final List<Widget> toggles = <Widget>[];
if (cameras.isEmpty) {
return const Text('No camera found');
} else {
for (CameraDescription cameraDescription in cameras) {
toggles.add(
SizedBox(
width: 90.0,
child: RadioListTile<CameraDescription>(
title: Icon(getCameraLensIcon(cameraDescription.lensDirection)),
groupValue: controller?.description,
value: cameraDescription,
onChanged: controller != null ? null : onNewCameraSelected,
),
),
);
}
}
return Row(children: toggles);
}
IconData getCameraLensIcon(CameraLensDirection direction) {
switch (direction) {
case CameraLensDirection.back:
return Icons.camera_rear;
case CameraLensDirection.front:
return Icons.camera_front;
case CameraLensDirection.external:
return Icons.camera;
}
throw ArgumentError('Unknown lens direction');
}
Widget _cameraPreviewWidget() {
if (controller == null || !controller.value.isInitialized) {
return const Text(
'Tap a camera',
style: TextStyle(
color: Colors.white,
fontSize: 24.0,
fontWeight: FontWeight.w900,
),
);
} else {
return AspectRatio(
aspectRatio: controller.value.aspectRatio,
child: CameraPreview(controller),
);
}
}
}
''''''
那是代碼 Output: https://i.stack.imgur.com/PMLKu.jpg
但我需要那個 Output: https://i.stack.imgur.com/rAAs8.jpg
我向實現這一點的 Flutter 發送了一個拉取請求。 在他們合並之前,您可以使用我的插件分支: https ://github.com/duzenko/plugins/tree/maps-snapshot
檢查包:google_maps_flutter 2.0.6
@override
Widget build(BuildContext context) {
return Scaffold(
body: GoogleMap(
initialCameraPosition: CameraPosition(
target: LatLng(52.45594441365693, 30.96944870261119),
zoom: 14,
),
onMapCreated: (controller) async {
final uin8list = await controller.takeSnapshot(); // its our screenshot
// For examle, we can convert this uin8list to base64 and send
// to photohosting imgbb.com and get url on this image
final base64image = base64Encode(uin8list);
//...api post request
},
),
這里的問題是快照方法和截圖插件都在地圖渲染之前拍攝圖像。 flutter_maps 插件中有兩個可用的回調:
如果您在onMapCreated回調中放置animateCamera並在onCameraIdle 中捕獲圖像,則可以使用 onCameraIdle 。 我發現您每次都需要通過添加一個小的隨機縮放偏移來移動相機。
class GoogleMapWidget extends StatefulWidget {
const GoogleMapWidget(
{Key? key, required this.latLng, required this.markers})
: super(key: key);
final LatLng latLng;
final Set<Marker> markers;
@override
State<GoogleMapWidget> createState() => GoogleMapWidgetState();
}
class GoogleMapWidgetState extends State<GoogleMapWidget> {
final Completer<GoogleMapController> _mapController =
Completer<GoogleMapController>();
Uint8List? imageBytes;
@override
Widget build(BuildContext context) {
return imageBytes != null
? Image.memory(imageBytes!, fit: BoxFit.cover)
: GoogleMap(
onMapCreated: (GoogleMapController controller) {
_mapController.complete(controller);
takeSnapShot();
},
initialCameraPosition: CameraPosition(
target: widget.latLng,
zoom: 13.0,
),
markers: widget.markers,
compassEnabled: false,
indoorViewEnabled: false,
myLocationEnabled: false,
myLocationButtonEnabled: false,
zoomControlsEnabled: false,
zoomGesturesEnabled: false,
tiltGesturesEnabled: false,
scrollGesturesEnabled: false,
rotateGesturesEnabled: false,
);
}
void takeSnapShot() async {
GoogleMapController controller = await _mapController.future;
Future<void>.delayed(const Duration(milliseconds: 1000), () async {
imageBytes = await controller.takeSnapshot();
setState(() {});
});
}
要獲取唯一 map 內容的屏幕截圖,您可以使用GoogleMapController.takeSnapshot()
function。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.