Osmdroid: show and hide markers description on click - java

I am programming an app in Java using Android Studio.
I already displayed a map using osmdroid, added some overlays to display markers on special locations and added a title & a description to the markers.
Now I display the title & description of the marker on click using the setFocusItemsOnTap method.
My problem is that I am not able to hide the title & description of the marker on a second click (so if its already shown). Is there any way to do this?
Or if thats not possible is there a way to only display the title & description of one marker at once using the setFocusItemsOnTab methode?
public static List<OverlayItem> items = new ArrayList<OverlayItem>();
//[...]
items.add(new OverlayItem("uid1","Title", "Description", new GeoPoint(51.398,6.875)));
//[...]
List<OverlayItem> currentList;
currentList = new ArrayList<OverlayItem>();
currentList.add(items.get(i));
//[...]
final ItemizedOverlayWithFocus<OverlayItem> mOverlay = new ItemizedOverlayWithFocus<OverlayItem>(this, currentList, new ItemizedIconOverlay.OnItemGestureListener<OverlayItem>() {
#Override
public boolean onItemSingleTapUp(final int index, final OverlayItem item) {
//here it should decide if the title & description is already shown or not. (true => hide it, false => display it)
return true;
}
#Override
public boolean onItemLongPress(final int index, final OverlayItem item) {
return false;
}
});
mOverlay.setFocusItemsOnTap(true);
I have to use these parts of the code, because i wanted to add different markers and i wanted to be able to focus all of them. Also i need to be able to add them to a dynamic list during runtime.
Thanks for your help!

If you're sticking with ItemizedIconOverlay, I believe you can only have one popup at a time. You would have to subclass ItemizedIconOverlay and override the draw method to support rendering popups for multiple items at a time.
I think you'll have better luck with the Marker class. It already supports the click to close function. Again, only a single marker popup can be displayed at a time. This can be overridden by supplying your own InfoWindow instances for each marker.

Related

osmbonuspack: unable to assign each marker its own style in kml structure

I'm developing an Android application using osmdroid and osmbonus pack libraries which allows the user to drag and drop icons to the map from a menu.
The application is intended to allow the user to "save the map", so i'm trying to manage how to save all the dragged markers in a kml document, and than loading it when necessary.
I've tried following the 13.3 tutorial https://github.com/MKergall/osmbonuspack/wiki/Tutorial_4 , but i still can't figure it out, so i'm probably missing something.
I created a class for the insert of the markers in the map, with this method:
public void insertIcon(int image) throws IOException {
marker = new Marker(map);
point = new GeoPoint(currentLocation);
marker.setPosition(point);
marker.setAnchor(Marker.ANCHOR_CENTER, Marker.ANCHOR_BOTTOM);
map.getOverlays().add(marker);
map.invalidate();
applyDraggableListener(marker);
marker.setIcon(activity.getDrawable(image));
}
And then once the marker is dragged in a certain position, i add it to the kml structure:
...
public void onMarkerDragEnd(Marker marker) {
GeoPoint geopoint = marker.getPosition();
//poiMarker.setDraggable(false);
Utilities.kmlDocument.mKmlRoot.addOverlay(marker, Utilities.kmlDocument);
}
...
At this point, i don't know how to assign to that specific marker its specific style, which is basically just the icon.
I've made several tests inside the MyKmlStyler, but the main point of the problem is in fact that i don't know how distinguish between each kmlPlacemark.
Inside the method onPoint of MyKmlStyler i put a println and obviously all the placemarks have the same style.
#Override
public void onPoint(Marker marker, KmlPlacemark kmlPlacemark, KmlPoint kmlPoint) {
System.out.println(kmlPlacemark);
}
The only thing i'm able to do is giving a unique style to all the markers dragged.
I've already tried with putStyle and the other ways described in the tutorial, but as i've already said, most likely i'm missing something.
My goal is to give each kmlPlacemark a different style according to what the real icon of the marker the user dragged is, all inside the same kmlDocument.
Edit
I thought i managed to find a solution this way:
public void onMarkerDragEnd(Marker marker) {
/*GeoPoint geopoint = marker.getPosition();
poiMarker.setDraggable(false);
*/
KmlDocument mKmlDocument = new KmlDocument();
KmlPlacemark p = new KmlPlacemark(marker);
Style s = buildStyle();
p.mStyle = mKmlDocument.addStyle(s);
mKmlDocument.mKmlRoot.add(p);
mKmlOverlay = (FolderOverlay) mKmlDocument.mKmlRoot.buildOverlay(map, null, null, mKmlDocument);
Utilities.kmlDocument.mKmlRoot.addOverlay(mKmlOverlay, Utilities.kmlDocument);
}
private Style buildStyle(){
Drawable defaultMarker = AppCompatResources.getDrawable(activity, R.drawable.person);
Bitmap defaultBitmap = ((BitmapDrawable) defaultMarker).getBitmap();
return new Style(defaultBitmap, 0x901010AA, 3.0f, 0x20AA1010);
}
but still, no style is applied to the markers, so the icon shown is the default one, not the chosen one.
Note: Utilities.kmlDocument is where i store all the map markers so it is different from mKmlDocument
Basically, your root cause issue if that you try to rely on markers to build your KML document.
You should handle your own "model", and from that model, build markers as needed, and build KML document when needed.
Your "model" can probably be something as simple as an arraylist of objects with: a GeoPosition, and a "type". Depending on this type, you will be able to create markers with various icons, and KmlPlacemarks with various styles.

