studio - Cómo crear un marcador de mapa de bits de forma personalizada con la API de Android v2
marker android (4)
Esta pregunta ya tiene una respuesta aquí:
Estoy desarrollando una aplicación para Android en la que estoy usando Google Map API v2. Necesito mostrar la ubicación del usuario en un mapa con marcadores personalizados.
Cada marcador mostrará la imagen del usuario desde una URL. La imagen debe descargarse en modo asíncrono desde el servidor. Vea la captura de pantalla adjunta para ver un ejemplo.
¿Cómo agrego una imagen e información personalizada en el marcador?
De la respuesta de lambda, he hecho algo más cercano a los requisitos.
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);
}
}
Espero que todavía no sea tarde para compartir mi solución. Antes de eso, puedes seguir el tutorial como se indica en la documentación del desarrollador de Android . Para lograr esto, debe usar el Administrador de clústeres con defaultRenderer
.
Crear un objeto que implemente
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); }
Crea una clase de procesador predeterminada. Esta es la clase que hace todo el trabajo (inflar marcador personalizado / clúster con su propio estilo). Estoy usando el cargador de imágenes Universal para realizar la descarga y el almacenamiento en caché de la imagen.
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; }
Aplica el administrador de clúster en tu clase de actividad / fragmento.
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<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 SampleJob job: jobs){ mClusterManager.addItem(job); } mClusterManager.cluster(); }
Resultado
La solución alternativa y más sencilla que también uso es crear un diseño de marcador personalizado y convertirlo en un mapa de bits.
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>
Convierta esta vista en mapa de bits usando el siguiente código
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;
}
Agregue su marcador personalizado en la devolución de llamada de Map ready.
@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))));
}
Para obtener más información, siga el enlace a continuación
En Google Maps API v2 Demo, hay una clase MarkerDemoActivity
en la que puede ver cómo se establece una imagen personalizada en un mapa de Google .
// Uses a custom icon.
mSydney = mMap.addMarker(new MarkerOptions()
.position(SYDNEY)
.title("Sydney")
.snippet("Population: 4,627,300")
.icon(BitmapDescriptorFactory.fromResource(R.drawable.arrow)));
Como esto simplemente reemplaza el marcador con una imagen, es posible que desee utilizar un Canvas
para dibujar cosas más complejas y elegantes:
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));
Esto dibuja Canvas canvas1
en GoogleMap mMap
. El código debería (en su mayoría) hablar por sí mismo, hay muchos tutoriales que describen cómo dibujar un Canvas
. Puede comenzar mirando el lienzo y los Drainage de la página del desarrollador de Android.
Ahora también quieres descargar una imagen de una 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);
Debe descargar la imagen de un hilo de fondo (podría usar AsyncTask o Volley para eso).
Después de eso, puede reemplazar BitmapFactory.decodeResource(getResources(), R.drawable.user_picture_image)
con la imagen descargada bmImg
.