Setting listeners to groups of markers using Google Maps API - google-maps-markers

I am working on an Android app where the Google Map has markers for different categories of locations. For instance, collection of markers for places to visit near the current location and collection of markers for places visited so far.
I found that all the markers on the map can be set with Listeners using
GoogleMap.setOnMarkerClickListener(OnMarkerClickListener)
However, I have a collection of Markers
ArrayList<Marker> markerList1
ArrayList<Marker> markerList2
and I want to set markers in markerList1 with one Listener and markers in markerList2 with other Listener. Please help me get to the best way to do this.

If you only have two such lists, a direct way would be to do
if (markerList1.contains(marker)) {
doFirstAction(marker);
} else {
doSecondAction(marker);
}
inside onMarkerClick.
However contains is a linear search, so if the amount of markers in a single list is large and you have more than two categories or the amount of categories might change in the future, I suggest switching to a single Map instead, e.g.
private Map<Marker, OnMarkerClickListener> allMarkers;
// in onCreate
OnMarkerClickListener firstActionListener = new ...
OnMarkerClickListener secondActionListener = new ...
Marker marker = ...
allMarkers.put(marker, firstActionListener);
// in global onMarkerClickListener
return allMarkers.get(marker).onMarkerClick(marker);
This way you have your separate listeners, code is optimal and adheres to the open/closed principle: if you add new category, you don't change existing code.

The method OnMarkerClickListener is set for a map object and cannot be set at marker or marker group level. This means the same public boolean onMarkerClick(final Marker marker) will be triggered on clicking any marker on the map.
Now to handle the clicks for different types of markers, you need to use an if else logic within this function. You can identify to which group a marker belongs by possibly checking for some string match in details like marker.getTitle() or marker.getSnippet() or by checking a hashmap or sqlite db entry that contains more details on a marker.

Related

Bing Maps V8 - How can I rotate map in Bird's Eye view?

I am upgrading from Bing Maps V7 to V8 and rotating the map from JS doesn't work anymore. I have been trying with this piece of code:
map.setView( { heading:90 } );
This works if I change the source URL for the map library to V7. And I see that the "setView" function and the "heading" option still exist in V8.
Here's an article about how to do it in V7:
https://alastaira.wordpress.com/2012/03/28/rotating-bing-maps/
Bing Maps V8 currently doesn't have Birdseye. A new birdseye experience is being introduced to V8 within the next few months. This new experience has a lot of new imagery which uses a different format from the old birdseye experience. Given that the imagery that is in V7 is very old and is a major point of DSAT, it was decided to hold off on adding birdseye to V8 until the next experience and data is available.
I did some more research and two undocumented things have changed.
map.setView() does not respond to a full options object anymore.
Example:
var options = this.map.getOptions();
options.heading = 90;
map.setView(options);
It now needs the heading and other changed fields manually specified to reflect any changes.
map.setView({heading: 90});
map.setView({heading: xx}) no longer accepts negative values as valid so you must manually submit heading values for any clockwise rotations so that it corresponds to the positive heading value.
Thus, map.setView({heading: -90}) was previously smart enough to know that is equivalent to map.setView({heading: 270}), but now must be submitted to the API as a positive value.
Similar to the first example, I have some legacy code for resetting the map back to original lat/lon and heading that now needs a second setView() call in order to update.
var options = this.map.getOptions();
options.zoom = this.initialZoom;
options.center = new Microsoft.Maps.Location(this.lat, this.lon);
options.heading = this.heading = 0;
this.map.setView(options);
this.map.setView({heading: this.heading});
Must call setView another time so that the new heading is actually applied.

Split node.js event stream based on unique id in event body

I have a node.js-based location service that produces events as users move about, and I want to use RxJS to process these events and look for arbitrarily complex patterns like a user enters a region and visits 2 points of interest within 1 hour.
To begin with I need to split the stream of events base on unique user ids (from event body), but I am not finding any stock RxJS functions that will do this.
filter() would require that all uuids be known beforehand which is not desirable.
groupBy() looks like it would need to process the entire sequence prior to returning the grouped observables, which is not possible.
I'm thinking that maybe I need to build a custom observable that maintains a map of uuids to observables, and instantiate new observables as required. Each of these observables would then need to undergo identical processing in search of the pattern match, and ultimately trigger some action when a user's movements match the pattern. One of the obvious challenges here is I have a dynamically growing map of observables being produced as user enter the system and move about.
Any ideas how something like this could be achieved with RxJS?
I think you are misunderstanding how groupBy() works. It will generate a new Observable every time a new key is generated, and if the key already exists, it will just be pushed to the existing Observable.
So for your problem it should look something like this:
var source = getLocationEvents();
var disposable = new Rx.CompositeDisposable();
disposable.add(
source.groupBy(function(x) { return x.userid; })
.map(function(x) {
return x.map(function(ev) { /*Process the the event*/ });
})
.subscribe(function(group) {
disposable.add(group.subscribe(/*Do something with the event*/));
});

In Local Datastore chapter, fromPin and fromlocaldatastore

Just like as title, I want to ask what difference between
fromPin()
and
fromLocalDatastore()
By the way, Pin and datastore two terminologies. What difference between two of them ?
Thanks.
There is a slight difference and you can see it from the docs and from the decompiled code of the Parse library (okay, this last one is more complicated...).
The docs says:
fromLocalDatastore(): Change the source of this query to all pinned objects.
fromPin(): Change the source of this query to the default group of pinned objects.
Here you can see that, interally on Parse, there is a way to get all the objects from the entire set of pinned data, without filters, but also from a so-called "default group". This group is defined in the Parse code with the following string: _default (o'rly?).
When you pin something using pinInBackground, you can do it in different ways:
pinInBackground() [without arguments]: Stores the object and every object it points to in the local datastore.
This is what the docs say, but if you look at the code you'll discover that the pin will be actually performed to the... _default group!
public Task<Void> pinInBackground() {
return pinAllInBackground("_default", Arrays.asList(new ParseObject[] { this }));
}
On the other hand, you can always call pinInBackground(String group) to specify a precise group.
Conclusion: every time you pin an object, it's guaranteed to be pinned to a certain group. The group is "_default" if you don't specify anything in the parameters. If you pin an object to your custom group "G", then a query using fromPin() will not find it! Because you didn't put it on "_default", but "G".
Instead, using fromLocalDatastore(), the query is guaranteed to find your object because it will search into "_default", "G" and so on.

jVectorMap define data series on the fly

What I am trying to do and is failing is this:
worldMap.series.regions[0]=new jvm.DataSeries({
scale:['#CCCCCC','#FF0000'],
normalizeFunction:'polynomial',
values:{'country_code':value...},
min:minValue,
max:maxValue
});
The error I get is that regions is not defined, so I'm doing that wrong.
What is the proper way of doing that and how can I dispose of data if I don't need it anymore (as in remove colouring of countries as if map was initialized with empty dataset).
Thank you.
If all you want to do is to change series data then you can use DataSeries methods like clear and setValues:
worldMap.series.regions[0].clear();

Smartgwt : localfiltering on a selectItem

I have a Rpc Datasource providing a list of objects. I have two selectItem databound to this datasource but each showing a different attribute.
For one of these attributes I have a duplicate value which are enabled by design.
However in the SelectItem related to this field I would like to remove duplicate to simplify the user choice(reduce the list length and also it seems strange to have double values..)
I think I can arrived to do it using lodal filtering but I cannot find the point to start to write the right citeria.

Resources