In IOS 13 Google Map camera position is not showing Accurate when ViewController is Presented not pushed.Both screenshot attached - ios

I am working on Taxi App, Where I want to present and show three markers but always the camera position is always top left corner, I have to scroll map view to see the markers.Already tried these things.
Put my code in viewwillappear & viewdidappear and remove it from viewdidload.
Put all my code in DispatchQueue after 2 seconds
Use Animation & increase/Decrease time.
The sample code has been attached just to show one marker, which is perfectly working fine when view controller is being pushed to the navigation stack.
func testCode() {
mapView.layoutIfNeeded()
DispatchQueue.main.asyncAfter(deadline: .now() + 2, execute: {
let camera = GMSCameraPosition(latitude: 31.326137, longitude: 75.575520, zoom: 10)
self.pickupMarker = GMSMarker()
self.addMarkerOnMap(lat: "31.326137", long: "75.575520", img: #imageLiteral(resourceName: "drop-icon"), mapVieww: self.mapView,marker: &(self.pickupMarker), title: "Drop at", snippet:"Hello")
CATransaction.begin()
CATransaction.setValue(Int(1), forKey: kCATransactionAnimationDuration)
self.mapView.animate(to: camera)
CATransaction.commit()
})
}

I did Four things to resolve this issue.
Take a container first where I want my map view, in the storyboard and make an outlet in the class.
Remove mapview outlet and remove mapview UIVIew from a storyboard also.
Programmatically add GMSMapView as a subview in a container (where I want to show the map).
Add code in viewdidappear method in Dispatchqueue and everything is now working fine.

Related

Why do my SwiftUI gestures on a Map work only once?

Setup:
I am converting an app from UIKit to SwiftUI.
The app uses now instead of an MKMapView a SwiftUI Map.
Unfortunately, not all features of an MKMapView are already provided by Apple for Map, e.g. dragging a map annotation and getting the coordinate of the drag end point.
Anyway, I am trying thus to implement a similar function in SwiftUI. This is the development body of my annotation view:
var body: some View {
GeometryReader { geo in // 1
let frameInGlobal = geo.frame(in: .global)
Image("PinRed")
.background(Color.green) // 2
.offset(CGSize(width: dragAmount.width, height: dragAmount.height - liftOff)) // 3
.defersSystemGestures(on: .all) // 4
.onTapGesture {
print("Global center: \(frameInGlobal.midX) x \(frameInGlobal.midY)")
}
.gesture(drag(frameInGlobal: frameInGlobal)) // 5
.simultaneousGesture( // 6
LongPressGesture(minimumDuration: 0.2)
.onEnded { _ in // 7
liftOff = 40.0
}
)
}
.frame(width: 30, height: 30)
.background(Color.red) // 2
}
<1> GeometryReader is used to get the screen coordinates during dragging.
<2> The background colors are there so that it can easily be identified what happens.
<3> The pin image is offset by the drag amount plus a vertical shift so that the pin is visible above the finger.
<4> The system gestures, e.g. zoom in after double tap and long press to drag the map, are deferred so that the custom gestures come through.
<5> The custom drag gesture essentially changes a #GestureState var dragAmount = CGSize.zero so that the pin image follows the finger.
<6> A simultaneousGesture is required so that the custom tap gesture as well as the custom long press gesture can be used.
<7> That the pin is lift off, indicates that dragging can start.
Problem:
If the liftOff value is 0.0, I can tap the annotation, which prints out its position, and I can long press it and drag it around. After dragging stopped, it still accepts further taps and long presses.
However, when the liftOff value is e.g. 40.0, the annotation can only be tapped as long as it is not dragged, and when it has been dragged the 1st time, it cannot be dragged again. This means the custom gestures do no longer come through. Instead, only the system gestures work.
Here is an example of the situation after the 1st drag (green is the image background, red the GeometryReader background).
Question:
Why are the custom gestures only accepted when the pin is not lift off?
And how to do it right?
Edit:
I just found out that my custom gestures work as long as Image (green square) and GeometryReader (red square) overlap, and the tap point, long press point and start point of a drag are within the overlap area.
Problem solved. It has nothing to do with SwiftUI:
If in the code example above liftOff is 0, the green View (Image) and the red View (GeometryReader) have always the same position on the screen. If the green View is tapped, the hit position is forwarded to the custom gestures. Since the red View has the same position on the screen, the red View handles the hit.
If however liftOff is larger than the frame size of the green and red View, both do not overlap on the screen. If now the green View is tapped, the hit position is forwarded to the red View that does not overlap the green View, i.e. the red View is not hit, and the hit is forwarded to the next View behind the green View, which is the Map itself. Thus the custom gestures are not triggered, but the system gestures.
In the code above, this can easily be checked by adding line 3 additionally as last view modifier of the GeometryReader.

Unable to Add UI elements on top of AGSMapView

I have an app that I'm trying to migrate from Google Maps to ArcGIS maps because I need to use the maps offline.
I'm using the ArcGIS iOS 100.6 SDK and am trying to place a UIbutton on top of AGSMapView. In the View Controller "MapView" and the UIButton are under "View". The UIbutton is not a subview of MapView. I also have three other elements that should overlay the map that I hide and unhide using "isHidden = true/false" and these cannot be displayed either. The app is written in Swift 4.2 and I'm using Xcode 10.3.
Here is the view in the view controller:
View
Safe Area
Btn Satellite Toggle (outlet name: "btnSatelliteToggle")
View Mark Location
View Verify Location
View Pic Detail
MapView
Constraints
This is the code where I show the map and try to add the button on top:
let viewMap = AGSMapView(frame: .zero)
viewMap.map = AGSMap(basemapType: .navigationVector,
latitude: currentLocation.latitude, longitude: currentLocation.longitude,
levelOfDetail: zoomLevel)
viewMap.graphicsOverlays.add(overlay)
viewMap.touchDelegate = self
view = viewMap
view.bringSubviewToFront(btnSatelliteToggle)
The map is displayed along with the graphics overlay, but I am unable to show any UI elements on top of the map. This works fine with Google maps, but not with ArcGIS maps.
How do I get these UI elements to be displayed on top of the AGSMapView generated map?
Thanks in advance for your help.
It appears your MapView is at the top of the view hierarchy and thus obscuring its sibling views.
Try rearranging the view hierarchy to place the MapView at the bottom:
View
Safe Area
MapView
Btn Satellite Toggle (outlet name: "btnSatelliteToggle")
View Mark Location
View Verify Location
View Pic Detail
Constraints
I actually just solved this. Here is the updated code that works:
viewMap.map = AGSMap(basemapType: .navigationVector,
latitude: currentLocation.latitude, longitude: currentLocation.longitude,
levelOfDetail: zoomLevel)
viewMap.graphicsOverlays.add(overlay)
viewMap.touchDelegate = self
I removed:
Setting AGSMapView(frame: .zero)
as this prevented the map from being displayed in MapView.
Also, by not setting a view (thus using the default view controller "view") all siblings are available for display and can be controlled via "isHidden."

How to add a fixed bar on the mapView on iOS

Recently, I have made a simple project which needs to use GoogleMap Api.
I think that my Question is so simple and easy,
but i don't know how to complete it.
Well this is my problem
i want to add a just simple bar on the View.(up 1, bottom 1)
these 2 bars are fixed. and also there is a button(like moving back button) on the bars that i can presse
Except 2 bar position, if i drag/swipe on mapView than change and show the location information.
please check the following image.(This is what i want to make.)
How can i put the bars on the view and let the bars can be seen in the simulator? plz let me know
(i dont upload code cuz it's not the problem about the code, just want to know about the concept of how to insert view(or layer?) like that)
First, let say you have a map view:
let camera = GMSCameraPosition.camera(withLatitude: 11.5449, longitude: 104.8922, zoom: 12)
let map = GMSMapView.map(withFrame: .zero, camera: camera)
map.isMyLocationEnabled = true
self.view = map
Then, you can just add your top and bottom views to the view as normal
let topBar = UIView()
view.addSubview(topBar)
let bottomBar = UIView()
view.addSubview(bottomBar)
And if you want to add other views such as texts and buttons, you can add them as subviews to the topBar or bottomBar view
let button = UIButton()
topBar.addSubview(button)
Noted: to put the views in the exact locations as in the image, you need to specify their locations.
For example:
bottomBar.frame = CGRect(x: 0, y: view.bounds.height - 200, width: view.bounds.width, height: 200)
In storyboard:
I didn't use google maps so here I'm using the default MKMapView as an example.
First, let's say we have a map view covering the entire view controller:
Then for the top bar, let's add a view and give it some constraints:
Now for the back button and the title:
Now, for the bottom bar: first we need a view to hold all the things:
For the texts, we use 4 uilabels, embed them into a stack to make them lined-up. Give some spacing as well to make them look good:
Finally, for the image on the right, we can use uiimageview or uibutton:
Don't forget to add constraints to the stackview and the uiimageview/uibutton

How do I create a new View (or subView) with the tap of a button in swift?

I am currently making a flashcard app, and I am trying to make a button that creates an entirely new View (or subView) for the user to edit. Should I use Container Views? Collection Views? I also want to have these set to only one View Controller, so I can save the "cards" in one "set". Please Help!!
Edit: How can I save these views in a "folder" so the user can look at them later. Is there an efficient way to do this so the app doesn't slow or stop.
Edit #2: Ok, so I'm kind of getting it... collection views. But how would I implement this into my because I am using tvOS. Any thoughts?
If you want to create a new UIView programmatically, it's actually quite simple. You could create a method like this:
func addNewView(to container: UIView) {
let newView = UIView()
container.addSubview(newView)
newView.backgroundColor = UIColor.blue
newView.frame = CGRect(x: 10, y: 50, width: 200, height: 250)
}
That would create a new view inside whichever container view you passed in with a blue background, 10pts from the left (x-axis), 50pts from the top (y-axis, think a normal cartesian coordinate system with the y-axis inverted), width of 200 and height of 250.
You could then call this method on the push of a button by handling a button tap with it's own method like this:
func buttonTapped(_ sender: UIButton) {
addNewView(to: self.view)
}
Obviously all the values for the frame I gave you were just for an example so you could visualize it in your head, you can edit those however you want, or make calculations based on the size of your device's screen. You can get the device's screen size by saying self.view.bounds

iOS Google Maps API - Views and Labels will not Overlay Over the Map

I have created a Google Map view using the Google Maps SDK for iOS and the map displays fine. Then I added a label on top of the Map. When I run this the label will not show on top of the map. I've tried moving the label to different positions, messing with constraints, but nothing seems to make the label show. I've also tried putting the label in the View instead of it being a child of Map. It still will not show.
Here is the relevant code:
import UIKit
import GoogleMaps
class MapViewController: UIViewController, GMSMapViewDelegate {
override func viewDidLoad() {
super.viewDidLoad()
let camera = GMSCameraPosition.cameraWithLatitude(37.4987309,
longitude: -77.4700891, zoom: 10)
let mapView = GMSMapView.mapWithFrame(CGRectZero, camera: camera)
mapView.delegate = self
self.view = mapView
}
}
Here is the storyboard:
Try this. Drag a new view
into your storyboard and place it under your label like the picture.
Then CTRL+drag from the "Map View" to the "View" and shift+click the following options and click "add constraints"
This is simply setting the simple autolayout constraints. CTRL+drag the "Map View" into your view controller's class.
Replace self.view = mapView, with self.theMapView.addSubview(mapView).
(where theMapView is the "Map View" in the storyboard)
Now, instead of your actual main view adding the map as a view, you're just creating a subview that does the same, and you have full control of what goes on top of what!
I encountered the same situation and here is how I solved it.
In your storyboard you have a view named 'Map'
You created the following camera :
let camera = GMSCameraPosition.cameraWithLatitude(37.4987309,
longitude: -77.4700891, zoom: 10)
Control drag the 'Map' View onto your view controller and name it whatever, such as mapView
self.mapView.camera = camera
self.mapView.bringSubview(toFront: yourLabelToBePlacedOnTop)

Resources