Here is my first tutorial on Android development.
The purpose of this tutorial is to create custom marker for Google Maps using a layout containing a customizable TextView.
First thing to do, install and configure Google Maps API v2 to obtain an API key (to put in the file manifest.xml).
All the information is here:
http://developer.android.com/google/play-services/maps.html
And to get the api key is here:
https://code.google.com/apis/console/
We create the layout of the application by specifying a fragment referring to the Google Map API (com.google.android.gms.maps.SupportMapFragment).
layout/map_layout.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 | <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="#FFFFFF" > <fragment android:id="@+id/map" android:name="com.google.android.gms.maps.SupportMapFragment" android:layout_width="fill_parent" android:layout_height="fill_parent" /> </RelativeLayout> |
We create a layout with a TextView (dynamic) and ImageView. It will be converted into bitmap to display in the map.
layout/custom_marker_layout.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | <?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content" > <ImageView android:layout_width="55dp" android:layout_height="65dp" android:src="@drawable/custom_marker" /> <TextView android:id="@+id/num_txt" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="8dp" android:layout_marginTop="5dp" android:gravity="center" android:text="20" android:textColor="#ce8223" android:textSize="25dp" android:textStyle="bold" /> </RelativeLayout> |
In CustomMapMarker class, we setup the map (tutorial here).
We get the layout custom_marker_layout with layout inflater service, we change our TextView and convert the view result into a bitmap (with createDrawableFromView method).
CustomMapMarker.class
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 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 | public class CustomMapMarker extends FragmentActivity { private GoogleMap mMap; private Marker customMarker; private LatLng markerLatLng; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.map_layout); markerLatLng = new LatLng(48.8567,2.3508); setUpMapIfNeeded(); } private void setUpMapIfNeeded() { // Do a null check to confirm that we have not already instantiated the // map. if (mMap == null) { // Try to obtain the map from the SupportMapFragment. mMap = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map)).getMap(); // Check if we were successful in obtaining the map. if (mMap != null) { setUpMap(); } } } private void setUpMap() { View marker = ((LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.custom_marker_layout, null); TextView numTxt = (TextView) marker.findViewById(R.id.num_txt); numTxt.setText("27"); customMarker = mMap.addMarker(new MarkerOptions() .position(markerLatLng) .title("Title") .snippet("Description") .icon(BitmapDescriptorFactory.fromBitmap(createDrawableFromView(this, marker)))); final View mapView = getSupportFragmentManager().findFragmentById(R.id.map).getView(); if (mapView.getViewTreeObserver().isAlive()) { mapView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() { @SuppressLint("NewApi") // We check which build version we are using. @Override public void onGlobalLayout() { LatLngBounds bounds = new LatLngBounds.Builder().include(markerLatLng).build(); if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) { mapView.getViewTreeObserver().removeGlobalOnLayoutListener(this); } else { mapView.getViewTreeObserver().removeOnGlobalLayoutListener(this); } mMap.moveCamera(CameraUpdateFactory.newLatLngBounds(bounds, 50)); } }); } } // Convert a view to bitmap public static Bitmap createDrawableFromView(Context context, View view) { DisplayMetrics displayMetrics = new DisplayMetrics(); ((Activity) context).getWindowManager().getDefaultDisplay().getMetrics(displayMetrics); view.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); view.measure(displayMetrics.widthPixels, displayMetrics.heightPixels); view.layout(0, 0, displayMetrics.widthPixels, displayMetrics.heightPixels); view.buildDrawingCache(); Bitmap bitmap = Bitmap.createBitmap(view.getMeasuredWidth(), view.getMeasuredHeight(), Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(bitmap); view.draw(canvas); return bitmap; } } |
Preview:

Google Maps Android API v2 useful links:
https://developers.google.com/maps/documentation/android/start
https://developers.google.com/maps/documentation/android/map
https://code.google.com/apis/console/
http://developer.android.com/google/play-services/index.html
Project sources on GitHub:
https://github.com/Nasc/CustomMapMarker