Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

onTapGesture not working #39

Open
IraklisElef opened this issue Mar 9, 2023 · 23 comments
Open

onTapGesture not working #39

IraklisElef opened this issue Mar 9, 2023 · 23 comments

Comments

@IraklisElef
Copy link

IraklisElef commented Mar 9, 2023

The onTapGesture is not working inside the ViewMapAnnotation, here is my code:

 `Map(
        coordinateRegion: $region,
        type: .standard,
        pointOfInterestFilter: .includingAll,
        interactionModes: [.all],
        annotationItems: evChargerManager.evChargers,
        annotationContent: { charger in

            ViewMapAnnotation(coordinate: (charger.addressInfo?.coordinates)!) {

                Image(K.Images.SupplementarilyIcons.pinpoint)
                    .resizable()
                    .frame(width: 40, height: 40, alignment: .center)
                    .onTapGesture {
                        showingSheet.toggle()
                    }
                    .sheet(isPresented: $showingSheet) {
                        EVChargerView(evCharger: charger)
                    } //: SHEET

            } //: VIEW MAP ANNOTATION

        } //: ANNOTATION CONTENT

    ) //: MAP`
@pauljohanneskraft
Copy link
Owner

You are right - this is one of the issues that #38 is trying to fix - could you please try whether your gesture works when targeting that branch?

@JohannesWi
Copy link

Got the same problem. Using the Branch https://github.com/iakov-kaiumov/Map didn't solve the problem for me.

Hope this get fixed soon as the library is amazing and I would love to use it!

@iakov-kaiumov
Copy link

@JohannesWi
Hi! Could you provide an example of code that is not working for you, please? It will help me to solve the issue.
In my project everything works fine.

@JohannesWi
Copy link

Thanks for your response @iakov-kaiumov !
Im using the same example as @IraklisElef is doing. My code looks like this:

Map(
                         coordinateRegion: $region,
                          type: .standard,
                          pointOfInterestFilter: .excludingAll,
                          informationVisibility: .default.union(.userLocation),
                          interactionModes: [.all],
                          annotationItems: markers,
                          annotationContent: { location in
                              ViewMapAnnotation(coordinate: location.coordinate) {
                                  Color.red
                                    .frame(width: 24, height: 24)
                                    .clipShape(Circle())
                                    .onTapGesture {
                                      print("test")
                                    }
                              }
                          }
                        )
                .frame(height: 350)
                .cornerRadius(8)

@iakov-kaiumov
Copy link

@JohannesWi
This is really strange, because this code works for me. Attaching screen recording and code fragment.

struct Annotation: Identifiable {

    let id = UUID()
    let coordinate: CLLocationCoordinate2D
    let clusteringIdentifier: String

}

struct ContentView: View {

    @State private var region = MKCoordinateRegion(
        center: .init(latitude: 50, longitude: 10),
        latitudinalMeters: 100_000,
        longitudinalMeters: 100_000
    )

    @State private var annotations = [
        Annotation(coordinate: .init(latitude: 49.5, longitude: 09.5), clusteringIdentifier: "a"),
        Annotation(coordinate: .init(latitude: 49.5, longitude: 10.0), clusteringIdentifier: "a"),
        Annotation(coordinate: .init(latitude: 49.5, longitude: 10.5), clusteringIdentifier: "a"),
        Annotation(coordinate: .init(latitude: 50.0, longitude: 09.5), clusteringIdentifier: "b"),
        Annotation(coordinate: .init(latitude: 50.0, longitude: 10.0), clusteringIdentifier: "b"),
        Annotation(coordinate: .init(latitude: 50.0, longitude: 10.5), clusteringIdentifier: "b"),
        Annotation(coordinate: .init(latitude: 50.5, longitude: 09.5), clusteringIdentifier: "b"),
        Annotation(coordinate: .init(latitude: 50.5, longitude: 10.0), clusteringIdentifier: "b"),
        Annotation(coordinate: .init(latitude: 50.5, longitude: 10.5), clusteringIdentifier: "b"),
    ]
    
    @State private var isPresented: Bool = false

