如何使用Android地图API v2创build自定义形状的位图标记

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

每个标记将从URL显示用户的图片。 必须从服务器以asynchronous模式下载映像。 有关示例,请参阅附件屏幕截图。

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

在这里输入图像描述

在Google Maps API v2 Demo中,有一个MarkerDemoActivity类,您可以在其中看到如何将自定义图像设置为GoogleMap。

 // Uses a custom icon. mSydney = mMap.addMarker(new MarkerOptions() .position(SYDNEY) .title("Sydney") .snippet("Population: 4,627,300") .icon(BitmapDescriptorFactory.fromResource(R.drawable.arrow))); 

因为这只是用图像replace标记,所以您可能想使用Canvas绘制更复杂更漂亮的东西:

 Bitmap.Config conf = Bitmap.Config.ARGB_8888; Bitmap bmp = Bitmap.createBitmap(80, 80, conf); Canvas canvas1 = new Canvas(bmp); // paint defines the text color, stroke width and size Paint color = new Paint(); color.setTextSize(35); color.setColor(Color.BLACK); // modify canvas canvas1.drawBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.user_picture_image), 0,0, color); canvas1.drawText("User Name!", 30, 40, color); // add marker to Map mMap.addMarker(new MarkerOptions() .position(USER_POSITION) .icon(BitmapDescriptorFactory.fromBitmap(bmp)) // Specifies the anchor to be at a particular point in the marker image. .anchor(0.5f, 1)); 

canvas1 Canvas canvas1绘制到GoogleMap mMap 。 代码应该(大部分)自己说话,有很多教程在那里如何画一个Canvas 。 您可以从Android Developer页面查看Canvas和Drawables开始。

现在你也想从URL下载图片。

 URL url = new URL(user_image_url); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setDoInput(true); conn.connect(); InputStream is = conn.getInputStream(); bmImg = BitmapFactory.decodeStream(is); 

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

之后,您可以将BitmapFactory.decodeResource(getResources(), R.drawable.user_picture_image)replace为下载的图像bmImg

我也使用的替代和更容易的解决scheme是创build自定义标记布局,并将其转换为位图。

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> 

通过使用下面的代码将此视图转换为位图

  private Bitmap getMarkerBitmapFromView(@DrawableRes int resId) { View customMarkerView = ((LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.view_custom_marker, null); ImageView markerImageView = (ImageView) customMarkerView.findViewById(R.id.profile_image); markerImageView.setImageResource(resId); customMarkerView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED); customMarkerView.layout(0, 0, customMarkerView.getMeasuredWidth(), customMarkerView.getMeasuredHeight()); customMarkerView.buildDrawingCache(); Bitmap returnedBitmap = Bitmap.createBitmap(customMarkerView.getMeasuredWidth(), customMarkerView.getMeasuredHeight(), Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(returnedBitmap); canvas.drawColor(Color.WHITE, PorterDuff.Mode.SRC_IN); Drawable drawable = customMarkerView.getBackground(); if (drawable != null) drawable.draw(canvas); customMarkerView.draw(canvas); return returnedBitmap; } 

在Map readycallback中添加自定义标记。

 @Override public void onMapReady(GoogleMap googleMap) { Log.d(TAG, "onMapReady() called with"); mGoogleMap = googleMap; MapsInitializer.initialize(this); addCustomMarker(); } private void addCustomMarker() { Log.d(TAG, "addCustomMarker()"); if (mGoogleMap == null) { return; } // adding a marker on map with image from drawable mGoogleMap.addMarker(new MarkerOptions() .position(mDummyLatLng) .icon(BitmapDescriptorFactory.fromBitmap(getMarkerBitmapFromView(R.drawable.avatar)))); } 

欲了解更多详情,请点击下面的链接

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

我希望现在分享我的解决scheme还为时不晚。 在此之前,您可以按照Android开发者文档中的说明来学习教程。 为了实现这一点,您需要使用具有defaultRenderer Cluster Manager。

  1. 创build一个实现ClusterItem的对象

     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); } 
  2. 创build一个默认的渲染器类。 这是完成所有工作的类(用自己的风格夸大自定义标记/集群)。 我正在使用通用图像加载器来下载和caching图像。

     public class JobRenderer extends DefaultClusterRenderer<Job> { 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<Job> 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(Job 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<Job> 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; } 
  3. 在您的活动/片段类中应用集群pipe理器。

     public class SampleActivity extends AppCompatActivity implements OnMapReadyCallback { private ClusterManager<Job> mClusterManager; private GoogleMap mMap; private ArrayList<SampleJob> jobs = new ArrayList<SampleJob>(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_landing); SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager() .findFragmentById(R.id.map); mapFragment.getMapAsync(this); } @Override public void onMapReady(GoogleMap googleMap) { mMap = googleMap; mMap.getUiSettings().setMapToolbarEnabled(true); mClusterManager = new ClusterManager<Job>(this, mMap); mClusterManager.setRenderer(new JobRenderer(this, mMap, mClusterManager)); mMap.setOnCameraChangeListener(mClusterManager); mMap.setOnMarkerClickListener(mClusterManager); //Assume that we already have arraylist of jobs for(final Job job: jobs){ mClusterManager.addItem(job); } mClusterManager.cluster(); } 
  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); } }