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

3115 multiple infowindows + leave open while panning #3127

Merged
merged 6 commits into from
Nov 30, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,13 @@
/**
* A tooltip view
*/
final class InfoWindow {
public class InfoWindow {

private WeakReference<Marker> mBoundMarker;
private WeakReference<MapView> mMapView;
private float mMarkerHeightOffset;
private float mViewWidthOffset;
private PointF mCoordinates;
private boolean mIsVisible;
protected View mView;

Expand Down Expand Up @@ -86,22 +89,26 @@ InfoWindow open(Marker boundMarker, LatLng position, int offsetX, int offsetY) {
MapView.LayoutParams lp = new MapView.LayoutParams(MapView.LayoutParams.WRAP_CONTENT, MapView.LayoutParams.WRAP_CONTENT);
mView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);

// Calculate default Android x,y coordinate
PointF coords = mMapView.get().toScreenLocation(position);
float x = coords.x - (mView.getMeasuredWidth() / 2) + offsetX;
float y = coords.y - mView.getMeasuredHeight() + offsetY;

// get right/left popup window
float rightSideInfowWindow = x + mView.getMeasuredWidth();
float leftSideInfoWindow = x;
// Calculate y-offset for update method
mMarkerHeightOffset = -mView.getMeasuredHeight() + offsetY;

// get right/left map view
final float mapRight = mMapView.get().getRight();
final float mapLeft = mMapView.get().getLeft();
// Calculate default Android x,y coordinate
mCoordinates = mMapView.get().toScreenLocation(position);
float x = mCoordinates.x - (mView.getMeasuredWidth() / 2) + offsetX;
float y = mCoordinates.y - mView.getMeasuredHeight() + offsetY;

if (mView instanceof InfoWindowView) {
// only apply repositioning/margin for InfoWindowView
Resources resources = mMapView.get().getContext().getResources();

// get right/left popup window
float rightSideInfowWindow = x + mView.getMeasuredWidth();
float leftSideInfoWindow = x;

// get right/left map view
final float mapRight = mMapView.get().getRight();
final float mapLeft = mMapView.get().getLeft();

float marginHorizontal = resources.getDimension(R.dimen.infowindow_margin);
float tipViewOffset = resources.getDimension(R.dimen.infowindow_tipview_width) / 2;
float tipViewMarginLeft = mView.getMeasuredWidth() / 2 - tipViewOffset;
Expand Down Expand Up @@ -129,15 +136,13 @@ InfoWindow open(Marker boundMarker, LatLng position, int offsetX, int offsetY) {
if (outOfBoundsRight && mapRight - rightSideInfowWindow < marginHorizontal) {
x -= marginHorizontal - (mapRight - rightSideInfowWindow);
tipViewMarginLeft += marginHorizontal - (mapRight - rightSideInfowWindow) - tipViewOffset;

leftSideInfoWindow = x;
}

// Add margin left
if (outOfBoundsLeft && leftSideInfoWindow - mapLeft < marginHorizontal) {
x += marginHorizontal - (leftSideInfoWindow - mapLeft);
tipViewMarginLeft -= (marginHorizontal - (leftSideInfoWindow - mapLeft)) - tipViewOffset;

}

// Adjust tipView
Expand All @@ -149,6 +154,9 @@ InfoWindow open(Marker boundMarker, LatLng position, int offsetX, int offsetY) {
mView.setX(x);
mView.setY(y);

// Calculate x-offset for update method
mViewWidthOffset = x - mCoordinates.x - offsetX;

close(); //if it was already opened
mMapView.get().addView(mView, lp);
mIsVisible = true;
Expand Down Expand Up @@ -196,7 +204,7 @@ void adaptDefaultMarker(Marker overlayItem) {
}

private void onClose() {
mMapView.get().deselectMarker();
mMapView.get().deselectMarker(getBoundMarker());
}

InfoWindow setBoundMarker(Marker boundMarker) {
Expand Down Expand Up @@ -226,4 +234,15 @@ private static void setResIds(Context context) {
.getIdentifier("id/infowindow_subdescription", null, packageName);
mImageId = context.getResources().getIdentifier("id/infowindow_image", null, packageName);
}

public void update() {
MapView mapView = mMapView.get();
Marker marker = mBoundMarker.get();
if (mapView != null && marker != null) {
mCoordinates = mapView.toScreenLocation(marker.getPosition());
mView.setX(mCoordinates.x + mViewWidthOffset);
mView.setY(mCoordinates.y + mMarkerHeightOffset);
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,9 @@ void setTitle(String title) {
/**
* Do not use this method. Used internally by the SDK.
*/
public void showInfoWindow() {
public InfoWindow showInfoWindow() {
if (getMapView() == null) {
return;
return null;
}

MapView.InfoWindowAdapter infoWindowAdapter = getMapView().getInfoWindowAdapter();
Expand All @@ -91,17 +91,18 @@ public void showInfoWindow() {
if (content != null) {
infoWindow = new InfoWindow(content, getMapView());
showInfoWindow(infoWindow);
return;
return infoWindow;
}
}

getInfoWindow().adaptDefaultMarker(this);
showInfoWindow(getInfoWindow());
return showInfoWindow(getInfoWindow());
}

private void showInfoWindow(InfoWindow iw) {
private InfoWindow showInfoWindow(InfoWindow iw) {
iw.open(this, getPosition(), 0, topOffsetPixels);
infoWindowShown = true;
return iw;
}

private InfoWindow getInfoWindow() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
import com.almeros.android.multitouch.gesturedetectors.TwoFingerGestureDetector;
import com.mapbox.mapboxsdk.R;
import com.mapbox.mapboxsdk.annotations.Annotation;
import com.mapbox.mapboxsdk.annotations.InfoWindow;
import com.mapbox.mapboxsdk.annotations.Marker;
import com.mapbox.mapboxsdk.annotations.MarkerOptions;
import com.mapbox.mapboxsdk.annotations.Polygon;
Expand Down Expand Up @@ -201,7 +202,8 @@ public final class MapView extends FrameLayout {
// Every annotation that has been added to the map
private final List<Annotation> mAnnotations = new ArrayList<>();
private List<Marker> mMarkersNearLastTap = new ArrayList<>();
private Marker mSelectedMarker;
private List<Marker> mSelectedMarkers = new ArrayList<>();
private List<InfoWindow> mInfoWindows = new ArrayList<>();
private InfoWindowAdapter mInfoWindowAdapter;
private SpriteFactory mSpriteFactory;
private ArrayList<Sprite> mSprites = new ArrayList<>();
Expand Down Expand Up @@ -238,6 +240,7 @@ public final class MapView extends FrameLayout {
private boolean mZoomEnabled = true;
private boolean mScrollEnabled = true;
private boolean mRotateEnabled = true;
private boolean mAllowConcurrentMultipleOpenInfoWindows = false;
private String mStyleUrl;

//
Expand Down Expand Up @@ -807,10 +810,6 @@ public void onCreate(@Nullable Bundle savedInstanceState) {
addOnMapChangedListener(new OnMapChangedListener() {
@Override
public void onMapChanged(@MapChange int change) {
if ((change == REGION_WILL_CHANGE) || (change == REGION_WILL_CHANGE_ANIMATED)) {
deselectMarker();
}

if (change == DID_FINISH_LOADING_MAP) {
reloadSprites();
reloadMarkers();
Expand Down Expand Up @@ -1294,6 +1293,30 @@ private void zoom(boolean zoomIn, float x, float y) {
}
}

//
// InfoWindows
//

/**
* Changes whether the map allows concurrent multiple infowindows to be shown.
*
* @param allow If true, map allows concurrent multiple infowindows to be shown.
*/
@UiThread
public void setAllowConcurrentMultipleOpenInfoWindows(boolean allow) {
this.mAllowConcurrentMultipleOpenInfoWindows = allow;
}

/**
* Returns whether the map allows concurrent multiple infowindows to be shown.
*
* @return If true, map allows concurrent multiple infowindows to be shown.
*/
@UiThread
public boolean isAllowConcurrentMultipleOpenInfoWindows() {
return this.mAllowConcurrentMultipleOpenInfoWindows;
}

//
// Debug
//
Expand Down Expand Up @@ -2005,7 +2028,8 @@ public double getMetersPerPixelAtLatitude(@FloatRange(from = -180, to = 180) dou

/**
* Selects a marker. The selected marker will have it's info window opened.
* Any other open info windows will be closed.
* Any other open info windows will be closed unless isAllowConcurrentMultipleOpenInfoWindows()
* is true.
* <p/>
* Selecting an already selected marker will have no effect.
*
Expand All @@ -2018,12 +2042,14 @@ public void selectMarker(@NonNull Marker marker) {
return;
}

if (marker == mSelectedMarker) {
if (mSelectedMarkers.contains(marker)) {
return;
}

// Need to deselect any currently selected annotation first
deselectMarker();
if (!isAllowConcurrentMultipleOpenInfoWindows()) {
deselectMarkers();
}

boolean handledDefaultClick = false;
if (mOnMarkerClickListener != null) {
Expand All @@ -2032,26 +2058,46 @@ public void selectMarker(@NonNull Marker marker) {
}

if (!handledDefaultClick) {
// default behaviour
// Can't do this as InfoWindow will get hidden
//setCenterCoordinate(marker.getPosition(), true);
marker.showInfoWindow();
// default behaviour show InfoWindow
mInfoWindows.add(marker.showInfoWindow());
}

mSelectedMarker = marker;
mSelectedMarkers.add(marker);
}

/**
* Deselects any currently selected marker. The selected marker will have it's info window closed.
* Deselects any currently selected marker. All markers will have it's info window closed.
*/
@UiThread
public void deselectMarker() {
if (mSelectedMarker != null) {
if (mSelectedMarker.isInfoWindowShown()) {
mSelectedMarker.hideInfoWindow();
mSelectedMarker = null;
public void deselectMarkers() {
if (mSelectedMarkers.isEmpty()) {
return;
}

for (Marker marker : mSelectedMarkers) {
if (marker.isInfoWindowShown()) {
marker.hideInfoWindow();
}
}

// Removes all selected markers from the list
mSelectedMarkers.clear();
}

/**
* Deselects a currently selected marker. The selected marker will have it's info window closed.
*/
@UiThread
public void deselectMarker(@NonNull Marker marker) {
if (!mSelectedMarkers.contains(marker)) {
return;
}

if (marker.isInfoWindowShown()) {
marker.hideInfoWindow();
}

mSelectedMarkers.remove(marker);
}

//
Expand Down Expand Up @@ -2129,8 +2175,8 @@ private void setVisibleCoordinateBounds(LatLng[] coordinates, RectF padding, dou
*/
@UiThread
@Nullable
public Marker getSelectedMarker() {
return mSelectedMarker;
public List<Marker> getSelectedMarkers() {
return mSelectedMarkers;
}

private void adjustTopOffsetPixels() {
Expand All @@ -2144,12 +2190,12 @@ private void adjustTopOffsetPixels() {
}
}

if (mSelectedMarker != null) {
if (mSelectedMarker.isInfoWindowShown()) {
Marker temp = mSelectedMarker;
for (Marker marker : mSelectedMarkers) {
if (marker.isInfoWindowShown()) {
Marker temp = marker;
temp.hideInfoWindow();
temp.showInfoWindow();
mSelectedMarker = temp;
marker = temp;
}
}
}
Expand Down Expand Up @@ -2230,6 +2276,9 @@ public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int h
public void onSurfaceTextureUpdated(SurfaceTexture surface) {
mCompassView.update(getDirection());
mUserLocationView.update();
for (InfoWindow infoWindow : mInfoWindows) {
infoWindow.update();
}
}
}

Expand Down Expand Up @@ -2426,19 +2475,24 @@ public boolean onSingleTapConfirmed(MotionEvent e) {
Collections.sort(nearbyMarkers);

if (nearbyMarkers == mMarkersNearLastTap) {

// TODO: We still need to adapt this logic to the new mSelectedMarkers list,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should ticket TODO: items rather than leave them in code.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My bad. Just ticketed it: #3156

// though the basic functionality is there.

// the selection candidates haven't changed; cycle through them
if (mSelectedMarker != null && (mSelectedMarker.getId() == mMarkersNearLastTap.get(mMarkersNearLastTap.size() - 1).getId())) {
// the selected marker is the last in the set; cycle back to the first
// note: this could be the selected marker if only one in set
newSelectedMarkerId = mMarkersNearLastTap.get(0).getId();
} else if (mSelectedMarker != null) {
// otherwise increment the selection through the candidates
long result = mMarkersNearLastTap.indexOf(mSelectedMarker);
newSelectedMarkerId = mMarkersNearLastTap.get((int) result + 1).getId();
} else {
// if (mSelectedMarker != null
// && (mSelectedMarker.getId() == mMarkersNearLastTap.get(mMarkersNearLastTap.size() - 1).getId())) {
// // the selected marker is the last in the set; cycle back to the first
// // note: this could be the selected marker if only one in set
// newSelectedMarkerId = mMarkersNearLastTap.get(0).getId();
// } else if (mSelectedMarker != null) {
// // otherwise increment the selection through the candidates
// long result = mMarkersNearLastTap.indexOf(mSelectedMarker);
// newSelectedMarkerId = mMarkersNearLastTap.get((int) result + 1).getId();
// } else {
// no current selection; select the first one
newSelectedMarkerId = mMarkersNearLastTap.get(0).getId();
}
// }
} else {
// start tracking a new set of nearby markers
mMarkersNearLastTap = nearbyMarkers;
Expand All @@ -2459,7 +2513,7 @@ public boolean onSingleTapConfirmed(MotionEvent e) {
Annotation annotation = mAnnotations.get(i);
if (annotation instanceof Marker) {
if (annotation.getId() == newSelectedMarkerId) {
if (mSelectedMarker == null || annotation.getId() != mSelectedMarker.getId()) {
if (mSelectedMarkers.isEmpty() || !mSelectedMarkers.contains(annotation)) {
selectMarker((Marker) annotation);
}
break;
Expand All @@ -2469,7 +2523,7 @@ public boolean onSingleTapConfirmed(MotionEvent e) {

} else {
// deselect any selected marker
deselectMarker();
deselectMarkers();

// notify app of map click
if (mOnMapClickListener != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ protected void onCreate(Bundle savedInstanceState) {
mMapView.setAccessToken(ApiAccess.getToken(this));
mMapView.onCreate(savedInstanceState);

// Enable to let concurrent multiple infowindows to be shown.
//mMapView.setAllowConcurrentMultipleOpenInfoWindows(true);

mMapView.addMarker(new MarkerOptions()
.title("Intersection")
.snippet("H St NW with 15th St NW")
Expand Down
Loading