Problema
Além de exibir um mapa centrado em um local específico, o aplicativo precisa colocar uma anotação com um marcador mais visível no local.
Solução
Criar um ItemizedOverlay personalizado para o mapa, que inclui todos os pontos para marcar. ItemizedOverlay é uma classe base abstrata que lida com todo o desenho dos itens individuais em um MapView. Os itens em si são as instâncias de OverlayItem, que é uma classe de modelo que define o nome, o subtítulo, e marcador drawable para descrever o ponto no mapa.
Como Funciona
Vamos criar uma implementação de ItemizedOverlay que terá uma série de GeoPoints e desenhá-los no mapa utilizando o mesmo marcador drawable para cada um. Veja.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | public class LocationOverlay extends ItemizedOverlay<OverlayItem> { private List<GeoPoint> mItems; public LocationOverlay(Drawable marker) { super(boundCenterBottom(marker)); } public void setItems(ArrayList<GeoPoint>items){ mItems = items; populate(); } @Override protected OverlayItem createItem(int i) { return new OverlayItem(mItems.get(i),null,null); } @Override public int size() { return mItems.size(); } @Override public boolean onTap(int i) { return true; } } |
Nesta implementação, o construtor tem uma Drawable para representar o marcador colocado no mapa em cada local. Drawables que são usados em sobreposições devem ter limites próprios aplicados a eles, e boundCenterBottom() é um método de conveniência que lida com isso para nós. Especificamente, aplica-se limites, de tal forma que o ponto no Drawable que toca o mapa de localização será no centro da linha inferior de pixels.
ItemizedOverlay tem dois métodos abstratos que devem ser substituídos: createItem(), que deve retornar um objeto do tipo declarado, e size(), que retorna o número de itens administrados. Este exemplo tem uma lista de GeoPoints e envolve todos em OverlayItems. O método de populate() deve ser chamado no overlay, logo que todos os dados estão presentes e prontos para exibição, que neste caso é no final de setItems().Vamos aplicar essa sobreposição para um mapa a desenhar três locais personalizados na cidade de Maringá-Pr, usando o ícone do aplicativo padrão como o marcador. Veja.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | public class PointMapsActivity extends MapActivity { MapView map; MapController controller; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); map = (MapView)findViewById(R.id.map); controller = map.getController(); ArrayList<GeoPoint> locais = new ArrayList<GeoPoint>(); //Catedral de Maringá locais.add(new GeoPoint(-23414922,-51938077)); //Parque do Ingá locais.add(new GeoPoint(-23424976,-51930056)); //Teatro Municipal Reviver locais.add(new GeoPoint(-23423243,-51922245)); LocationOverlay myOverlay = new LocationOverlay(getResources().getDrawable(R.drawable.icon)); myOverlay.setItems(locais); map.getOverlays().add(myOverlay); controller.setCenter(locais.get(0)); controller.setZoom(15); } @Override protected boolean isRouteDisplayed() { return false; } } |
Quando executar, essa Activity nos mostrará a seguinte tela.

Observe como o desenho da sombra projetada no marcador foi tratado por nós com MapView e o ItemizedOverlay.Mas, e se queremos personalizar cada item para que ele exiba uma imagem de marca diferente? Como poderíamos fazer isso? Definindo explicitamente marcador do item, um Drawable personalizado pode ser retornado para cada item. Neste caso, o Drawable fornecido para o construtor ItemizedOverlay é apenas um valor padrão a ser usado se não substituir por personalizadas existentes. Considere uma modificação para a implementação, mostrado no código a seguir.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | public class LocationOverlay extends ItemizedOverlay<OverlayItem> { private List<GeoPoint> mItems; private List<Drawable> mMarkers; public LocationOverlay(Drawable marker) { super(boundCenterBottom(marker)); } public void setItems(ArrayList<GeoPoint>items, ArrayList<Drawable> drawables){ mItems = items; mMarkers = drawables; populate(); } @Override protected OverlayItem createItem(int i) { OverlayItem item = new OverlayItem(mItems.get(i),null,null); item.setMarker(boundCenterBottom(mMarkers.get(i))); return item; } @Override public int size() { return mItems.size(); } @Override public boolean onTap(int i) { return true; } } |
Com essa modificação, o OverlayItems criados agora recebem uma imagem de marcador personalizado na forma de um Drawable correspondente ao índice do item em uma lista de imagens. Se o Drawable que você definiu tem estados, os estados pressionados e focados será exibida quando o item é selecionado ou tocada. Nosso exemplo modificado para usar a nova implementação parece com este código a seguir.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | public class PointMapsActivity extends MapActivity { MapView map; MapController controller; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); map = (MapView)findViewById(R.id.map); controller = map.getController(); ArrayList<GeoPoint> locais = new ArrayList<GeoPoint>(); ArrayList<Drawable> images = new ArrayList<Drawable>(); //Catedral de Maringá locais.add(new GeoPoint(-23425527,-51938295)); images.add(getResources().getDrawable(R.drawable.cathedral)); //Parque do Ingá locais.add(new GeoPoint(-23424976,-51930056)); images.add(getResources().getDrawable(R.drawable.forest)); //Teatro Municipal Reviver locais.add(new GeoPoint(-23423243,-51922245)); images.add(getResources().getDrawable(R.drawable.theater)); LocationOverlay myOverlay = new LocationOverlay(getResources().getDrawable(R.drawable.icon)); myOverlay.setItems(locais,images); map.getOverlays().add(myOverlay); controller.setCenter(locais.get(0)); controller.setZoom(15); } @Override protected boolean isRouteDisplayed() { return false; } } |
Agora nosso exemplo fornece uma imagem diferente para cada item que quiser mostrar no mapa. Especificamente, nós decidimos representar a real localização de diversos pontos turísticos da cidade com marcadores personalizados. Veja a figura abaixo.

Para torná-los interativos
Talvez você tenha notado o método OnTap() que foi definido na LocationOverlay, mas nunca foi utilizado. Outro recurso interessante da implementação base ItemizedOverlay é que ele lida com teste de clique e tem um método de conveniência quando um item específico que tocou, fazendo referência índice desse item. A partir deste método, você pode implementar outras funções, como mostrar um diálogo, iniciar uma nova atividade, ou qualquer outra ação que se encaixa no contexto do usuário tocando na marcação para mais informações. Bom espero que tenham gostado dessa dica e até a próxima.



