我正在开发一个使用Google Map API v2的Android应用程序。我需要使用自定义标记在地图上显示用户位置。

每个标记都将通过URL显示用户的图片。必须以异步模式从服务器下载映像。请参阅随附的屏幕截图以获取示例。

如何在标记中添加图像和自定义信息?



评论

非常好的解决方案nasc.fr/android/…

developers.google.com/maps/documentation/android-api/utility/…-已由Google家伙在maps-utils库中实现

您可以尝试此stackoverflow.com/a/48005956/6667442

#1 楼

在Google Maps API v2演示中,有一个MarkerDemoActivity类,您可以在其中查看如何将自定义图像设置为GoogleMap。对于图像,您可能希望使用Canvas绘制更复杂,更奇特的东西:代码应该(大部分)说明一切,那里有很多教程如何绘制canvas1。您可以从Android开发人员页面上的“画布和可绘制对象”开始。

现在您还想从URL下载图片。

br />您必须从后台线程下载图像(可以使用AsyncTask或Volley或RxJava)。

之后,您可以用下载的图像GoogleMap mMap替换Canvas

评论


很好的答案,除了URL部分。您将在主应用程序线程上下载该映像,这是一个非常糟糕的主意。实际上,因此,您的代码将在Android 4.0+上完全崩溃。 “ Might”在这里的声明太弱了,您必须在后台线程中下载该图像,以避免UI出现混乱,更不用说NetworkOnMainThreadException。

– CommonsWare
13年2月11日在12:51

@lambda k我们使用后台线程下载图像,当我们从Web服务获取纬度,经度和url时,我不明白先生的一件事,然后如何快速将url转换为位图

– Rishi Gautam
2013年4月26日上午10:13

新的AsyncTask (){protected void onPostExecute(Bitmap result){image.setImageBitmap(result); }; @Override受保护的位图doInBackground(Void ... params){return Utils.loadBitmap(url); } }。执行();

–sonida
13年4月30日在3:45

此方法有效,但存在性能问题,并且不缓存,处理内存问题等。请研究Google的Volley或Square的Picasso框架以提高下载效率。

–帕特里克(Patrick)
13年5月28日在16:05

在Lolipop工作吗?我在我的应用程序中实现了类似的功能,该功能从url加载标记图像,该图像在除Lolipop之外的所有操作系统版本上均能正常工作。在Lolipop中,它不会呈现下载的图标。有人知道吗?

– Vinay
2015年4月3日在7:22

#2 楼

我还使用的另一种更简单的解决方案是创建自定义标记布局并将其转换为位图。

view_custom_marker.xml使用下面的代码将此视图转换为位图

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/custom_marker_view"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@drawable/marker_mask">

    <ImageView
        android:id="@+id/profile_image"
        android:layout_width="48dp"
        android:layout_height="48dp"
        android:layout_gravity="center_horizontal"
        android:contentDescription="@null"
        android:src="@drawable/avatar" />
</FrameLayout>


在Map ready回调中添加自定义标记。
有关更多详细信息,请单击下面的链接

如何使用布局创建自定义标记?

评论


请检查您的答案。什么是未定义视图?

–饮食
16年5月12日在18:16

@dit感谢您指出我已经更新了我的答案。其实它的customMarkerView

– waleedsarwar86
16年5月13日在7:47

我们可以使用Glide从URL加载图像吗?

–令人沮丧的Gosai
17年4月11日在11:14



@Prashant Gosai您需要添加一个回调,并且在下载图像时,可以从膨胀的布局中获取位图。

–汉普尔·埃尔德(HampelElőd)
17年8月3日在7:15

这个答案实际上是惊人的,非常有创造力,使我解决了一个令人讨厌的问题

–收货人
7月28日4:28

#3 楼

我希望分享我的解决方案还为时不晚。在此之前,您可以按照Android Developer文档中所述的教程进行操作。为此,您需要将Cluster Manager与defaultRenderer一起使用。创建一个实现ClusterItem的对象
/>
创建默认的渲染器类。这是完成所有工作的类(使用您自己的样式来填充自定义标记/群集)。我正在使用Universal Image loader进行图像的下载和缓存。

