设置地图标注图片:Mapbox Android

3
在iOS中,您可以通过调用以下方法轻松为标记设置一个弹出窗口:
[marker setCanShowCallout:YES];
[marker setRightCalloutAccessoryView:YOUR_BUTTON];

但是我在Mapbox Android SDK中找不到此功能。我现在有一个监听器,可以检测到对calloutview的触摸,但是我如何设置callout图像/按钮呢?

Marker marker = new Marker(p.getTitle(), p.getCatagoryName(), new LatLng(p.getLatitude(), p.getLongitude()));
                        marker.setMarker(getResources().getDrawable(getResources().getIdentifier(string, "drawable", getActivity().getPackageName())));
                                mMapView.addMarker(marker);

                        InfoWindow toolTip = marker.getToolTip(mMapView);
                        View view = toolTip.getView();
                        // view.setBackgroundResource(R.drawable.callout_button); THIS DOES NOT WORK
                        view.setOnTouchListener(new View.OnTouchListener() {
                            @Override
                            public boolean onTouch(View view, MotionEvent motionEvent) {
                                Log.e(TAG, "onTouch");

                                return true;
                            }
                        });

嗨,马克,你解决了这个问题吗?我们已经完成了使用Mapbox的iOS版本,并已经开始开发我们的应用程序的Android版本。我们遇到了同样的问题。在我们的iOS工具提示上有一个accessoryView,它可以引导用户查看与该兴趣点相关的“全屏视图”中的详细信息。但是,在Android中重复这个功能相当没有文档记录...除非我们漏掉了什么。 - Joshua Powell
很抱歉要说这个,但实际上我还没有想出来。我重新审视了我的设计,并决定采用与谷歌地图相同的方法实现。 - Mark Molina
我认为这就是我们过去几天一直在考虑的。毕竟,如果你在Android上使用Google Maps..他们的设计模式根本不使用工具提示/弹出窗口。他们有一个自定义视图,从底部滑出并可滚动。我们认为这可能是Android平台上更自然的方法。 - Joshua Powell
不过请注意,Android SDK中并没有包含谷歌地图实现。我必须从头开始创建它。 - Mark Molina
2个回答

5

您需要自己构建此功能,但通过定义自定义标记和工具提示布局实际上很容易实现。

首先定义您的工具提示布局。显然它必须是一个RelativeLayout以定位呼出图片。将上下文设置为创建标记的任何Activity。底部的TipView必须包含在内,因为它控制自定义工具提示的大小。

<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:background="@color/white"
    android:id="@+id/parent_layout"
    android:padding="5dp"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    tools:context="com.XXX.MainActivity">

    <TextView
        android:id="@+id/tooltip_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textColor="@color/black"
        android:textSize="18sp"
        android:maxEms="17"
        android:layout_gravity="left"
        android:layout_weight="1"
        android:text="@string/toolTipTitle"/>

    <TextView
        android:id="@+id/tooltip_description"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textColor="@color/black"
        android:textSize="14sp"
        android:maxEms="17"
        android:text="@string/toolTipDescription"
        android:layout_below="@+id/tooltip_title"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true" />

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/marker_about"
        android:src="@drawable/ic_action_about"
        android:layout_toEndOf="@+id/tooltip_description"
        android:layout_toRightOf="@+id/tooltip_description"
        android:layout_centerVertical="true"
        android:layout_centerHorizontal="true"
        android:layout_marginLeft="10dp" />

    <com.mapbox.mapboxsdk.views.TipView
            android:layout_width="132dp"
            android:layout_height="10dp"/>
</RelativeLayout>

然后创建一个自定义的Marker类,并重写createTooltip方法,返回一个具有新布局的InfoWindow:

public class CustomMarker extends Marker {

    public CustomMarker(MapView mv, String aTitle, String aDescription, LatLng aLatLng){
        super(mv, aTitle, aDescription, aLatLng);
    }

    @Override
    protected InfoWindow createTooltip(MapView mv) {
        return new InfoWindow(R.layout.custom_tooltip, mv);
    }
}