    var body: some View {
        Map(
            coordinateRegion: $region,
            type: .standard,
            pointOfInterestFilter: .excludingAll,
            informationVisibility: .default.union(.userLocation),
            interactionModes: [.all],
            annotationItems: annotations,
            annotationContent: { location in
                ViewMapAnnotation(coordinate: location.coordinate) {
                    Color.red
                    .frame(width: 24, height: 24)
                    .clipShape(Circle())
                    .onTapGesture {
                        isPresented.toggle()
                    }
                }
            }
        )
        .cornerRadius(8)
        .alert(isPresented: $isPresented) { Alert(title: Text("Tapped!")) }
    }
}
Simulator.Screen.Recording.-.iPhone.14.Pro.Max.-.2023-03-10.at.15.32.04.mov

@IraklisElef
Copy link
Author

The branch of @iakov-kaiumov did it for me! It also fixed the weird bug with the annotation where it misplaces itself when applying the .ignoresSafeArea() modifier. However, there is another weird bug. When I press the annotation, instead of showing one sheet, it kind of shows 2 sheets one on top of the other, here is a screen recording:

RPReplay_Final1678461918.mov

@JohannesWi
Copy link

JohannesWi commented Mar 10, 2023

@iakov-kaiumov
thank you very much for your reply! I have my map view inside a ZStack and added a custom color above which didn't work with the touch-event.

It would be great if this branch could be merged soon

@iakov-kaiumov
Copy link

The branch of @iakov-kaiumov did it for me! It also fixed the weird bug with the annotation where it misplaces itself when applying the .ignoresSafeArea() modifier. However, there is another weird bug. When I press the annotation, instead of showing one sheet, it kind of shows 2 sheets one on top of the other, here is a screen recording:

Could you please tell a little bit more about how you present the sheet? Such behaviour cannot occur when using one .sheet modifier even if the touch event trigger twice. Moreover, in my case, touch event fires only once, so, I guess that the problem is connected with your sheets implementation.

@IraklisElef
Copy link
Author

Ok so, I have an array of annotations. Each annotation has coordinates and some other data. Whenever I am presenting this annotation, I want to be able to click it and then show a sheet. This sheet needs the annotation's data. However, I noticed that the sheet does not take the correct annotation. It takes data from another annotation. Moreover, if I use instead a NavigationLink instead of a sheet, it shows the correct data every time. Do you have any clue of what is going on?

@IraklisElef
Copy link
Author

I figured it out. Here is my code:

                `Map(
                    coordinateRegion: $region,
                    type: .standard,
                    pointOfInterestFilter: .includingAll,
                    interactionModes: [.all],
                    annotationItems: mapInformation.evChargers,
                    annotationContent: { charger in
        
                        ViewMapAnnotation(coordinate: (charger.addressInfo?.coordinates)!) {
        
                            Image(K.Images.SupplementarilyIcons.pinpoint)
                                .resizable()
                                .frame(width: 40, height: 40, alignment: .center)
                                .onTapGesture {
                                    showingSheet.toggle()
                                }
                                .sheet(isPresented: $showingSheet) {
                                    EVChargerView(evCharger: charger)
                                } //: SHEET
        
                        } //: VIEW MAP ANNOTATION
        
                    } //: ANNOTATION CONTENT
        
                ) //: MAP`

As you can see, whenever the user taps the image. the showingSheet variable toggles to true, which ends up activating the sheet. Inside that sheet I have a view which takes as a parameter the annotation. However, because, as I understand, the Map struct keeps updating, it keeps passing every time a new annotation to the sheet view, which ends up creating not two sheets, but as many as there are annotations. Now that I know the issue, I am not sure how to work around it so that it passes only one annotation. I tried saving to a separate variable the annotation that the user taps on, and then passing that variable to the sheet view, but for some reason it does not save it. Any ideas?

@iakov-kaiumov
Copy link

@IraklisElef
As I thought, the problem is not connected with the Map library. To show the sheet correctly, try the following code:

struct YourView: View {
  ...

  @State private var selectedAnnotation: Annotation? = nil

