private void handleTap(final MapSelectableItem item, final Geopoint touchedPoint, final boolean isLongTap, final int tapX, final int tapY) {
        final RouteItem routeItem = item.isRouteItem() ? item.getRouteItem() : null;
        if (isLongTap) {
            // toggle route item
            if (routeItem != null && Settings.isLongTapOnMapActivated()) {

                final Geocache cache = routeItem.getGeocache();

                if (Settings.isShowRouteMenu()) {
                    final SimplePopupMenu menu = MapUtils.createCacheWaypointLongClickPopupMenu(this, routeItem, tapX, tapY, viewModel.individualRoute.getValue(), viewModel, null);
                    if (MapStarUtils.canHaveStar(cache)) {
                        final String geocode = routeItem.getGeocode();
                        viewModel.cachesWithStarDrawn.write(cwsd -> {
                            final boolean isStarDrawn = cwsd.contains(geocode);
                            MapStarUtils.addMenuIfNecessary(menu, cache, isStarDrawn, drawStar -> {
                                CommonUtils.addRemove(cwsd, geocode, !drawStar);
                                viewModel.cachesWithStarDrawn.notifyDataChanged();
                            });
                        });
                    }
                    menu.show();
                } else {
                    viewModel.toggleRouteItem(this, routeItem);
                }
            } else if (item.isRoute() && routeTrackUtils != null && item.getRoute() != null) {
                // individual route or track
                if (lastElevationChartRoute != null && StringUtils.equals(item.getRoute().getName(), lastElevationChartRoute)) {
                    elevationChartUtils.removeElevationChart();
                } else {
                    routeTrackUtils.showRouteTrackContextMenu(tapX, tapY, this::handleLongTapOnRoutesOrTracks, RouteTrackUtils.isIndividualRoute(item.getRoute()) ? viewModel.individualRoute.getValue() : item.getRoute());
                }
            }
        } else if (routeItem != null) {
            // open popup for element
            if (routeItem.getType() == RouteItem.RouteItemType.GEOCACHE) {
                viewModel.sheetInfo.setValue(new UnifiedMapViewModel.SheetInfo(routeItem.getGeocode(), 0));
                sheetShowDetails(viewModel.sheetInfo.getValue());
                MapMarkerUtils.addHighlighting(routeItem.getGeocache(), getResources(), nonClickableItemsLayer);
            } else if (routeItem.getType() == RouteItem.RouteItemType.WAYPOINT && routeItem.getWaypointId() != 0) {
                viewModel.sheetInfo.setValue(new UnifiedMapViewModel.SheetInfo(routeItem.getGeocode(), routeItem.getWaypointId()));
                sheetShowDetails(viewModel.sheetInfo.getValue());
                MapMarkerUtils.addHighlighting(routeItem.getWaypoint(), getResources(), nonClickableItemsLayer);
            }
        } else if (item.getData() instanceof Zone) {
            WherigoViewUtils.displayThing(this, item.getData(), false);
        } else if (item.getData() instanceof String) {
            GeoItemTestLayer.handleTapTest(clickableItemsLayer, this, touchedPoint, item.getData().toString(), isLongTap);
        }
    }
to be called by map fragments' observers for zoom level change
main/src/main/java/cgeo/geocaching/unifiedmap/UnifiedMapActivity.java