185 votes

Comment créer un marqueur bitmap personnalisé avec l'API de carte Android v2

Je suis en train de développer une application Android où j'utilise Google Map API v2. J'ai besoin d'afficher la localisation de l'utilisateur sur une carte avec des marqueurs personnalisés.

Chaque marqueur affichera la photo de l'utilisateur à partir d'une URL. L'image doit être téléchargée de manière asynchrone depuis le serveur. Voir la capture d'écran ci-jointe pour un exemple.

Comment puis-je ajouter une image et des informations personnalisées dans le marqueur?

entrer la description de l'image ici

220voto

lambda Points 737

Dans la Démo de l'API Google Maps v2, il y a une classe MarkerDemoActivity dans laquelle vous pouvez voir comment une image personnalisée est définie pour une GoogleMap.

// Utilise une icône personnalisée.
mSydney = mMap.addMarker(new MarkerOptions()
    .position(SYDNEY)
    .title("Sydney")
    .snippet("Population : 4 627 300")
    .icon(BitmapDescriptorFactory.fromResource(R.drawable.arrow)));

Comme cela remplace simplement le marqueur par une image, vous voudrez peut-être utiliser un Canvas pour dessiner des choses plus complexes et plus fantaisistes :

Bitmap.Config conf = Bitmap.Config.ARGB_8888;
Bitmap bmp = Bitmap.createBitmap(80, 80, conf);
Canvas canvas1 = new Canvas(bmp);

// paint définit la couleur du texte, la largeur du trait et la taille
Paint color = new Paint();
color.setTextSize(35);
color.setColor(Color.BLACK);

// modifier le canvas
canvas1.drawBitmap(BitmapFactory.decodeResource(getResources(),
    R.drawable.user_picture_image), 0,0, color);
canvas1.drawText("Nom de l'utilisateur !", 30, 40, color);

// ajouter un marqueur à la carte
mMap.addMarker(new MarkerOptions()
    .position(POSITION_UTILISATEUR)
    .icon(BitmapDescriptorFactory.fromBitmap(bmp))
    // Spécifie l'ancre à un point particulier dans l'image du marqueur.
    .anchor(0.5f, 1));

Cela dessine le Canvas canvas1 sur le GoogleMap mMap. Le code devrait (principalement) se comprendre de lui-même, il existe de nombreux tutoriels expliquant comment dessiner un Canvas. Vous pouvez commencer en regardant la documentation sur le Canvas et les Drawables de la page des développeurs Android.

Maintenant, vous voulez également télécharger une image depuis une URL.

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

Vous devez télécharger l'image depuis un thread de fond (vous pourriez utiliser AsyncTask ou Volley ou RxJava pour cela).

Après cela, vous pouvez remplacer BitmapFactory.decodeResource(getResources(), R.drawable.user_picture_image) par votre image téléchargée bmImg.

104voto

Waleed Sarwar Points 665

La solution alternative et plus simple que j'utilise également est de créer une mise en page de marqueur personnalisée et de la convertir en bitmap.

view_custom_marker.xml

Convertissez cette vue en bitmap en utilisant le code ci-dessous

 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;
    }

Ajoutez votre marqueur personnalisé dans le rappel 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;
    }

    // ajout d'un marqueur sur la carte avec une image de drawable
   mGoogleMap.addMarker(new MarkerOptions()
            .position(mDummyLatLng)
            .icon(BitmapDescriptorFactory.fromBitmap(getMarkerBitmapFromView(R.drawable.avatar))));
}

16voto

Amad Yus Points 1889

J'espère qu'il n'est pas trop tard pour partager ma solution. Avant cela, vous pouvez suivre le tutoriel tel qu'indiqué dans la documentation des développeurs Android. Pour y parvenir, vous devez utiliser le Gestionnaire de clusters avec defaultRenderer.

  1. Créez un objet qui implémente ClusterItem

    public class SampleJob implements ClusterItem {
    
    private double latitude;
    private double longitude;
    
    //Créez le constructeur, les getters et les setters ici
    
    @Override
    public LatLng getPosition() {
        return new LatLng(latitude, longitude);
    }
  2. Créez une classe de rendu par défaut. C'est la classe qui fait tout le travail (gonfler un marqueur/cluster personnalisé avec votre propre style). J'utilise Universal Image Loader pour télécharger et mettre en cache l'image.

    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 clusterManager) {
        super(context, map, clusterManager);
    
        // initialiser le générateur d'icônes de cluster
        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);
    
        // initialiser le générateur d'icônes d'éléments de cluster
        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 cluster, MarkerOptions markerOptions) {
    
        Iterator 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. Appliquez le gestionnaire de clusters dans votre classe d'activité/fragment.

    public class SampleActivity extends AppCompatActivity implements OnMapReadyCallback {
    
    private ClusterManager mClusterManager;
    private GoogleMap mMap;
    private ArrayList jobs = new ArrayList();
    
    @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(this, mMap);
        mClusterManager.setRenderer(new JobRenderer(this, mMap, mClusterManager));
        mMap.setOnCameraChangeListener(mClusterManager);
        mMap.setOnMarkerClickListener(mClusterManager);
    
        // Supposons que nous ayons déjà une arraylist de jobs
    
        for(final SampleJob job: jobs){
            mClusterManager.addItem(job);
        }
        mClusterManager.cluster();
    }
  4. Résultat

Result

2voto

Muhammad Adil Points 121

De la réponse de lambda, j'ai fait quelque chose de plus proche des exigences.

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))
                // Spécifie l'ancre à un point particulier dans l'image de marqueur.
                .anchor(0.5f, 1));
    } else {
        currentLocationMarker.setPosition(currentLocation);
    }

}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X