2013-02-11 8 views
133

Я разрабатываю приложение для Android, где я использую API карт Google v2. Мне нужно показать местоположение пользователя на карте с помощью пользовательских маркеров.Как создать пользовательский растровый маркер с Android map API v2

Каждый маркер отобразит изображение пользователя по URL-адресу. Изображение должно быть загружено в асинхронном режиме с сервера. См. Прилагаемый скриншот для примера.

Как добавить изображение и пользовательскую информацию в маркер?

enter image description here

+9

Я не знаю, почему мой вопрос закрыт. Пожалуйста, помогите мне. –

+45

Я чувствую, что это реальный вопрос. У меня также есть такое требование. Я не мог найти решение в GoogleMapDocs. Но они всегда ищут ответы на вопросы, если они не знают ответа. –

+6

Согласитесь, это правильный вопрос. Возможно, название должно быть: Android map api v2, пользовательский растровый маркер. –

ответ

158

В 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. Вы можете начать с просмотра Canvas and Drawables со страницы разработчика для 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 или Volley для этого).

После этого вы можете заменить BitmapFactory.decodeResource(getResources(), R.drawable.user_picture_image) на скаченное изображение bmImg.

+18

Отличный ответ, за исключением URL-адреса. Вы загружаете это изображение в основной поток приложений, что является чрезвычайно плохой идеей. Из-за этого ваш код будет разбит на Android 4.0+. «Might» слишком слабо сказано здесь - вы должны * загрузить изображение в фоновом потоке, чтобы избежать janky UI, не говоря уже о 'NetworkOnMainThreadException'. – CommonsWare

+1

@ lambda k мы загружаем изображения с фоновым потоком, я не понимаю, сэр, когда мы получаем широту, долготу и url из веб-службы, а затем как быстро конвертировать URL в растровое изображение –

+0

new AsyncTask () { protected void onPostExecute (результат битмапа) { image.setImageBitmap (результат); }; @Override защищенный Bitmap doInBackground (Void ... params) { return Utils.loadBitmap (url); } } .execute(); – sonida

62

Альтернативное и простое решение, которое я также использую, заключается в создании настраиваемого макета маркера и преобразовании его в растровое изображение.

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

Для получения более подробной информации, пожалуйста, перейдите по ссылке ниже

How to create custom marker using layout?

+0

PLS проверяет ваш ответ. ndefined 'view'? – dit

+0

@dit Спасибо, что указали, что я обновил свой ответ. Фактически его customMarkerView – waleedsarwar86

+0

без проблем! Эта же проблема находится в вашем сообщении в блоге;) – dit

10

Я надеюсь, что он все еще не слишком поздно, чтобы разделить мое решение. До этого вы можете следить за учебником, как указано в Android Developer documentation. Для этого вам необходимо использовать Cluster Manager с defaultRenderer.

  1. Создайте объект, который реализует 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. Создать класс рендерер по умолчанию. Это класс, который выполняет всю работу (раздувая пользовательский маркер/кластер своим стилем). Я использую Universal image loader для загрузки и кэширования изображения.

    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; 
    } 
    
  3. Применить диспетчер кластера в своем классе активности/фрагмента.

    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(); 
    } 
    
  4. Результат

Result

+0

Не могли бы вы указать зависимости для этого подхода? Большая часть базы кода не учитывается. –

+0

Является ли класс «Job» ссылкой на «com.evernote: android-job: 1.2.1» lib? –

+0

@JonDunn «Работа» в этом примере - это пользовательский класс. Это зависимость, которую я использовал: compile 'com.google.maps.android:android-maps-utils:0.5+. Дополнительную информацию можно найти здесь: https://developers.google.com/maps/documentation/android-api/utility/marker-clustering#introduction –

1

Из лямбда-ответа, я сделал что-то ближе к требованиям.

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

} 
Смежные вопросы