Jun 26, 2012

Custom MapView

Refer to my old example of MapView http://android-coding.blogspot.com/2011/06/easy-drawing-current-location-and.html; It's a simple example of using MapView, with everything implement in main activity.

In this article, I'm going to implement a custom MyMapView extends MapView. Most of the routine works will be moved in MyMapView, include MyItemizedOverlay, MyLocationOverlay and some initialization such as setClickable(true), setBuiltInZoomControls(true)...etc. Such that the main activity will become simple and clear.

Custom MapView


Refer to the articles to obtain Maps API Key and MapActivity.

Create a new Android project Target Android 2.3.3 with Google APIs.

Create a new class MyMapView extends MapView. Basically it perform the same works of the example in http://android-coding.blogspot.com/2011/06/easy-drawing-current-location-and.html, with almost everything move in.

package com.AndroidCustomMapView;

import java.util.ArrayList;

import android.content.Context;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;

import com.google.android.maps.GeoPoint;
import com.google.android.maps.ItemizedOverlay;
import com.google.android.maps.MapView;
import com.google.android.maps.MyLocationOverlay;
import com.google.android.maps.OverlayItem;

public class MyMapView extends MapView {

 MyItemizedOverlay myItemizedOverlay = null;
 MyLocationOverlay myLocationOverlay = null;

 public MyMapView(Context context, String apiKey) {
  super(context, apiKey);
  init(context);
 }

 public MyMapView(Context context, AttributeSet attrs) {
  super(context, attrs);
  init(context);
 }

 public MyMapView(Context context, AttributeSet attrs, int defStyle) {
  super(context, attrs, defStyle);
  init(context);
 }
 
 private void init(Context ctx){
  setClickable(true);
  setBuiltInZoomControls(true);
  
  Drawable marker=getResources().getDrawable(android.R.drawable.star_big_on);
  int markerWidth = marker.getIntrinsicWidth();
  int markerHeight = marker.getIntrinsicHeight();
  marker.setBounds(0, markerHeight, markerWidth, 0);
  
  myItemizedOverlay = new MyItemizedOverlay(marker);
  getOverlays().add(myItemizedOverlay);
  
  myLocationOverlay = new MyLocationOverlay(ctx, this);
  getOverlays().add(myLocationOverlay);
  
 }
 
 public void addMarker(GeoPoint p, String title, String snippet){
  myItemizedOverlay.addItem(p, title, snippet);
 }
 
 public void callOnResume(){
  myLocationOverlay.enableMyLocation();
  myLocationOverlay.enableCompass();
 }
 
 public void callOnPause(){
  myLocationOverlay.disableMyLocation();
  myLocationOverlay.disableCompass();
 }
 
 public class MyItemizedOverlay extends ItemizedOverlay<OverlayItem> {
  
  private ArrayList<OverlayItem> overlayItemList = new ArrayList<OverlayItem>();

  public MyItemizedOverlay(Drawable defaultMarker) {
   //super(defaultMarker);
   super(boundCenterBottom(defaultMarker));
   populate();
  }

  @Override
  protected OverlayItem createItem(int i) {
   return overlayItemList.get(i);
  }

  @Override
  public int size() {
   return overlayItemList.size();
  }
  
  public void addItem(GeoPoint p, String title, String snippet){
   OverlayItem newItem = new OverlayItem(p, title, snippet);
   overlayItemList.add(newItem);
   populate(); 
  }

 }

}


Modify main.xml to add <com.AndroidCustomMapView.MyMapView> in the layout.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/hello" />
    <com.AndroidCustomMapView.MyMapView
        android:id="@+id/mymapview"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:apiKey="--- Your own Maps API Key here ---"/>

</LinearLayout>


Modify the activity, AndroidCustomMapViewActivity to use our MyMapView. It become much clear now.
package com.AndroidCustomMapView;

import android.os.Bundle;

import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapActivity;

public class AndroidCustomMapViewActivity extends MapActivity {
 
 MyMapView myMapView;
 
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        myMapView = (MyMapView)findViewById(R.id.mymapview);
        
        GeoPoint myPoint1 = new GeoPoint(0*1000000, 0*1000000);
        myMapView.addMarker(myPoint1, "myPoint1", "myPoint1");
        GeoPoint myPoint2 = new GeoPoint(50*1000000, 50*1000000);
        myMapView.addMarker(myPoint2, "myPoint2", "myPoint2");
    }

 @Override
 protected boolean isRouteDisplayed() {
  // TODO Auto-generated method stub
  return false;
 }

 @Override
 protected void onPause() {
  // TODO Auto-generated method stub
  super.onPause();
  myMapView.callOnPause();
 }

 @Override
 protected void onResume() {
  // TODO Auto-generated method stub
  super.onResume();
  myMapView.callOnResume();
 }

}


Remember to modify AndroidManifest.xml to include uses-library of "com.google.android.maps", and grant permission of "android.permission.INTERNET" and "android.permission.ACCESS_FINE_LOCATION".
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.AndroidCustomMapView"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk android:minSdkVersion="10" />
    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        <uses-library android:name="com.google.android.maps" />
        <activity
            android:name=".AndroidCustomMapViewActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>


2 comments:

  1. How can we use this same approach of a Custom MapView in the new Google Maps APIv2? Need Help - Thanks!

    ReplyDelete
    Replies
    1. This comment has been removed by a blog administrator.

      Delete

Infolinks In Text Ads