3
votes

I have a pin which has a arrowed-tip. When placed a marker, the tip is not actually pointing accurately to the tap location. It seems my pins are being positioned base on their center. I want to move this center by a particular offset.

Here is what I am currently using (among many other custom pins I have). These are sized at 250x250:

enter image description here

This is a circular button. Notice it has a arrow on the bottom-most part (pointing downwards).

Now, lets place this pin on mapbox:

@Override
public void onMapClicked(@NonNull LatLng point)
{
    mPopularView.showPinSelectedPopup(false);

    if(!mIsOnMyRecommendationMode)
        return;

    IconFactory iconFactory = IconFactory.getInstance(getContext());
    Drawable iconDrawable = ContextCompat.getDrawable(getContext(), R.drawable.ic_map_bank_blue_pin);
    Icon icon = iconFactory.fromDrawable(iconDrawable);

    MarkerOptions markerOption = new MarkerOptions();
    markerOption.setPosition(point);
    markerOption.title("Just a I don't know where I am!");
    markerOption.setSnippet("Hello World! I don't know where I am!");
    markerOption.setIcon(icon);

    mPopularView.getMapboxMap().addMarker(markerOption);

    mIsOnMyRecommendationMode = false;
}

Fairly simple, just like in the docs. It works very well. Look at the following pic:

enter image description here

I hope this pic will paint a thousand words. Please do not suggest of adjusting the LatLang to account for the offset. That will be incorrect on my use case. It has to be the pixel position of the icon itself. MapBox should have accounted for this when they allowed devs to develop their own custom pins (WE ARE GOING TO PUT ARROWS ON OUR PINS!).

Currently, I set the height of the custom pin icon with double the height. But one caveat I found is that I can actually select the bottom half of the now longer pin icon. For example:

enter image description here

Notice the image above. The height of that image has been doubled. When I placed this, now the arrow correctly points to the area I tapped. One caveat is that, when you pressed below the pin, it still detects click callback. Guess why... because the bounds (specifically the height) of the custom icon is longer and so does its click boundaries. Thus, I cannot put pins below it as it detects it as onMarkerClicked().

How can I get around this? Any ideas?

Thanks!

Not So Elegant Solution

Just wanted to post this as answer in case somebody else is experiencing the same. My situation is kind of extreme and I really need to load the bitmap on the pin instead of some other method proposed by cammace. I use the old fashioned pixel-positioning to get exactly what I wanted. Fortunately, MapBox is equipped with transforming screen coordinates to map coordinates and vice-versa.

I tested this on both tablet and a mobile phone and it doesn't seem to get affected by the screen size. Its pointy edge now actually points at my designated target:

LatLng position = new LatLng();
position.setLatitude(lat);
position.setLongitude(long);

PointF pointF = mMapboxMap.getProjection().toScreenLocation(position);
pointF.offset(0f, -(icon.getBitmap().getHeight() / 2.0f));

position = mMapboxMap.getProjection().fromScreenLocation(pointF);

This is not the most elegant solution. I hope this helps anyone who are in similar situation like me. Nudging the pin upward is only representational, I still read the original latlong values of pins from our homebrew server as is, I just placed the latlong values a little bit off upwards during marker placement.

Zooming also doesn't seem to be affected by this, I tried both not placing it by pixels and one with using this solution.

As I have said, if this is totally wrong. Let me know.

If there are some caveats on this approach. Please do let me know.

1
can you just show the screenshot of the problem you are facing as its very unclear from the description.Newbie Android
Post the code what have you tried?Akshay Bhat 'AB'
Sorry, I never tried any code, my work around is fairly simple. Given a pin say 250x250, make the height of this pin double such that it is 250x500. The reason for this is that when the pin is put in place (assuming it is positioning it base on the center of the sprite/pin/icon/drawable) it will appear that the tip of the icon points to where I actually selected. There is caveat, the hit selection of this is really noticeable. selecting below the pin (even though there is no pin below it) triggers the callback. I'll follow up the asset I have and some code.Neon Warge
@AshayBhat'AB' updated thanks!Neon Warge

1 Answers

1
votes

With the release of 4.2.0 last week, we have three ways of adding markers. The current way you are adding them will indeed mean that you will need to add padding to your image so that the image is centered (this is what we are doing with the default marker).

The second option you have is using MarkerViews. Simply replace this line:

MarkerOptions markerOption = new MarkerOptions();

to this:

MarkerViewOptions markerOption = new MarkerViewOptions();

this will expose a few more options including an anchoring option. Marker views have one issue which is performance, so if you are adding an abundance of markers or don't like them being slightly out of sync with the map, you have a third option.

The third option will be using Runtime Styling to create a symbol layer and making use of the offset property found in the style spec. Have a look at this example found in our demo app for better understanding of the potential of using runtime styling.