mirror of
https://github.com/TeamVanced/VancedMicroG
synced 2025-01-22 09:07:32 +01:00
Add InfoWindow support
This commit is contained in:
parent
2751bdac1c
commit
e77a08ece4
BIN
res/drawable-xhdpi/maps_default_window.9.png
Normal file
BIN
res/drawable-xhdpi/maps_default_window.9.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.3 KiB |
@ -1,4 +1,9 @@
|
||||
package com.google.android.gms.maps.internal;
|
||||
|
||||
import com.google.android.gms.dynamic.IObjectWrapper;
|
||||
import com.google.android.gms.maps.model.internal.IMarkerDelegate;
|
||||
|
||||
interface IInfoWindowAdapter {
|
||||
IObjectWrapper getInfoWindow(IMarkerDelegate marker);
|
||||
IObjectWrapper getInfoContents(IMarkerDelegate marker);
|
||||
}
|
||||
|
@ -1,4 +1,7 @@
|
||||
package com.google.android.gms.maps.internal;
|
||||
|
||||
import com.google.android.gms.maps.model.internal.IMarkerDelegate;
|
||||
|
||||
interface IOnInfoWindowClickListener {
|
||||
void onInfoWindowClick(IMarkerDelegate marker);
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.RelativeLayout;
|
||||
import com.google.android.gms.dynamic.IObjectWrapper;
|
||||
import com.google.android.gms.dynamic.ObjectWrapper;
|
||||
import com.google.android.gms.maps.GoogleMapOptions;
|
||||
@ -49,44 +49,104 @@ public class GoogleMapImpl {
|
||||
|
||||
private final ViewGroup view;
|
||||
private final GoogleMapOptions options;
|
||||
|
||||
private final Delegate delegate = new Delegate();
|
||||
private final UiSettings uiSettings = new UiSettings();
|
||||
private final Projection projection = new Projection();
|
||||
private MapView mapView;
|
||||
private int mapType = 1;
|
||||
|
||||
private MapView mapView;
|
||||
private Context context;
|
||||
private InfoWindow infoWindow;
|
||||
private int markerCounter = 0;
|
||||
|
||||
private IOnCameraChangeListener cameraChangeListener;
|
||||
private IOnMapClickListener mapClickListener;
|
||||
private IOnMapLoadedCallback mapLoadedCallback;
|
||||
private IOnMapLongClickListener mapLongClickListener;
|
||||
private IOnMarkerClickListener markerClickListener;
|
||||
public GoogleMapImpl(LayoutInflater inflater, GoogleMapOptions options) {
|
||||
private IOnMarkerDragListener markerDragListener;
|
||||
private IOnInfoWindowClickListener infoWindowClickListener;
|
||||
|
||||
private int mapType = 1;
|
||||
private IInfoWindowAdapter infoWindowAdapter;
|
||||
|
||||
public GoogleMapImpl(LayoutInflater inflater, GoogleMapOptions options) {
|
||||
context = inflater.getContext();
|
||||
this.view = new FrameLayout(context);
|
||||
try {
|
||||
mapView = (MapView) Class.forName("com.google.android.maps.MapView").getConstructor(Context.class, String.class).newInstance(context, null);
|
||||
view.addView(mapView);
|
||||
} catch (Exception e) {
|
||||
Log.d(TAG, "Sorry, can't create legacy MapView");
|
||||
}
|
||||
this.view = new RelativeLayout(context);
|
||||
try {
|
||||
mapView = (MapView) Class.forName("com.google.android.maps.MapView").getConstructor(Context.class, String.class).newInstance(context, null);
|
||||
prepareMapView();
|
||||
view.addView(mapView);
|
||||
} catch (Exception e) {
|
||||
Log.d(TAG, "Sorry, can't create legacy MapView");
|
||||
}
|
||||
this.options = options;
|
||||
}
|
||||
|
||||
private void prepareMapView() {
|
||||
mapView.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
Log.d(TAG, "onClick");
|
||||
IOnMapClickListener listener = mapClickListener;
|
||||
if (listener != null) {
|
||||
try {
|
||||
// TODO: Handle LatLng right
|
||||
listener.onMapClick(new LatLng(0, 0));
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
mapView.setOnLongClickListener(new View.OnLongClickListener() {
|
||||
@Override
|
||||
public boolean onLongClick(View v) {
|
||||
Log.d(TAG, "onLongClick");
|
||||
IOnMapLongClickListener listener = mapLongClickListener;
|
||||
if (listener != null) {
|
||||
try {
|
||||
// TODO: Handle LatLng right
|
||||
listener.onMapLongClick(new LatLng(0, 0));
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, e);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
try {
|
||||
delegate.animateCamera(new CameraUpdateFactoryImpl().newCameraPosition(options.getCamera()));
|
||||
delegate.setMapType(options.getMapType());
|
||||
uiSettings.setCompassEnabled(options.isCompassEnabled());
|
||||
uiSettings.setZoomControlsEnabled(options.isZoomControlsEnabled());
|
||||
uiSettings.setRotateGesturesEnabled(options.isRotateGesturesEnabled());
|
||||
uiSettings.setScrollGesturesEnabled(options.isScrollGesturesEnabled());
|
||||
uiSettings.setTiltGesturesEnabled(options.isTiltGesturesEnabled());
|
||||
uiSettings.setZoomGesturesEnabled(options.isZoomGesturesEnabled());
|
||||
} catch (RemoteException ignored) {
|
||||
// It's not remote...
|
||||
if (options != null) {
|
||||
try {
|
||||
delegate.animateCamera(new CameraUpdateFactoryImpl().newCameraPosition(options.getCamera()));
|
||||
delegate.setMapType(options.getMapType());
|
||||
uiSettings.setCompassEnabled(options.isCompassEnabled());
|
||||
uiSettings.setZoomControlsEnabled(options.isZoomControlsEnabled());
|
||||
uiSettings.setRotateGesturesEnabled(options.isRotateGesturesEnabled());
|
||||
uiSettings.setScrollGesturesEnabled(options.isScrollGesturesEnabled());
|
||||
uiSettings.setTiltGesturesEnabled(options.isTiltGesturesEnabled());
|
||||
uiSettings.setZoomGesturesEnabled(options.isZoomGesturesEnabled());
|
||||
} catch (RemoteException ignored) {
|
||||
// It's not remote...
|
||||
}
|
||||
}
|
||||
}
|
||||
if (savedInstanceState != null) {
|
||||
savedInstanceState.setClassLoader(GoogleMapImpl.class.getClassLoader());
|
||||
mapView.onRestoreInstanceState(savedInstanceState);
|
||||
}
|
||||
}
|
||||
|
||||
public IOnMarkerClickListener getMarkerClickListener() {
|
||||
return markerClickListener;
|
||||
}
|
||||
|
||||
public IOnInfoWindowClickListener getInfoWindowClickListener() {
|
||||
return infoWindowClickListener;
|
||||
}
|
||||
|
||||
public Context getContext() {
|
||||
return context;
|
||||
}
|
||||
@ -108,8 +168,15 @@ public class GoogleMapImpl {
|
||||
}
|
||||
|
||||
public void remove(MarkerImpl marker) {
|
||||
mapView.getOverlays().remove(marker);
|
||||
}
|
||||
mapView.getOverlays().remove(marker.getOverlay());
|
||||
try {
|
||||
if (infoWindow != null && infoWindow.getMarker().getId().equals(marker.getId())) {
|
||||
hideInfoWindow();
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
// It's not remote...
|
||||
}
|
||||
}
|
||||
|
||||
public void redraw() {
|
||||
mapView.postInvalidate();
|
||||
@ -120,6 +187,49 @@ public class GoogleMapImpl {
|
||||
}
|
||||
}
|
||||
|
||||
public void onSaveInstanceState(Bundle outState) {
|
||||
mapView.onSaveInstanceState(outState);
|
||||
}
|
||||
|
||||
public void hideInfoWindow() {
|
||||
if (infoWindow != null) {
|
||||
mapView.getOverlays().remove(infoWindow);
|
||||
infoWindow.destroy();
|
||||
}
|
||||
infoWindow = null;
|
||||
}
|
||||
|
||||
public void showInfoWindow(final MarkerImpl marker) {
|
||||
hideInfoWindow();
|
||||
InfoWindow window = new InfoWindow(context, this, marker);
|
||||
if (infoWindowAdapter != null) {
|
||||
try {
|
||||
IObjectWrapper infoWindow = infoWindowAdapter.getInfoWindow(marker);
|
||||
window.setWindow((View) ObjectWrapper.unwrap(infoWindow));
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, e);
|
||||
}
|
||||
}
|
||||
if (!window.isComplete()) {
|
||||
if (infoWindowAdapter != null) {
|
||||
try {
|
||||
IObjectWrapper contents = infoWindowAdapter.getInfoContents(marker);
|
||||
window.setContent((View) ObjectWrapper.unwrap(contents));
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!window.isComplete()) {
|
||||
window.buildDefault();
|
||||
}
|
||||
if (window.isComplete()) {
|
||||
infoWindow = window;
|
||||
Log.d(TAG, "Showing info window " + infoWindow + " for marker " + marker);
|
||||
mapView.getOverlays().add(infoWindow);
|
||||
}
|
||||
}
|
||||
|
||||
private class Delegate extends IGoogleMapDelegate.Stub {
|
||||
@Override
|
||||
public CameraPosition getCameraPosition() throws RemoteException {
|
||||
@ -176,8 +286,10 @@ public class GoogleMapImpl {
|
||||
|
||||
@Override
|
||||
public IMarkerDelegate addMarker(MarkerOptions options) throws RemoteException {
|
||||
MarkerImpl marker = new MarkerImpl(options, GoogleMapImpl.this);
|
||||
mapView.getOverlays().add(marker.getOverlay());
|
||||
MarkerImpl marker = new MarkerImpl("m" + markerCounter++, options, GoogleMapImpl.this);
|
||||
if (infoWindow != null) mapView.getOverlays().remove(infoWindow);
|
||||
mapView.getOverlays().add(marker.getOverlay());
|
||||
if (infoWindow != null) mapView.getOverlays().add(infoWindow);
|
||||
redraw();
|
||||
return marker;
|
||||
}
|
||||
@ -195,6 +307,7 @@ public class GoogleMapImpl {
|
||||
@Override
|
||||
public void clear() throws RemoteException {
|
||||
mapView.getOverlays().clear();
|
||||
hideInfoWindow();
|
||||
redraw();
|
||||
}
|
||||
|
||||
@ -265,38 +378,18 @@ public class GoogleMapImpl {
|
||||
|
||||
@Override
|
||||
public void setOnCameraChangeListener(IOnCameraChangeListener listener) throws RemoteException {
|
||||
|
||||
}
|
||||
cameraChangeListener = listener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOnMapClickListener(final IOnMapClickListener listener) throws RemoteException {
|
||||
mapView.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
try {
|
||||
Log.d(TAG, "onMapClick:");
|
||||
listener.onMapClick(new LatLng(0, 0));
|
||||
} catch (RemoteException ignored) {
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
mapClickListener = listener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOnMapLongClickListener(final IOnMapLongClickListener listener) throws RemoteException {
|
||||
mapView.setOnLongClickListener(new View.OnLongClickListener() {
|
||||
@Override
|
||||
public boolean onLongClick(View v) {
|
||||
try {
|
||||
Log.d(TAG, "onMapLongClick:");
|
||||
listener.onMapLongClick(new LatLng(0, 0));
|
||||
} catch (RemoteException e) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
mapLongClickListener = listener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOnMarkerClickListener(IOnMarkerClickListener listener) throws RemoteException {
|
||||
@ -305,18 +398,18 @@ public class GoogleMapImpl {
|
||||
|
||||
@Override
|
||||
public void setOnMarkerDragListener(IOnMarkerDragListener listener) throws RemoteException {
|
||||
|
||||
}
|
||||
markerDragListener = listener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOnInfoWindowClickListener(IOnInfoWindowClickListener listener) throws RemoteException {
|
||||
|
||||
}
|
||||
infoWindowClickListener = listener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setInfoWindowAdapter(IInfoWindowAdapter adapter) throws RemoteException {
|
||||
|
||||
}
|
||||
infoWindowAdapter = adapter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IObjectWrapper getTestingHelper() throws RemoteException {
|
||||
@ -360,9 +453,9 @@ public class GoogleMapImpl {
|
||||
|
||||
@Override
|
||||
public void setOnMapLoadedCallback(IOnMapLoadedCallback callback) throws RemoteException {
|
||||
|
||||
}
|
||||
}
|
||||
mapLoadedCallback = callback;
|
||||
}
|
||||
}
|
||||
|
||||
private class UiSettings extends IUiSettingsDelegate.Stub {
|
||||
|
||||
|
@ -104,7 +104,7 @@ public class MapFragmentImpl extends IMapFragmentDelegate.Stub {
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(Bundle outState) throws RemoteException {
|
||||
|
||||
myMap().onSaveInstanceState(outState);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -100,6 +100,14 @@ public class CameraUpdateFactoryImpl extends ICameraUpdateFactoryDelegate.Stub {
|
||||
@Override
|
||||
public IObjectWrapper newCameraPosition(final CameraPosition cameraPosition) throws RemoteException {
|
||||
Log.d(TAG, "newCameraPosition");
|
||||
if (cameraPosition == null) {
|
||||
return new ObjectWrapper<CameraUpdate>(new CameraUpdate() {
|
||||
@Override
|
||||
public void update(GoogleMapImpl map) {
|
||||
// Nothing
|
||||
}
|
||||
});
|
||||
}
|
||||
return newLatLngZoom(cameraPosition.target, cameraPosition.zoom);
|
||||
}
|
||||
|
||||
|
161
src/org/microg/gms/maps/markup/InfoWindow.java
Normal file
161
src/org/microg/gms/maps/markup/InfoWindow.java
Normal file
@ -0,0 +1,161 @@
|
||||
/*
|
||||
* Copyright (c) 2014 μg Project Team
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.microg.gms.maps.markup;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.Rect;
|
||||
import android.os.RemoteException;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
import com.google.android.gms.R;
|
||||
import com.google.android.gms.maps.internal.IOnInfoWindowClickListener;
|
||||
import com.google.android.gms.maps.model.internal.IMarkerDelegate;
|
||||
import com.google.android.maps.GeoPoint;
|
||||
import com.google.android.maps.MapView;
|
||||
import com.google.android.maps.Overlay;
|
||||
import org.microg.gms.maps.GoogleMapImpl;
|
||||
import org.microg.gms.maps.ResourcesContainer;
|
||||
|
||||
public class InfoWindow extends Overlay {
|
||||
private static final String TAG = InfoWindow.class.getName();
|
||||
private Context context;
|
||||
private View window;
|
||||
private GoogleMapImpl map;
|
||||
private MarkerImpl marker;
|
||||
|
||||
public InfoWindow(Context context, final GoogleMapImpl map, final MarkerImpl marker) {
|
||||
super();
|
||||
this.context = context;
|
||||
this.map = map;
|
||||
this.marker = marker;
|
||||
}
|
||||
|
||||
public void setWindow(View view) {
|
||||
window = view;
|
||||
if (window != null) {
|
||||
window.measure(0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isComplete() {
|
||||
return window != null;
|
||||
}
|
||||
|
||||
public void setContent(View view) {
|
||||
if (view == null) return;
|
||||
setWindow(new DefaultWindow(view));
|
||||
}
|
||||
|
||||
public void buildDefault() {
|
||||
try {
|
||||
if (marker.getTitle() != null)
|
||||
setContent(new DefaultContent());
|
||||
} catch (RemoteException e) {
|
||||
// Not remote...
|
||||
}
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
if (window instanceof DefaultWindow) {
|
||||
((DefaultWindow) window).removeAllViews();
|
||||
}
|
||||
}
|
||||
|
||||
public IMarkerDelegate getMarker() {
|
||||
return marker;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Canvas canvas, MapView mapView, boolean shadow) {
|
||||
if (window != null && marker.getHeight() != -1) {
|
||||
try {
|
||||
Point zero = mapView.getProjection().toPixels(new GeoPoint(0, 0), null);
|
||||
Point point = mapView.getProjection().toPixels(marker.getPosition().toGeoPoint(), null);
|
||||
point.offset(-zero.x, -zero.y);
|
||||
point.offset(-window.getMeasuredWidth() / 2, -window.getMeasuredHeight() - marker.getHeight());
|
||||
Log.d(TAG, point.toString());
|
||||
window.layout(0, 0, window.getMeasuredWidth(), window.getMeasuredHeight());
|
||||
canvas.save();
|
||||
canvas.translate(point.x, point.y);
|
||||
window.draw(canvas);
|
||||
canvas.restore();
|
||||
} catch (RemoteException e) {
|
||||
// This is not remote...
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTap(GeoPoint p, MapView mapView) {
|
||||
try {
|
||||
IOnInfoWindowClickListener listener = map.getInfoWindowClickListener();
|
||||
if (listener != null) {
|
||||
Point clickPoint = mapView.getProjection().toPixels(p, null);
|
||||
Point markerPoint = mapView.getProjection().toPixels(marker.getPosition().toGeoPoint(), null);
|
||||
Rect rect = new Rect(markerPoint.x - (window.getMeasuredWidth() / 2),
|
||||
markerPoint.y - marker.getHeight() - window.getMeasuredHeight(),
|
||||
markerPoint.x + (window.getMeasuredWidth() / 2),
|
||||
markerPoint.y - marker.getHeight());
|
||||
if (rect.contains(clickPoint.x, clickPoint.y)) {
|
||||
try {
|
||||
listener.onInfoWindowClick(marker);
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, e);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
// This is not remote...
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private class DefaultWindow extends FrameLayout {
|
||||
public DefaultWindow(View view) {
|
||||
super(context);
|
||||
addView(view);
|
||||
setBackground(ResourcesContainer.get().getDrawable(R.drawable.maps_default_window));
|
||||
}
|
||||
}
|
||||
|
||||
private class DefaultContent extends LinearLayout {
|
||||
public DefaultContent() {
|
||||
super(context);
|
||||
setOrientation(LinearLayout.VERTICAL);
|
||||
try {
|
||||
TextView title = new TextView(context);
|
||||
title.setTextAppearance(context, android.R.style.TextAppearance_DeviceDefault_Medium_Inverse);
|
||||
title.setText(marker.getTitle());
|
||||
addView(title);
|
||||
if (marker.getSnippet() != null) {
|
||||
TextView snippet = new TextView(context);
|
||||
snippet.setTextAppearance(context, android.R.style.TextAppearance_DeviceDefault_Inverse);
|
||||
snippet.setText(marker.getSnippet());
|
||||
addView(snippet);
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
// ...
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -35,10 +35,11 @@ import org.microg.gms.maps.GoogleMapImpl;
|
||||
public class MarkerImpl extends IMarkerDelegate.Stub {
|
||||
private static final String TAG = MarkerImpl.class.getName();
|
||||
|
||||
private final String id;
|
||||
|
||||
private float alpha;
|
||||
private boolean flat;
|
||||
private boolean draggable;
|
||||
private String id = Integer.toHexString(hashCode());
|
||||
private LatLng position;
|
||||
private float anchorU;
|
||||
private float anchorV;
|
||||
@ -74,7 +75,7 @@ public class MarkerImpl extends IMarkerDelegate.Stub {
|
||||
}
|
||||
if (!result) {
|
||||
mapView.getController().animateTo(position.toGeoPoint());
|
||||
// TODO info window
|
||||
map.showInfoWindow(MarkerImpl.this);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -109,7 +110,8 @@ public class MarkerImpl extends IMarkerDelegate.Stub {
|
||||
}
|
||||
};
|
||||
|
||||
public MarkerImpl(MarkerOptions options, GoogleMapImpl map) {
|
||||
public MarkerImpl(String id, MarkerOptions options, GoogleMapImpl map) {
|
||||
this.id = id;
|
||||
this.map = map;
|
||||
this.alpha = options.getAlpha();
|
||||
this.draggable = options.isDraggable();
|
||||
@ -124,7 +126,7 @@ public class MarkerImpl extends IMarkerDelegate.Stub {
|
||||
this.icon = options.getIcon();
|
||||
if (icon == null)
|
||||
icon = new BitmapDescriptor(new ObjectWrapper<DefaultBitmapDescriptor>(new DefaultBitmapDescriptor(0)));
|
||||
Log.d(TAG, "New: " + title + " @ " + position + ", " + icon);
|
||||
Log.d(TAG, "New: " + id + " with title " + title + " @ " + position);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -267,4 +269,10 @@ public class MarkerImpl extends IMarkerDelegate.Stub {
|
||||
public Overlay getOverlay() {
|
||||
return overlay;
|
||||
}
|
||||
|
||||
public int getHeight() {
|
||||
Bitmap bitmap = icon.getBitmap();
|
||||
if (bitmap == null) return -1;
|
||||
return bitmap.getHeight();
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user