JavaFX - Cannot Refresh/Update ListView

Well it appears I have been stumped by one of the simplest ListView implementations out there. For a few days I have found it impossible to properly reallocate a JavaFX ListView. I am working on making an EntityView completely dynamic, being able to remove elements whenever needed through a ContextMenu. So I have a ListView that is populated by an ArrayList, which we will refer to as "renderable". When you select "Remove" in the context menu, it removes the Entity from the renderable list, which also happens to be the "value" of the List Cell on whom I right clicked. Afterwards, I wish to refresh the ListView and remove now the nonexistent cell. So by creating a new ObservableList with the new renderable list (which removes the correct entity and that works fine), I set the items in the ListView, which does jack shit. I can set the list to null in this case, which removes all the elements. But I cannot reset the list with the new array and it remove the now missing entity. Somebody point me in the right direction please!
When I use the method I stated above, it removes it from the list, but not visually. There becomes an unusable cell at the bottom of the list, which has its name.
public void createContextMenu(final Entity curr, MouseEvent me){
MenuItem[] items = {new MenuItem("EDIT TYPE"), new MenuItem("REMOVE")};
ContextMenu menu = new ContextMenu(items);
menu.show(list, me.getScreenX(), me.getScreenY());
items[1].setOnAction(new EventHandler<ActionEvent>(){
public void handle(ActionEvent arg0) {
CanvasTab tab = (CanvasTab) core.canvasTabbedPane.getSelectionModel().getSelectedItem();
Kanvas k = tab.canvas;
k.renderable.remove(curr);
System.out.println(k.renderable);
k.redraw();
EntityView.this.list.getItems().remove(curr);
ObservableList<Entity> temp = FXCollections.observableList(k.renderable);
EntityView.this.list.setItems(temp);
}
});
}
This is the context menu:

Parsing JSON data to Map markers, all markers showing the same info, how can I fix this?

need a bit of help with this one.
I have JSON of a some shops and the shops information, like their names, ids and locations. I parsed it into an ArrayList.
Through an AsyncTask I plotted them on a map. Currently, that's 4 shops. I Overrided the marker onClick to show the data the way I wanted. The problem I'm having is that although the markers are in the correct places based on the longitude and latitude, the other information is not.
When I click on a marker, the same shop name is listed on all of them. It's only showing the last shop in my JSON. All the data is coming from the last shop in my JSON. Here is my onPostExecute() code:
#Override
protected void onPostExecute(ArrayList<ShopArray> shopArray) {
super.onPostExecute(shopArray);
for (ShopArray shopArrayOb : shopArray) {
double lat = shopArrayOb.geo_lat;
double lng = shopArrayOb.geo_lng;
final String barName = shopArrayOb.bar_name;
LatLng shopLocations = new LatLng(lat, lng);
MarkerOptions marker = new MarkerOptions()
.position(shopLocations)
gMap.addMarker(marker);
gMap.setOnMarkerClickListener(new OnMarkerClickListener() {
#Override
public boolean onMarkerClick(Marker marker) {
testText.setText(barName);
return false;
}
});
}
I don't really know how to fix this. I just want it to show the correct names for the markers, amongst other data. It keeps showing data from the last shop in my JSON and nothing else. If you need to see more of my code then let me know and I will update my post.
I would really appreciate some help on this, thanks in advance!
EDIT: I've just tested with the default marker onClick. (.title and .snippet) and it worked! It's showing the correct info!
Is there a way to get a custom onClick then? Looks like setOnMarkerListener is causing the problem.
It's because you're calling setOnMarkerClickListener() on the SAME gMap object multiple times. In this way it's not strange that the last call will take effect, and the last shop's info will be used. You should set OnMarkerClickListener only once. Of course, then you have to identify your markers in its onMarkerClick() method to decide which shop was clicked.
You can put your all markers in HashMap:
//somewhere befor async task
HashMap<LatLng, String> map = new HashMap<LatLng, String>();
Then add markers to it:
//in your post execute
map.put(shopLocations, barName);
Then in your listener:
gMap.setOnMarkerClickListener(new OnMarkerClickListener() {
#Override
public boolean onMarkerClick(Marker marker) {
testText.setText(map.get(marker.getPosition()));
return false;
}
});

How to force combobox to render autocomplete options?

This is my zul code:
<combobox id="digitalPublisherCombobox" value="#load(ivm.inventory.digitalPublisherName)"
onOK="#command('setDigitalPublisher', digitalPublisherBox = self)"
onSelect="#command('setDigitalPublisher', digitalPublisherBox = self)"
onChanging="#command('setupQuicksearchByEvent', searchlayout = event, prefix = 'PUB', tags = 'PublisherName, PublisherNameTranslit')"
mold="rounded" hflex="1" buttonVisible="false" autodrop="true">
<comboitem self="#{each=entry}" value="#{entry.key}" label="#{entry.value}"/>
</combobox>
And this is QuickSearch implementations:
#Command
public void setupQuicksearchByEvent(#BindingParam("searchlayout")Event event, #BindingParam("prefix") String prefix, #BindingParam("tags") String tags) throws WrongValueException, SearchException, IOException
{
if(event instanceof InputEvent)
{
InputEvent inputEvent = (InputEvent) event;
String inputText = inputEvent.getValue();
List<String> searchFields = Arrays.asList(tags.split(","));
ListModel model = new ListModelMap(ZKLogic.findDocsStartingWith(prefix, searchFields, "proxy", inputText), true);
ListModel subModel = ListModels.toListSubModel(model, Autocompleter.MAP_VALUE_CONTAINS_COMPARATOR, 10);
Combobox searchBox = (Combobox) event.getTarget();
searchBox.setModel(subModel);
searchBox.setItemRenderer(new ComboitemRenderer()
{
#Override
public void render( Comboitem item, Object data, int pos ) throws Exception
{
String publisherString = data.toString();
UID key = getUidFromPublisherString(publisherString);
int startIndex = publisherString.indexOf('=') + 1;
String publisher = publisherString.substring(startIndex);
item.setLabel(publisher);
item.setValue(key);
}
});
}
}
ZKLogic.findDocsStartingWith return map with UID-key and String-value.
With code above I achieved to get dropdown list when I switch to another window. I need to type something, then select another browser or notepad window - and comboitems will be displayed immediately.
So, my question still need answer, is there are any techniques to reproduce this windows switching in code? Or maybe I should do something with autocomplete, because I've got some ac working with preloaded lists, but this thing should return only 10 records from db, instead of all 70000 entries, every time when user type something in the field.
Edit 20/09/2013: Problem still exist. Rename question a bit, because thing that I need is to call render option by force in code. Is there is any way to do it? Code hasn't changed a lot, but print option in render method said, that method can miss two or more onChange events and suddenly render text for one variant.
Maybe you know another autocomplete options in zk framework where database participating? I'm ready to change implementation, if there is a guide with working implementation of it.
Ok I see two problems, you should solve first.
Setting the Renderer in every call of setupQuicksearchByEvent(...).
that is not logical, cos it is the same every time.
Add to the zul combobox tag something like
itemRenderer="#load(ivm.myRenderer)" ....
If you want just 10 items, do not let the db-request return more then 10.
If you use JPA klick here or for sql here or just google a bit.
After you fixed this two issues, we can exclude these as a reason of the unexpected behavior and fix it, if it is still present.
Edit
Ok, I have two possible ways to fix it.
Call Combobox#invalidate()
This schould force zk to rerender the Combobox, but could
lead to low performance and I would not prefer this.
Use Listbox with the select mold instead of Combobox.
To force the rerender, use Listbox#renderAll()
Try setting the selected item on your combobox or throw its related event
Solution is simple. Really. Nothing is better then brute-force, but I think I tried to avoid it and use it in despair.
#Command
public void setupQuicksearchByEvent(#BindingParam("searchlayout")Event event, #BindingParam("prefix") String prefix, #BindingParam("tags") String tags) throws WrongValueException, SearchException, IOException
{
if(event instanceof InputEvent)
{
InputEvent inputEvent = (InputEvent) event;
String inputText = inputEvent.getValue();
List<String> searchFields = Arrays.asList(tags.split(","));
Map<UID, String> publishers = ZKLogic.findDocsStartingWith(prefix, searchFields, "proxy", inputText);
Combobox searchBox = (Combobox) event.getTarget();
searchBox.getChildren().clear();
for (Map.Entry<UID, String > entry : publishers.entrySet())
{
Comboitem item = new Comboitem();
item.setLabel(entry.getValue());
item.setValue(entry.getKey());
searchBox.appendChild(item);
}
}
}

How to prevent empty context menu from showing in GXT

I have a TreePanel which shows different kind of objects hierarchically. Region, City, Location...
I want to be able to show different context menu items in different levels. For example: miR for Region, miC for City, miL for Location...
I used this snipped to achieve that dynamic structure:
contextMenu.addListener(Events.BeforeShow, new Listener<MenuEvent>() {
#Override
public void handleEvent(MenuEvent be) {
//First make all menu items invisible
List<Component> menuItems = contextMenu.getItems();
for (Component c : menuItems) {
c.setVisible(false);
}
//And make apprepriate menu items visible
TopologyTreeElement s = tree.getSelectionModel().getSelectedItem();
if (s instanceof TopologyTreeElement.Region) {
miR.setVisible(true);
}
if (s instanceof TopologyTreeElement.City) {
miC.setVisible(true);
}
}
});
But, in any level if all of the items are invisible, it shows an empty box. I want it not to show the menu totally. I tried adding this code snippet to the method, but it gave no help.
//Do not show menu if no menu item is invisible
boolean isMenuShouldBeVisible = miC.isVisible() || miR.isVisible();
if (!isMenuShouldBeVisible) {
be.preventDefault();
be.stopEvent();
}
Anyone can suggest a different approach?
Since you are listening to the BeforeShow event, you are allowed to cancel the event and stop the actual Show event from happening. Check to see if all items are invisible, and if so, call be.setCancelled(true).
Any event that starts in Before can be used to cancel the later event - this is why these before- events exist at all.

Categories

Resources