mirror of
https://github.com/TeamVanced/VancedMicroG
synced 2025-01-22 00:57:31 +01:00
Add marker onclick support, optimize drawing
This commit is contained in:
parent
3cdf785533
commit
5b9503275e
@ -41,7 +41,9 @@ import org.oscim.map.Viewport;
|
||||
import org.oscim.theme.VtmThemes;
|
||||
import org.oscim.tiling.source.oscimap4.OSciMap4TileSource;
|
||||
|
||||
public class BackendMap {
|
||||
import java.util.HashMap;
|
||||
|
||||
public class BackendMap implements ItemizedLayer.OnItemGestureListener<MarkerItem> {
|
||||
private final static String TAG = "GmsBackendMap";
|
||||
|
||||
private final Context context;
|
||||
@ -51,6 +53,8 @@ public class BackendMap {
|
||||
private final OSciMap4TileSource tileSource;
|
||||
private final TileCache cache;
|
||||
private final ItemizedLayer<MarkerItem> items;
|
||||
private java.util.Map<String, Markup> markupMap = new HashMap<>();
|
||||
private boolean redrawPosted = false;
|
||||
|
||||
public BackendMap(Context context) {
|
||||
this.context = context;
|
||||
@ -65,7 +69,8 @@ public class BackendMap {
|
||||
layers.add(buildings = new BuildingLayer(mapView.map(), baseLayer));
|
||||
layers.add(new LabelLayer(mapView.map(), baseLayer));
|
||||
layers.add(items = new ItemizedLayer<>(mapView.map(), new MarkerSymbol(new AndroidBitmap(BitmapFactory
|
||||
.decodeResource(ResourcesContainer.get(), R.drawable.maps_default_marker)), 0.5F, 1)));
|
||||
.decodeResource(ResourcesContainer.get(), R.drawable.nop)), 0.5F, 1)));
|
||||
items.setOnItemGestureListener(this);
|
||||
mapView.map().setTheme(VtmThemes.DEFAULT);
|
||||
}
|
||||
|
||||
@ -138,9 +143,10 @@ public class BackendMap {
|
||||
mapView.map().animator().cancel();
|
||||
}
|
||||
|
||||
public <T extends Markup> T add(T markup) {
|
||||
public synchronized <T extends Markup> T add(T markup) {
|
||||
switch (markup.getType()) {
|
||||
case MARKER:
|
||||
markupMap.put(markup.getId(), markup);
|
||||
items.addItem(markup.getMarkerItem(context));
|
||||
redraw();
|
||||
break;
|
||||
@ -157,14 +163,16 @@ public class BackendMap {
|
||||
return markup;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
public synchronized void clear() {
|
||||
markupMap.clear();
|
||||
items.removeAllItems();
|
||||
redraw();
|
||||
}
|
||||
|
||||
public void remove(Markup markup) {
|
||||
public synchronized void remove(Markup markup) {
|
||||
switch (markup.getType()) {
|
||||
case MARKER:
|
||||
markupMap.remove(markup.getId());
|
||||
items.removeItem(items.getByUid(markup.getId()));
|
||||
redraw();
|
||||
break;
|
||||
@ -173,7 +181,11 @@ public class BackendMap {
|
||||
}
|
||||
}
|
||||
|
||||
public void update(Markup markup) {
|
||||
public synchronized void update(Markup markup) {
|
||||
if (markup == null || !markup.isValid()) {
|
||||
Log.d(TAG, "Tried to update() invalid markup!");
|
||||
return;
|
||||
}
|
||||
switch (markup.getType()) {
|
||||
case MARKER:
|
||||
// TODO: keep order
|
||||
@ -188,4 +200,20 @@ public class BackendMap {
|
||||
Log.d(TAG, "Unknown markup: " + markup);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onItemSingleTapUp(int index, MarkerItem item) {
|
||||
Markup markup = markupMap.get(item.getUid());
|
||||
if (markup != null) {
|
||||
if (markup.onClick()) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onItemLongPress(int index, MarkerItem item) {
|
||||
// TODO: start drag+drop
|
||||
Log.d(TAG, "onItemLongPress: " + markupMap.get(item.getUid()));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -80,6 +80,7 @@ public class GoogleMapImpl extends IGoogleMapDelegate.Stub
|
||||
|
||||
private int markerCounter = 0;
|
||||
private int circleCounter = 0;
|
||||
private IOnMarkerClickListener onMarkerClickListener;
|
||||
|
||||
public GoogleMapImpl(LayoutInflater inflater, GoogleMapOptions options) {
|
||||
context = inflater.getContext();
|
||||
@ -212,6 +213,8 @@ public class GoogleMapImpl extends IGoogleMapDelegate.Stub
|
||||
@Override
|
||||
public void clear() throws RemoteException {
|
||||
backendMap.clear();
|
||||
circleCounter = 0;
|
||||
markerCounter = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -223,6 +226,22 @@ public class GoogleMapImpl extends IGoogleMapDelegate.Stub
|
||||
public void remove(Markup markup) {
|
||||
backendMap.remove(markup);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onClick(Markup markup) {
|
||||
if (markup instanceof IMarkerDelegate) {
|
||||
if (onMarkerClickListener != null) {
|
||||
try {
|
||||
if (onMarkerClickListener.onMarkerClick((IMarkerDelegate) markup))
|
||||
return true;
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, e);
|
||||
}
|
||||
}
|
||||
// TODO: open InfoWindow
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
Map options
|
||||
@ -321,7 +340,7 @@ public class GoogleMapImpl extends IGoogleMapDelegate.Stub
|
||||
|
||||
@Override
|
||||
public void setOnMarkerClickListener(IOnMarkerClickListener listener) throws RemoteException {
|
||||
|
||||
this.onMarkerClickListener = listener;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -41,7 +41,7 @@ public class BitmapDescriptorFactoryImpl extends IBitmapDescriptorFactoryDelegat
|
||||
|
||||
@Override
|
||||
public IObjectWrapper defaultMarker() throws RemoteException {
|
||||
return ObjectWrapper.wrap(new DefaultBitmapDescriptor());
|
||||
return ObjectWrapper.wrap(DefaultBitmapDescriptor.DEFAULT_DESCRIPTOR);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -19,13 +19,18 @@ package org.microg.gms.maps.bitmap;
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.util.Log;
|
||||
|
||||
import com.google.android.gms.dynamic.IObjectWrapper;
|
||||
import com.google.android.gms.dynamic.ObjectWrapper;
|
||||
import com.google.android.gms.maps.model.BitmapDescriptor;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public class BitmapDescriptorImpl {
|
||||
private BitmapDescriptor descriptor;
|
||||
private boolean loadStarted = false;
|
||||
private Set<Runnable> waitingForLoad = new HashSet<>();
|
||||
|
||||
public BitmapDescriptorImpl(IObjectWrapper remoteObject) {
|
||||
this(new BitmapDescriptor(remoteObject));
|
||||
@ -57,9 +62,13 @@ public class BitmapDescriptorImpl {
|
||||
return null;
|
||||
}
|
||||
|
||||
public synchronized void loadBitmapAsync(final Context context, final Runnable after) {
|
||||
public synchronized boolean loadBitmapAsync(final Context context, Runnable after) {
|
||||
if (getBitmap() != null) {
|
||||
return false;
|
||||
}
|
||||
waitingForLoad.add(after);
|
||||
if (loadStarted)
|
||||
return;
|
||||
return true;
|
||||
loadStarted = true;
|
||||
if (getDescriptor() != null) {
|
||||
new Thread(new Runnable() {
|
||||
@ -67,11 +76,18 @@ public class BitmapDescriptorImpl {
|
||||
public void run() {
|
||||
Log.d("BitmapDescriptor", "Start loading " + getDescriptor());
|
||||
if (getDescriptor().loadBitmap(context) != null) {
|
||||
after.run();
|
||||
Set<Runnable> waitingForLoad;
|
||||
synchronized (BitmapDescriptorImpl.this) {
|
||||
waitingForLoad = BitmapDescriptorImpl.this.waitingForLoad;
|
||||
}
|
||||
for (Runnable after : waitingForLoad) {
|
||||
after.run();
|
||||
}
|
||||
}
|
||||
Log.d("BitmapDescriptor", "Done loading " + getDescriptor());
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -19,36 +19,87 @@ package org.microg.gms.maps.bitmap;
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.ColorFilter;
|
||||
import android.graphics.ColorMatrix;
|
||||
import android.graphics.ColorMatrixColorFilter;
|
||||
import android.graphics.Paint;
|
||||
|
||||
import com.google.android.gms.R;
|
||||
import com.google.android.gms.dynamic.ObjectWrapper;
|
||||
|
||||
import org.microg.gms.maps.ResourcesContainer;
|
||||
|
||||
public class DefaultBitmapDescriptor extends AbstractBitmapDescriptor {
|
||||
private float hue;
|
||||
public static final DefaultBitmapDescriptor DEFAULT_DESCRIPTOR = new DefaultBitmapDescriptor(0);
|
||||
public static final BitmapDescriptorImpl DEFAULT_DESCRIPTOR_IMPL = new BitmapDescriptorImpl(ObjectWrapper.wrap(DEFAULT_DESCRIPTOR));
|
||||
public static final int DEGREES = 360;
|
||||
|
||||
public DefaultBitmapDescriptor() {
|
||||
this(0);
|
||||
}
|
||||
private final float hue;
|
||||
|
||||
public DefaultBitmapDescriptor(float hue) {
|
||||
this.hue = hue;
|
||||
this.hue = hue > 180 ? -DEGREES + hue : hue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bitmap generateBitmap(Context context) {
|
||||
Bitmap source = BitmapFactory
|
||||
.decodeResource(ResourcesContainer.get(), R.drawable.maps_default_marker);
|
||||
Bitmap bitmap = Bitmap
|
||||
.createBitmap(source.getWidth(), source.getHeight(), source.getConfig());
|
||||
float[] hsv = new float[3];
|
||||
for (int x = 0; x < bitmap.getWidth(); x++) {
|
||||
for (int y = 0; y < bitmap.getHeight(); y++) {
|
||||
int pixel = source.getPixel(x, y);
|
||||
Color.colorToHSV(pixel, hsv);
|
||||
hsv[0] = (hsv[0] + hue) % 360;
|
||||
bitmap.setPixel(x, y, Color.HSVToColor(Color.alpha(pixel), hsv));
|
||||
}
|
||||
Bitmap source;
|
||||
if (this == DEFAULT_DESCRIPTOR) {
|
||||
source = BitmapFactory.decodeResource(ResourcesContainer.get(), R.drawable.maps_default_marker);
|
||||
} else {
|
||||
source = DEFAULT_DESCRIPTOR.loadBitmap(context);
|
||||
}
|
||||
if (hue % DEGREES == 0) return source;
|
||||
Paint paint = new Paint();
|
||||
paint.setColorFilter(adjustHue(hue));
|
||||
Bitmap bitmap = Bitmap.createBitmap(source.getWidth(), source.getHeight(), source.getConfig());
|
||||
Canvas canvas = new Canvas(bitmap);
|
||||
canvas.drawBitmap(source, 0, 0, paint);
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a HUE ajustment ColorFilter
|
||||
* <p/>
|
||||
* see http://groups.google.com/group/android-developers/browse_thread/thread/9e215c83c3819953
|
||||
* see http://gskinner.com/blog/archives/2007/12/colormatrix_cla.html
|
||||
*
|
||||
* @param value degrees to shift the hue.
|
||||
*/
|
||||
public static ColorFilter adjustHue(float value) {
|
||||
ColorMatrix cm = new ColorMatrix();
|
||||
adjustHue(cm, value);
|
||||
return new ColorMatrixColorFilter(cm);
|
||||
}
|
||||
|
||||
/**
|
||||
* see http://groups.google.com/group/android-developers/browse_thread/thread/9e215c83c3819953
|
||||
* see http://gskinner.com/blog/archives/2007/12/colormatrix_cla.html
|
||||
*/
|
||||
public static void adjustHue(ColorMatrix cm, float value) {
|
||||
value = cleanValue(value, 180f) / 180f * (float) Math.PI;
|
||||
if (value == 0) {
|
||||
return;
|
||||
}
|
||||
float cosVal = (float) Math.cos(value);
|
||||
float sinVal = (float) Math.sin(value);
|
||||
float lumR = 0.213f;
|
||||
float lumG = 0.715f;
|
||||
float lumB = 0.072f;
|
||||
float[] mat = new float[]{lumR + cosVal * (1 - lumR) + sinVal * (-lumR),
|
||||
lumG + cosVal * (-lumG) + sinVal * (-lumG),
|
||||
lumB + cosVal * (-lumB) + sinVal * (1 - lumB), 0, 0,
|
||||
lumR + cosVal * (-lumR) + sinVal * (0.143f),
|
||||
lumG + cosVal * (1 - lumG) + sinVal * (0.140f),
|
||||
lumB + cosVal * (-lumB) + sinVal * (-0.283f), 0, 0,
|
||||
lumR + cosVal * (-lumR) + sinVal * (-(1 - lumR)),
|
||||
lumG + cosVal * (-lumG) + sinVal * (lumG),
|
||||
lumB + cosVal * (1 - lumB) + sinVal * (lumB),
|
||||
0, 0, 0f, 0f, 0f, 1f, 0f, 0f, 0f, 0f, 0f, 1f};
|
||||
cm.postConcat(new ColorMatrix(mat));
|
||||
}
|
||||
|
||||
protected static float cleanValue(float p_val, float p_limit) {
|
||||
return Math.min(p_limit, Math.max(-p_limit, p_val));
|
||||
}
|
||||
}
|
||||
|
@ -50,6 +50,7 @@ public class CircleImpl extends ICircleDelegate.Stub implements Markup {
|
||||
private CircleLayer layer;
|
||||
private Point point;
|
||||
private float drawRadius;
|
||||
private boolean removed = false;
|
||||
|
||||
public CircleImpl(String id, CircleOptions options, MarkupListener listener) {
|
||||
this.id = id;
|
||||
@ -65,6 +66,9 @@ public class CircleImpl extends ICircleDelegate.Stub implements Markup {
|
||||
@Override
|
||||
public void remove() throws RemoteException {
|
||||
listener.remove(this);
|
||||
removed = true;
|
||||
layer.setEnabled(false);
|
||||
layer = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -158,6 +162,16 @@ public class CircleImpl extends ICircleDelegate.Stub implements Markup {
|
||||
return id.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onClick() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid() {
|
||||
return !removed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MarkerItem getMarkerItem(Context context) {
|
||||
return null;
|
||||
|
@ -20,12 +20,15 @@ import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.os.RemoteException;
|
||||
import android.util.Log;
|
||||
|
||||
import com.google.android.gms.dynamic.IObjectWrapper;
|
||||
import com.google.android.gms.maps.model.LatLng;
|
||||
import com.google.android.gms.maps.model.MarkerOptions;
|
||||
import com.google.android.gms.maps.model.internal.IMarkerDelegate;
|
||||
|
||||
import org.microg.gms.maps.GmsMapsTypeHelper;
|
||||
import org.microg.gms.maps.bitmap.BitmapDescriptorImpl;
|
||||
import org.microg.gms.maps.bitmap.DefaultBitmapDescriptor;
|
||||
import org.oscim.android.canvas.AndroidBitmap;
|
||||
import org.oscim.layers.Layer;
|
||||
import org.oscim.layers.marker.MarkerItem;
|
||||
@ -39,6 +42,8 @@ public class MarkerImpl extends IMarkerDelegate.Stub implements Markup {
|
||||
private final MarkerOptions options;
|
||||
private final MarkupListener listener;
|
||||
private BitmapDescriptorImpl icon;
|
||||
private AndroidBitmap oldBitmap;
|
||||
private boolean removed = false;
|
||||
|
||||
public MarkerImpl(String id, MarkerOptions options, MarkupListener listener) {
|
||||
this.id = id;
|
||||
@ -55,6 +60,9 @@ public class MarkerImpl extends IMarkerDelegate.Stub implements Markup {
|
||||
@Override
|
||||
public void remove() {
|
||||
listener.remove(this);
|
||||
removed = true;
|
||||
icon = null;
|
||||
oldBitmap = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -200,27 +208,49 @@ public class MarkerImpl extends IMarkerDelegate.Stub implements Markup {
|
||||
return bitmap.getHeight();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onClick() {
|
||||
return listener.onClick(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid() {
|
||||
return !removed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MarkerItem getMarkerItem(Context context) {
|
||||
MarkerItem item = new MarkerItem(getId(), getTitle(), getSnippet(),
|
||||
GmsMapsTypeHelper.fromLatLng(getPosition()));
|
||||
if (icon != null) {
|
||||
if (icon.getBitmap() != null) {
|
||||
item.setMarker(
|
||||
new MarkerSymbol(new AndroidBitmap(icon.getBitmap()), options.getAnchorU(),
|
||||
options.getAnchorV(), !options.isFlat()));
|
||||
} else {
|
||||
icon.loadBitmapAsync(context, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
listener.update(MarkerImpl.this);
|
||||
}
|
||||
});
|
||||
BitmapDescriptorImpl icon = this.icon;
|
||||
if (icon == null)
|
||||
icon = DefaultBitmapDescriptor.DEFAULT_DESCRIPTOR_IMPL;
|
||||
if (icon.getBitmap() != null) {
|
||||
oldBitmap = new AndroidBitmap(icon.getBitmap());
|
||||
prepareMarkerIcon(item);
|
||||
} else {
|
||||
if (!icon.loadBitmapAsync(context, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
listener.update(MarkerImpl.this);
|
||||
}
|
||||
})) {
|
||||
// Was loaded since last check...
|
||||
oldBitmap = new AndroidBitmap(icon.getBitmap());
|
||||
prepareMarkerIcon(item);
|
||||
}
|
||||
// Keep old icon while loading new
|
||||
if (oldBitmap != null) {
|
||||
prepareMarkerIcon(item);
|
||||
}
|
||||
}
|
||||
return item;
|
||||
}
|
||||
|
||||
private void prepareMarkerIcon(MarkerItem item) {
|
||||
item.setMarker(new MarkerSymbol(oldBitmap, options.getAnchorU(), options.getAnchorV(), !options.isFlat()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Layer getLayer(Context context, Map map) {
|
||||
return null;
|
||||
|
@ -31,6 +31,10 @@ public interface Markup {
|
||||
|
||||
public String getId();
|
||||
|
||||
public boolean onClick();
|
||||
|
||||
public boolean isValid();
|
||||
|
||||
public static enum Type {
|
||||
MARKER, LAYER
|
||||
}
|
||||
@ -39,5 +43,7 @@ public interface Markup {
|
||||
void update(Markup markup);
|
||||
|
||||
void remove(Markup markup);
|
||||
|
||||
boolean onClick(Markup markup);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user