I need some help to improve the performance of my algorithm, I'm struggling for days and can't find a good solution.
Goal: My app need to show a marker for each airport in the world (~1k markers), and each marker must show the airport name.
What I did: For the marker, I created an RelativeLayout with the Icon and a TextView to populate the name of aiport.
Also, I wrote a class "AirportCluster" extending DefaultClusterRenderer and inside the overrode method onBeforeClusterItemRendered I just cast the layout to Bitmap so it can be rendered on the map
#Override
protected void onBeforeClusterItemRendered(AirportItem airportItem, MarkerOptions markerOptions) {
RelativeLayout customLayoutMarker = (RelativeLayout) activity.getLayoutInflater().inflate(R.layout.custom_airport_marker,null);
String tAirportName = airportItem.getAirport().getAirportName().toLowerCase();
tAirportName = Character.toUpperCase(tAirportName.charAt(0)) + tAirportName.substring(1);
TextView textLabelAirportMarker = (TextView) customLayoutMarker.findViewById(R.id.label_text_airport_marker);
textLabelAirportMarker.setText(tAirportName);
customLayoutMarker.setDrawingCacheEnabled(true);
customLayoutMarker.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED), View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
customLayoutMarker.layout(0,0, customLayoutMarker.getMeasuredWidth(), customLayoutMarker.getMeasuredHeight());
customLayoutMarker.buildDrawingCache(true);
Bitmap flagBitmap;
if ( mMemoryCache.get(tAirportName) == null){
flagBitmap = Bitmap.createBitmap(customLayoutMarker.getDrawingCache());
mMemoryCache.put(tAirportName,flagBitmap);
}else{
flagBitmap = mMemoryCache.get(tAirportName);
}
BitmapDescriptor markerAirportWithText = BitmapDescriptorFactory.fromBitmap(flagBitmap);
markerOptions.icon(markerAirportWithText);
//markerOptions.icon(BitmapDescriptorFactory.fromResource(R.drawable.airport_marker));
}
As we can see in the code, I'm trying to cache it on the memory as well, but this is not working that good.
All the markers are being added on the method onMapReady inside a loop for each airport in the list
for (Airport temp : fixedAirports) {
LatLng latLng = new LatLng(temp.getCityLat(), temp.getCityLng());
// create marker
MarkerOptions markerOptions = new MarkerOptions().position(latLng).title("Marker in" + temp.getCityName());
markerOptions.icon(BitmapDescriptorFactory.fromResource(R.drawable.airport_marker));
AirportItem offsetItem = new AirportItem(temp.getCityLat(), temp.getCityLng());
offsetItem.setAirport(temp);
mClusterManager.addItem(offsetItem);
}
Issue: I also have a custom image for clustered airports, and when i try to zoom in/out sometimes it take to much to the clustered icon dismiss and show the marker item for an airport, sometimes the icon of the item even overlaps the clustered one, just like on the images below.
What I have to do to these animations (changing from clustered icon from single markers) be more fast and smooth??
Prepare BitmapDescriptors first in background (i.e. Coroutines viewModelScope or another thread or asynctask or Rxjava), then load them to ui. Dont draw anything inside your ClusterRenderer class. Doing so helped me a bit.
Related
I am using marker view in order to display marker.
My code:
View customView = LayoutInflater.from(activity).inflate(R.layout.dialog_obstacle_with_markers, null);
customView.setLayoutParams(new FrameLayout.LayoutParams(WRAP_CONTENT, WRAP_CONTENT));
ImageView iv_marker = customView.findViewById(R.id.iv_marker);
iv_marker.setTag(reportItemArrayList.get(i).getReportId());
ImageView iv_marker_white = customView.findViewById(R.id.iv_marker_white);
FrameLayout fl_category = customView.findViewById(R.id.fl_category);
ImageView iv_obstacle = customView.findViewById(R.id.iv_obstacle);
TextView tv_obstacle = customView.findViewById(R.id.tv_obstacle);
int[] rgbValue = Utils.getRGBFromHex(reportItemArrayList.get(i).getColor());
iv_marker.setColorFilter(Color.rgb(rgbValue[0], rgbValue[1], rgbValue[2]));
Glide.with(activity)
.load(reportItemArrayList.get(i).getFilename())
.apply(new RequestOptions()
.diskCacheStrategy(DiskCacheStrategy.ALL)
.placeholder(R.mipmap.ic_obstacle_place_holder)
.error(R.mipmap.ic_obstacle_place_holder))
.into(iv_obstacle);
tv_obstacle.setText(reportItemArrayList.get(i).getCategoryName());
MarkerView markerView = new MarkerView(new LatLng(Double.parseDouble(reportItemArrayList.get(i).getLat()), Double.parseDouble(reportItemArrayList.get(i).getLng())), customView);
markerViewManager.addMarker(markerView);
Here I have multiple same location markers available and I am able to see only first location marker and other marker are behind first marker due to same location.
Now I want to handle click event of other marker behind first marker.
Currently I am getting only first location marker click due to same location.
But I want all click events behind first marker.
Please help me with this.
you can not handle the click event of same location markers like this.
the markers should have different locations to handle them.
I am really struggling with google map util these days challenge after challenge and there is not good example or solution on the net.
This is my code:
#Override
protected void onBeforeClusterRendered(Cluster<ItemCluster> cluster,
MarkerOptions markerOptions) {
View marker = (getActivity()
.getLayoutInflater())
.inflate(R.layout.info_windows, null);
Bitmap bitmap = createDrawableFromView(
getActivity(), marker);
markerOptions.icon(BitmapDescriptorFactory.fromBitmap(bitmap));
}
The problem is before I send the view to this function to make a bitmap for marker, I try to set some data in my info_windows.xml which is included with some ImageViews and TextViews. But the app hangs, do you have any idea how to make this done?
Bitmap bitmap = createDrawableFromView(
getActivity(), marker);
I solve my problem by making an IconGenerator objectand then make the view from that this is how i did it:
first i made the object:
private final IconGenerator mClusterIconGenerator = new IconGenerator(getActivity().getApplicationContext());
and a view which contains our XML view file of our costum marker:
View markerIcon = getActivity().getLayoutInflater().inflate(R.layout.marker_icon, null);
then set the view on icongenerator:
mMarkerIconGenerator.setContentView(markerIcon);
then you need to initiate your imageview, textview, ... then set the values that you want to show inside your costum marker like this for ex:
mMarkerViento = (ImageView) clusterIcon.findViewById(R.id.viento);
then inside the ovveride method of:
#Override
protected void onBeforeClusterItemRendered(ItemCluster item, MarkerOptions markerOptions)
mMarkerViento.setImageResource(R.drawable.viento_ne2);
and at the end you generate your bitmap object from icon generator like this:
mMarkerIconGenerator.setBackground(TRANSPARENT_DRAWABLE); // set the background as transparent
Bitmap bitmap = mMarkerIconGenerator.makeIcon(); // make a bitmap object from the icon object
markerOptions.icon(BitmapDescriptorFactory.fromBitmap(bitmap)); // set the bitmap as marker icon
good luck and tanx
Android Google maps V2 How to draw a Custom Views(1/3 filled circle) on map where can i get canvas object to draw.As all new classes are final classes I can't extend them.
I need to draw a some cutom views on the map.I am upgrading from v1 to v2.The Overlays has been deprecated.I tries with Tile Provider but it is not drawing anything.
exampleButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
GroundOverlayOptions overlayOptions = new GroundOverlayOptions()
.image(BitmapDescriptorFactory.fromResource(R.drawable.testImage))
.position(new LatLng(currentLocation.getLatitude(), currentLocation.getLongitude()), 8600f, 6500f);
map.addGroundOverlay(overlayOptions);
}
});
This is the code to draw an image at a specified lat long which is working for google maps v2. You can basically get an image of 1/3 filled circle and set it to the lat long you want.
Hope it helps.
I think I have the same issue with the post on this link
Different markers show same infowindow content android google map v2
I am currently developing an app that integrates Google Maps v2 to allow users to take picture and automatically plotting a marker on the map.
I have a working InfoWindowAdapter but it seems that when I set a Bitmap as you can see below:
ImageView ivIcon = ((ImageView)myContentsView.findViewById(R.id.iconImg));
ivIcon.setImageBitmap(getResizedBitmap(myBitmap.getBp(),100,100));
When taking multiple pictures using my camera (which means it will have respective markers plotted on the map), the markers all share the same image, which is the latest image taken from the camera. I thought creating a Class by checking for difference in Bitmap object name would solve the problem but it did not.
It seems that when applying:
myMap.setInfoWindowAdapter(new MyInfoWindowAdapter());
it applies to all markers.
How do I go around doing it that each marker would have its own custom info window adapter?
Thanks!
======================================== EDIT =================================
I have an application that will allow users to take pictures which will also plot a marker on the map of the location of image capture. The marker will have a custom InfoWindow. I tried the solution but they are vague to me.
Do you mind explaining what did you do to your code such that doing:
googleMap.setInfoWindowAdapter(new InfoWindowAdapter());
will not affect all the markers on the map?
My current code for the CustomInfoBox is as follows:
class MyInfoWindowAdapter implements InfoWindowAdapter{
private final View myContentsView;
MyInfoWindowAdapter(){
myContentsView = getLayoutInflater().inflate(R.layout.custom_info_window, null);
}
#Override
public View getInfoContents(Marker marker) {
//TextView tvTitle = ((TextView)myContentsView.findViewById(R.id.title));
// tvTitle.setText(marker.getTitle());
TextView tvSnippet = ((TextView)myContentsView.findViewById(R.id.snippet));
tvSnippet.setText(marker.getSnippet());
ImageView ivIcon = ((ImageView)myContentsView.findViewById(R.id.badge));
ivIcon.setImageBitmap(getResizedBitmap(myBitmap.getBp(),100,100));
System.out.println("Custom Info Window: " + myBitmap.getBp());
return myContentsView;
}
#Override
public View getInfoWindow(Marker marker) {
// TODO Auto-generated method stub
return null;
}
}
When I call googleMap.setInfoWindowAdapter(MyInfoWindowAdapter);, all markers have the same layout and thus same picture (last picture taken by user!) which is not something that I want.
Any help will be much appreciated! thanks
I am working on an Android app that displays multiple markers on a Google MapView. Everything works perfectly but I would like the markers to have an animation when they appear on the map.
Here's an example of something similar on iPhone. See 1'20".
Here is how I add them to my MapView.
for(int i=0; i<myMarkerList.length(); i++){
GeoPoint x = new GeoPoint(
(int)(lat*1E6),
(int)(lng*1E6));
oItem = new OverlayItem(x, title, String.valueOf(nb_marker));
pin.setAlpha(255);
oItem.setMarker(pin);
if (oItem != null)
mapOverlay.addOverlay(oItem); // add the overlay item to the overlay
}
mapOverlays.add(mapOverlay); // add the overlay to the list of overlays
mapView.invalidate(); // update the map shown
It is so pretty on iPhone, and someone must have already done something similar on Android but I can't seem to find any useful info.
EDIT: Okay so I recon I either have to override the draw method which will be long and not that pretty, or just give up with OverlayItems.
Thank you for your time.
Best regards,
Tom
You can use this tutorial for a reference, it uses animations, so I think that suits your solution.
Code from the tutorial :
//Reference to our MapView
MapView mapView = (MapView) activity.findViewById(R.id.mapview);
//Get a LayoutInflater and load up the view we want to display.
//The false in inflater.inflate prevents the bubble View being added to the MapView straight away
LayoutInflater inflater = activity.getLayoutInflater();
LinearLayout bubble = (LinearLayout) inflater.inflate(R.layout.bubble, mapView, false);
//Set up the bubble's close button
ImageButton bubbleClose = (ImageButton) bubble.findViewById(R.id.bubbleclose);
bubbleClose.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Animation fadeOut = AnimationUtils.loadAnimation(ResultsMapResultsDisplayer.this.activity, R.anim.fadeout);
bubble.startAnimation(fadeOut);
bubble.setVisibility(View.GONE);
}
});
private void displaySearchResultBubble(final SearchResult result) {
//Hide the bubble if it's already showing for another result
map.removeView(bubble);
bubble.setVisibility(View.GONE);
//Set some view content
TextView venueName = (TextView) bubble.findViewById(R.id.venuename);
venueName.setText(result.getName());
//This is the important bit - set up a LayoutParams object for positioning of the bubble.
//This will keep the bubble floating over the GeoPoint result.getPoint() as you move the MapView around,
//but you can also keep the view in the same place on the map using a different LayoutParams constructor
MapView.LayoutParams params = new MapView.LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT,
result.getPoint(), MapView.LayoutParams.BOTTOM_CENTER);
bubble.setLayoutParams(params);
map.addView(bubble);
//Measure the bubble so it can be placed on the map
map.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
//Runnable to fade the bubble in when we've finished animatingTo our OverlayItem (below)
Runnable r = new Runnable() {
public void run() {
Animation fadeIn = AnimationUtils.loadAnimation(activity, R.anim.fadein);
bubble.setVisibility(View.VISIBLE);
bubble.startAnimation(fadeIn);
}
};
//This projection and offset finds us a new GeoPoint slightly below the actual OverlayItem,
//which means the bubble will end up being centered nicely when we tap on an Item.
Projection projection = map.getProjection();
Point p = new Point();
projection.toPixels(result.getPoint(), p);
p.offset(0, -(bubble.getMeasuredHeight() / 2));
GeoPoint target = projection.fromPixels(p.x, p.y);
//Move the MapView to our point, and then call the Runnable that fades in the bubble.
mapController.animateTo(target, r);
}
I seen your example app. From that i think you need only Glow in your markers, right? If yes then its possible through the styles and its having glow property also.
So I got it to work using a simple ArrayList of ImageViews and animation on them, no MapOverlay.