  var body: some View {
      Map(
          coordinateRegion: $region,
          annotationItems: annotations,
          annotationContent: { annotation in
              ViewMapAnnotation(coordinate: annotation.coordinate) {
                 Image(K.Images.SupplementarilyIcons.pinpoint)
                  .resizable()
                  .frame(width: 40, height: 40, alignment: .center)
                  .onTapGesture {
                      selectedAnnotation = annotation
                  }
              }
          }
      )
      .sheet(item: $selectedAnnotation) { annotation in
          List {
              Text("Sheet! \(annotation.id.uuidString)")
          }
      }
   }
}

@IraklisElef
Copy link
Author

Game changing solution! Thank you! Could I ask you one more question? I am trying to use the clusterAnnotation property of the Map struct. However, I am not really sure how to implement it. Any suggestions?

@iakov-kaiumov
Copy link

iakov-kaiumov commented Mar 11, 2023

You may take a look at the examples in the readme. Also, if you are using my branch, update it to the latest version, please.

@IraklisElef
Copy link
Author

I have taken a look. However, I have not seen any mentions on how to use the clusterAnnotation property, nor have I seen any examples of it.

@pauljohanneskraft
Copy link
Owner

For the clusterAnnotation, first make sure to set the clusteringIdentifier parameter when initializing the ViewMapAnnotation. Annotations with the same clusteringIdentifier will be clustered, so make sure to not make that identifier fully unique, but according to some categorization or use the same for all annotations in use (depending on how you would like to cluster them), then the clusterAnnotation parameter in the Map-initializer will be called whenever the MKMapView decides to create clusters.

@IraklisElef
Copy link
Author

I want the clustering to work whenever the user zooms out too much and the annotations are on top of each other. Does that mean that I will need to have the same clusteringIdentifier for all my annotations? Also, when I am trying to use clusterAnnotation, it asks me for 2 parameters. One is MKClusterAnnotation and the other the annotation items that I passed earlier on the annotationItems parameter. Could you give me an example of what to pass on MKClusterAnnotation? One last thing. I see that you've included an anchor parameter in the ViewMapAnnotation. What values would I need to pass on my CGPoint to anchor my annotation (basically in the middle bottom part of my image) on this spot:

IMG_5202

@iakov-kaiumov
Copy link

@IraklisElef
Copy link
Author

IraklisElef commented Mar 11, 2023

I've managed to integrate a clusterAnnotation. One last question if you know the answer. Is it possible to cluster more annotations? What I am trying to say is, let's say that the user is currently zoomed out 25% and the number of annotations that are clustered is 20. I want to be able to cluster, for example 30 annotations, if the user is zoomed out by the same 25%. So basically make the area that is needed to cluster smaller. Is that possible or Swift has a default value for it?

@pauljohanneskraft
Copy link
Owner

I'm not sure whether this is even possible in MKMapView. @IraklisElef do you have a working example on how this would be implemented using MKMapView? If it is not possible there, it will not be possible here, since this is just a wrapper around the UIKit view.

@IraklisElef
Copy link
Author

No I do not have a working example using MKMapView. I reckoned it would not be possible; nevertheless, I asked you in case you knew something I did not know. One question @pauljohanneskraft. On the example you provided on clustering annotations, here, I see that you've include one line of code that I do not understand its purpose, this one: let _ = assert(Set(members.map(\.clusteringIdentifier)).count == 1). Could you explain what it does? I removed this line of code and the clustering still worked.

@pauljohanneskraft
Copy link
Owner

You can remove it.

It has been part of the example to show that only annotations with the same clusteringIdentifier exist in a cluster (i.e. that the set of clusteringIdentifiers has a count of 1) and asserts this to be true (i.e. it would fail, if that weren't the case).

@iakov-kaiumov
Copy link

I've managed to integrate a clusterAnnotation. One last question if you know the answer. Is it possible to cluster more annotations? What I am trying to say is, let's say that the user is currently zoomed out 25% and the number of annotations that are clustered is 20. I want to be able to cluster, for example 30 annotations, if the user is zoomed out by the same 25%. So basically make the area that is needed to cluster smaller. Is that possible or Swift has a default value for it?

If I understand you correctly, your problem is that your annotations are not collapsing even if they visually intersect. This is an unsolved issue of my implementation (MKViewAnnotation frame is smaller than it should be).
To solve the issue, try this branch #40

I've tested it and it works as expected. I hope soon it will be merged.

@IraklisElef
Copy link
Author

Is it safe to use or are there any bugs?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants