Как создать пользовательский растровый маркер с Android map API v2 [дубликат]
этот вопрос уже есть ответ здесь:
Я разрабатываю приложение для Android, где я использую Google Map API v2. Мне нужно показать местоположение пользователя на карте с пользовательскими маркерами.
каждого маркера покажет изображение пользователя с URL-адреса. Образ должен быть загружен с сервера в асинхронном режиме. См. прилагаемый скриншот для примера.
Как добавить изображение и пользовательскую информацию в маркер?
4 ответа:
на 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)));
как это просто заменяет маркер с изображением вы можете использовать
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
наGoogleMap mMap
. Код должен (в основном) говорить сам за себя, есть много учебников там, как рисоватьCanvas
. Вы можете начать с глядя на холст и рисунки со страницы разработчика Android.теперь вы также хотите загрузить изображение с 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 или волейбол или RxJava для этого).
после этого вы можете заменить
BitmapFactory.decodeResource(getResources(), R.drawable.user_picture_image)
с загруженным изображениемbmImg
.
альтернативным и более простым решением, которое я также использую, является создание пользовательского макета маркера и преобразование его в растровое изображение.
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; }
добавьте свой пользовательский маркер на карту готового обратного вызова.
@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)))); }
для получения более подробной информации, пожалуйста, перейдите по ссылке ниже
Я надеюсь, что это еще не слишком поздно, чтобы поделиться своим решением. Перед этим вы можете следовать учебнику, как указано в документация для разработчиков Android. Для этого необходимо использовать диспетчер кластеров с
defaultRenderer
.
создать объект, который реализует
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); }
создать класс визуализации по умолчанию. Это класс, который выполняет всю работу (надувание пользовательского маркера/кластера с вашим собственным стилем). Я использую универсальный загрузчик изображений для загрузки и кэширования изображения.
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; }
применить диспетчер кластеров в классе activity / fragment.
public class SampleActivity extends AppCompatActivity implements OnMapReadyCallback { private ClusterManager<SampleJob> 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<SampleJob>(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 SampleJob job: jobs){ mClusterManager.addItem(job); } mClusterManager.cluster(); }
результат
из лямбда-ответа я сделал что-то ближе к требованиям.
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); } }