Skip to content
This repository has been archived by the owner on Aug 8, 2023. It is now read-only.

Optimise touch target for Marker clicks #8159

Closed
tobrun opened this issue Feb 22, 2017 · 23 comments
Closed

Optimise touch target for Marker clicks #8159

tobrun opened this issue Feb 22, 2017 · 23 comments
Assignees
Labels
Android Mapbox Maps SDK for Android

Comments

@tobrun
Copy link
Member

tobrun commented Feb 22, 2017

We have seen a couple of reports related to clicks on Marker and MarkerViews (#8158 / #8118). The root cause of these issues is the way we handle touch interaction with these components.

Both implementations of Markers rely on QueryPointAnnotations. This uses a rectangle to query the map for annotations. We currently try optimising the size of the rectangle with the average size of icons added to the map. This approach isn't ideal as sometimes the click isn't fired while you would expect it to.

ezgif com-video-to-gif 16

For MarkerViews we used to rely on click events on the Views itself but that resulted in issues as #5388. I want to look into bringing back view click handling as this will bring the best ux and allows for defining Android sdk selectors.

@tobrun
Copy link
Member Author

tobrun commented Mar 14, 2017

MarkerView clicks are now handled back on the View object since #8272. Relying on the platform implementation will provide the UX users are expecting. What remains for this ticket to close is optimizing the touch target for gl-based markers.

@mariusboepple
Copy link

What is the status on this? Still having the issue with anchoring with 5.0.1 (#7307).

@tobrun
Copy link
Member Author

tobrun commented Mar 28, 2017

@mariusboepple anchoring is fixed with #8519 and is testable with the SNAPSHOT version.

@mariusboepple
Copy link

@tobrun Thanks, I'll test soon!

@tobrun
Copy link
Member Author

tobrun commented Apr 19, 2017

MarkerView click behavior has been reverted with the 5.0.2 release in #8585. Issue is back in OP state.

@tobrun tobrun added this to the android-future milestone Apr 19, 2017
@pamartineza
Copy link

I have been discussing briefly this issue with your colleague @Guardiola31337

I'm using 5.0.2 release and still seeing inconsistent marker click behaviours:

If I declare a marker using "MarkerOptions", clicks are listened properly but icons appear anchored in the center.

val marker = mapboxMap.addMarker(MarkerOptions().position(latLng).icon(beachIcon))

If I declare a marker using "MarkerViewOptions", clicks are listened but first one and icons are bottom center anchored.

val marker = mapboxMap.addMarker(MarkerViewOptions().position(latLng).icon(beachIcon))

Is there any workaround right now to get clicks on markers properly while being able to have a bottom center anchored icon?

Thanks

@nijs9
Copy link

nijs9 commented May 13, 2017

Same problem here. When clicking a markerview, first click infowindow is showed. Only at the second click, onMarkerClick is triggered. You need to click a markerview 2 times to trigger the onMarkerClick, and infowindow always appear.

@MikeKasperlik
Copy link

Any news on this? I think having bottom centered annotations in a map AND allow the user to select them is not a too uncommon use-case. At least a workaround would be nice.

@pamartineza
Copy link

@MikeKasperlik @nijs9 this has been solved in #8991 afaik the fix will be released next monday, but if you want you can already use the SNAPSHOT version:

repositories {
    mavenCentral()
    maven { url "http://oss.sonatype.org/content/repositories/snapshots/" }
}

dependencies {
    compile ('com.mapbox.mapboxsdk:mapbox-android-sdk:5.1.0-SNAPSHOT@aar') {
        transitive=true
    }
}

@MikeKasperlik
Copy link

Sadly still the same behaviour with the snapshot version (5.1.0). Only clicks on the lower half of my markerview is detected.

@Larnoo
Copy link

Larnoo commented May 18, 2017

I have a problem. My Marker view is very large, but the clickable area is small.

@buganini
Copy link

buganini commented May 24, 2017

With 5.0.2 I am fine with clickable area but for the first click, infowindow shows, onMarkerClick not called, for the second click, infowindow shaows, onMarkerClick called.

onMarkerClick is called only when infowindow is displayed.

@tobrun
Copy link
Member Author

tobrun commented May 24, 2017

@buganini you are probably using an MarkerView? For this you need to use MarkerViewClickListener instead of MarkerClickListener. The mentioned use-case isn't reproducible with latest code (the default marker click listener will not be invoked anymore).

@buganini
Copy link

@tobrun you are right, thanks.

@galacticappster04
Copy link

galacticappster04 commented May 29, 2017

Any news on this one?

By the way, is this still related on marker clicks very large clickable area? This is really urgent in my case. I have my marker asset (which is a pointed marker) 2x height so it centers on its target. Unfortunately, this also enlarges its touch area such that tapping below the marker selects the marker itself, even though there is no marker there.

This really gets worse if you have a lot of markers in the screen. Selection jumps from marker to another. It is in fact annoying.

Is fix on the way?

@tobrun
Copy link
Member Author

tobrun commented May 29, 2017

Due to high request on this ticket, we are handling this as a high priority. Optimizing click events for all different size markers is a hard problem. To unblock you, I'm adding an example workaround. Though it needs to be fine tuned for your specific use-case + might need some additional InfoWindow management:

        mapboxMap.setOnMarkerClickListener(new MapboxMap.OnMarkerClickListener() {
          @Override
          public boolean onMarkerClick(@NonNull Marker marker) {
            // no op
            return true; // returning true here = handling click event ourselves
          }
        });
    mapView.setOnTouchListener(new View.OnTouchListener() {
      private int CLICK_ACTION_THRESHHOLD = 200;
      private float startX;
      private float startY;

      @Override
      public boolean onTouch(View v, MotionEvent event) {
        switch (event.getAction()) {
          case MotionEvent.ACTION_DOWN:
            startX = event.getX();
            startY = event.getY();
            break;
          case MotionEvent.ACTION_UP:
            float endX = event.getX();
            float endY = event.getY();
            if (isAClick(startX, endX, startY, endY)) {
              // the following invocation can also take in a rectangle instead of a Point
              List<Feature> features = mapboxMap.queryRenderedFeatures(new PointF(endX, endY), "com.mapbox.annotations.points");
              Timber.e("features size: %s", features.size());
              if(features.size()>0) {
                Feature f = features.get(0);
                Timber.e("features data: %s / %s / %s", f.getId(), f.getGeometry(),f.getType());
                List<Marker>markers = mapboxMap.getMarkers();
                for (Marker marker : markers) {
                  if(f.getId().equals(String.valueOf(marker.getId()))){
                    mapboxMap.selectMarker(marker);
                  }
                }
              }
            }
            return true;
        }
        return false;
      }


      private boolean isAClick(float startX, float endX, float startY, float endY) {
        float differenceX = Math.abs(startX - endX);
        float differenceY = Math.abs(startY - endY);
        if (differenceX > CLICK_ACTION_THRESHHOLD || differenceY > CLICK_ACTION_THRESHHOLD) {
          return false;
        }
        return true;
      }
    });

@mare011
Copy link

mare011 commented May 29, 2017

Hi I'm using MarkerViews, i have a layer of hexagons (like a bee hive) and markers in every hexagon, they are next to each others, but the click works just around the center of the view I've tried using both fixed and unspecified dimensions for a view.I've tried the solution above, but queryRenderedFeatures with point does not find any features, RectF variant works, but if I create rect from the size of the view it will catch the other features as well, should i then look for the closest one or do you have a better advice? Also if there any way i could trigger a pressed state on a marker view?

@zugaldia zugaldia modified the milestones: android-v5.2.0, android-future Jun 30, 2017
@tobrun
Copy link
Member Author

tobrun commented Jul 5, 2017

The way forward for this issue is to implement proper hit testing, for Marker this will mean using the height and width of Icon as bounds. For MarkerViews we will rely on View#getHitRect().

@tobrun
Copy link
Member Author

tobrun commented Jul 5, 2017

The View#getHitRect() approach seems promising.

ezgif com-video-to-gif 58

One side note:

These bounds do not account for any transformation properties currently set on the view, such as setScaleX(float) or setRotation(float).

@tobrun
Copy link
Member Author

tobrun commented Jul 5, 2017

The hit testing for GL based markers works as well as above:

ezgif com-video-to-gif 60

@tobrun
Copy link
Member Author

tobrun commented Jul 5, 2017

There is just one problem to be fixed here, and that is the issue of overlapping markers. I'm going to implement selecting a marker based on the overlap is has on the touch area.

update: this was fixed with intersecting the bounds with touch area and checking for the largest overlap of all the markers in the near area.

@tobrun
Copy link
Member Author

tobrun commented Jul 6, 2017

A MarkerView workaround that is backportable to older versions can be found here

@basitsaleemmb
Copy link

how to increase marker click area

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Android Mapbox Maps SDK for Android
Projects
None yet
Development

No branches or pull requests