这不应该改变其他任何功能,因此您现有的代码仍将正常工作。只需将Marker更改为自定义类名称即可。

编辑:这是实际设置CustomMarker和InfoWindow与我的地图一起使用的代码。您可以看到我在单击时启动了另一个活动,并为标记设置了自定义图标,但这些内容并不是必需的:

        CustomMarker m =
                new CustomMarker(mv, report.issue, report.getFormattedDateString(), latLng);
        m.setIcon(new Icon(this, Icon.Size.LARGE, "oil-well", "FF0000"));
        //get the InfoWindow's view so that you can set a touch listener which will switch
        //to the marker's detailed view when clicked
        final InfoWindow infoWindow = m.getToolTip(mv);
        View view = infoWindow.getView();
        view.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View view, MotionEvent motionEvent) {
                //make sure to choose action down or up, otherwise the intent will launch twice
                if(motionEvent.getAction() == MotionEvent.ACTION_DOWN){
                    startActivity(intent);
                    //close the InfoWindow so it's not still open when coming back to the map
                    infoWindow.close();
                }
                return true;
            }
        });
        mv.addMarker(m);

我也在使用SDK 0.5.0-SNAPSHOT版本。不确定这是否适用于旧版SDK。


它会产生一个空指针异常 @ryansh - Nooh
嘿@Nooh,我更新了我的回复,并加入了实际实现标记和信息窗口的代码,你可以查看一下。你使用的Mapbox SDK版本是哪个?如果你能提供更多关于你的问题的信息,我可以尝试帮助你。 - Ryan Hamley
感谢 @ryansh,自定义标记正常工作,我上周得到了结果。 - Nooh
太棒了。很高兴它能够解决@Nooh的问题。对于回复晚了表示歉意。 - Ryan Hamley

3

ryansh的出色回答要求我在自定义布局中包含具有tooltip_title和tooltip_description id的TextViews。我还必须添加第三个tooltip_subdescription TextView。默认的InfoWindow代码假定这些视图存在,如果它们不存在,则会崩溃。为了更好的控制,我扩展了InfoWindow,并重写了onOpen,能够使用任何我想要的tooltip布局。对于扩展的Marker类中重写的createTooltip方法,我自然实例化并返回了我的扩展InfoWindow对象。

更新。以下是扩展Marker和InfoWindow以支持自定义工具提示的示例:

public class MapboxMarker extends Marker {
    private MyInfoWindow mInfoWindow;

    public class MyInfoWindow extends InfoWindow {

        public MyInfoWindow(int layoutResId, MapView mapView) {
            super(layoutResId, mapView);
        }

        public void onOpen(Marker overlayItem) {
            //
            //  Set data on mInfoWindow.getView()
            //
        }

    }

    public MapboxMarker(MapView mv, LatLng aLatLng, MapController mapController){
        super(mv, "Title", "Description", aLatLng);
    }

    @Override
    protected InfoWindow createTooltip(MapView mv) {
        mInfoWindow = new MyInfoWindow(R.layout.custom_tooltip_layout, mv);
        return mInfoWindow;
    }
}

我使用了您的建议来覆盖InfoWindow,但是我收到了错误消息,说“没有默认构造函数可用”。在您的情况下,您是如何解决这个错误的?谢谢。 - Raditya Kurnianto
你在派生类中添加了一个默认构造函数: public MyInfoWindow(int layoutResId, MapView mapView) { super(layoutResId, mapView); } - AlanKley
我还发现,当我扩展Marker类并在调用super构造函数时使用空值作为title和description参数(super(mv, "", "", aLatLng)),触摸标记会停止工作。当我传递非空字符串(super(mv, " ", " ", aLatLng))时,它们再次开始工作,并调用MyMarker.onOpen。 - AlanKley
我做到了,你能否举个例子,当你尝试实现完全自定义布局到信息窗口时?我也试过,但总是出错。@AlanKley - Raditya Kurnianto

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接