public class SampleJob implements ClusterItem {

private double latitude;
private double longitude;

//Create constructor, getter and setter here

@Override
public LatLng getPosition() {
    return new LatLng(latitude, longitude);
}



在活动/片段类中应用集群管理器。

public class JobRenderer extends DefaultClusterRenderer< SampleJob > {

private final IconGenerator iconGenerator;
private final IconGenerator clusterIconGenerator;
private final ImageView imageView;
private final ImageView clusterImageView;
private final int markerWidth;
private final int markerHeight;
private final String TAG = "ClusterRenderer";
private DisplayImageOptions options;


public JobRenderer(Context context, GoogleMap map, ClusterManager<SampleJob> clusterManager) {
    super(context, map, clusterManager);

    // initialize cluster icon generator
    clusterIconGenerator = new IconGenerator(context.getApplicationContext());
    View clusterView = LayoutInflater.from(context).inflate(R.layout.multi_profile, null);
    clusterIconGenerator.setContentView(clusterView);
    clusterImageView = (ImageView) clusterView.findViewById(R.id.image);

    // initialize cluster item icon generator
    iconGenerator = new IconGenerator(context.getApplicationContext());
    imageView = new ImageView(context.getApplicationContext());
    markerWidth = (int) context.getResources().getDimension(R.dimen.custom_profile_image);
    markerHeight = (int) context.getResources().getDimension(R.dimen.custom_profile_image);
    imageView.setLayoutParams(new ViewGroup.LayoutParams(markerWidth, markerHeight));
    int padding = (int) context.getResources().getDimension(R.dimen.custom_profile_padding);
    imageView.setPadding(padding, padding, padding, padding);
    iconGenerator.setContentView(imageView);

    options = new DisplayImageOptions.Builder()
            .showImageOnLoading(R.drawable.circle_icon_logo)
            .showImageForEmptyUri(R.drawable.circle_icon_logo)
            .showImageOnFail(R.drawable.circle_icon_logo)
            .cacheInMemory(false)
            .cacheOnDisk(true)
            .considerExifParams(true)
            .bitmapConfig(Bitmap.Config.RGB_565)
            .build();
}

@Override
protected void onBeforeClusterItemRendered(SampleJob job, MarkerOptions markerOptions) {


    ImageLoader.getInstance().displayImage(job.getJobImageURL(), imageView, options);
    Bitmap icon = iconGenerator.makeIcon(job.getName());
    markerOptions.icon(BitmapDescriptorFactory.fromBitmap(icon)).title(job.getName());


}

@Override
protected void onBeforeClusterRendered(Cluster<SampleJob> cluster, MarkerOptions markerOptions) {

    Iterator<Job> iterator = cluster.getItems().iterator();
    ImageLoader.getInstance().displayImage(iterator.next().getJobImageURL(), clusterImageView, options);
    Bitmap icon = clusterIconGenerator.makeIcon(iterator.next().getName());
    markerOptions.icon(BitmapDescriptorFactory.fromBitmap(icon));
}

@Override
protected boolean shouldRenderAsCluster(Cluster cluster) {
    return cluster.getSize() > 1;
}


结果



评论


您能列出这种方法的依赖性吗?许多代码库都没有考虑。

–乔纳森·邓恩
17年11月23日23:36



您是从'com.evernote:android-job:1.2.1'库引用的'Job'类吗?

–乔纳森·邓恩
17年11月23日在23:40

此示例中的@JonDunn'Job'是自定义类。这是我使用的依赖项:编译'com.google.maps.android:android-maps-utils:0.5+。可以在以下位置找到更多说明:developers.google.com/maps/documentation/android-api/utility/…

– Amad Yus
17年11月24日在3:36

#4 楼

从lambda答案,我已经接近要求。

boolean imageCreated = false;

Bitmap bmp = null;
Marker currentLocationMarker;
private void doSomeCustomizationForMarker(LatLng currentLocation) {
    if (!imageCreated) {
        imageCreated = true;
        Bitmap.Config conf = Bitmap.Config.ARGB_8888;
        bmp = Bitmap.createBitmap(400, 400, conf);
        Canvas canvas1 = new Canvas(bmp);

        Paint color = new Paint();
        color.setTextSize(30);
        color.setColor(Color.WHITE);

        BitmapFactory.Options opt = new BitmapFactory.Options();
        opt.inMutable = true;

        Bitmap imageBitmap=BitmapFactory.decodeResource(getResources(),
                R.drawable.messi,opt);
        Bitmap resized = Bitmap.createScaledBitmap(imageBitmap, 320, 320, true);
        canvas1.drawBitmap(resized, 40, 40, color);

        canvas1.drawText("Le Messi", 30, 40, color);

        currentLocationMarker = mMap.addMarker(new MarkerOptions().position(currentLocation)
                .icon(BitmapDescriptorFactory.fromBitmap(bmp))
                // Specifies the anchor to be at a particular point in the marker image.
                .anchor(0.5f, 1));
    } else {
        currentLocationMarker.setPosition(currentLocation);
    }

}