Nice bubble in Android maps

Tutorials that use the MapActivity. Many using GPS functionality.

Nice bubble in Android maps

Postby eldruida » Sun May 01, 2011 10:21 am

Hi,

I've been looking for a good label for android google maps for long time. As I didn't found any I like. I decide to learn how to improve one by myself picking examples from here and there.

The project is based on Commonsware nooyawk

First we create an xml for the bubble:
Code: Select all
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
   xmlns:android="http://schemas.android.com/apk/res/android"
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   android:id="@+id/popBub">


   <TextView
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:text="test text"
      android:maxEms="20"

      android:background="@drawable/bub"
      android:gravity="center">
   </TextView>
</FrameLayout>


As you can see I added the option maxEms so it will break lines. Since the bubble expands horitzontaly and vertically using 9 patch.

This is a normal xml mapView:
Syntax: [ Download ] [ Hide ]
Using xml Syntax Highlighting
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <RelativeLayout
  3.         xmlns:android="http://schemas.android.com/apk/res/android"
  4.         android:layout_width="fill_parent"
  5.         android:layout_height="fill_parent">
  6.         <com.google.android.maps.MapView
  7.                 android:id="@+id/map"
  8.                 android:layout_width="fill_parent"
  9.                 android:layout_height="fill_parent"
  10.                 android:apiKey="00yHj0k7_7vxbuQ9zwyXI4bNMJrAjYrJ9KKHgbQ"
  11.                 android:clickable="true" />
  12. </RelativeLayout>
  13.  
  14.  
Parsed in 0.002 seconds, using GeSHi 1.0.8.4


Now the code:
I'm going to bold what I changed and comment it
Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1. /* Copyright (c) 2008-2011 -- CommonsWare, LLC
  2.  
  3.          Licensed under the Apache License, Version 2.0 (the "License");
  4.          you may not use this file except in compliance with the License.
  5.          You may obtain a copy of the License at
  6.  
  7.                  http://www.apache.org/licenses/LICENSE-2.0
  8.  
  9.          Unless required by applicable law or agreed to in writing, software
  10.          distributed under the License is distributed on an "AS IS" BASIS,
  11.          WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12.          See the License for the specific language governing permissions and
  13.          limitations under the License.
  14.  */
  15.  
  16. package com.commonsware.android.maps;
  17.  
  18. import java.util.ArrayList;
  19. import java.util.List;
  20.  
  21. import android.graphics.drawable.Drawable;
  22. import android.os.Bundle;
  23. import android.view.KeyEvent;
  24. import android.view.View;
  25. import android.view.View.OnClickListener;
  26. import android.view.ViewGroup;
  27. import android.widget.FrameLayout;
  28. import android.widget.TextView;
  29.  
  30. import com.google.android.maps.GeoPoint;
  31. import com.google.android.maps.ItemizedOverlay;
  32. import com.google.android.maps.MapActivity;
  33. import com.google.android.maps.MapView;
  34. import com.google.android.maps.MyLocationOverlay;
  35. import com.google.android.maps.OverlayItem;
  36.  
  37. public class NooYawk extends MapActivity {
  38.         private MapView map = null;
  39.         private MyLocationOverlay me = null;
  40.         private View viewBubble;
  41.         private ViewGroup parentBubble;
  42.         <span style="font-weight: bold">private OverlayItem item;
  43.         private GeoPoint geo;</span>
  44.  
  45.         @Override
  46.         public void onCreate(Bundle savedInstanceState) {
  47.                 super.onCreate(savedInstanceState);
  48.                 setContentView(R.layout.main);
  49.  
  50.                 map = (MapView) findViewById(R.id.map);
  51.  
  52.                 map.getController().setCenter(
  53.                                 getPoint(40.76793169992044, -73.98180484771729));
  54.                 map.getController().setZoom(17);
  55.                 map.setBuiltInZoomControls(true);
  56.  
  57.                 Drawable marker = getResources().getDrawable(R.drawable.marker);
  58.  
  59.                 marker.setBounds(0, 0, marker.getIntrinsicWidth(),
  60.                                 marker.getIntrinsicHeight());
  61.  
  62.                 map.getOverlays().add(new SitesOverlay(marker));
  63.  
  64.                 me = new MyLocationOverlay(this, map);
  65.                 map.getOverlays().add(me);
  66.         }
  67.  
  68.         @Override
  69.         public void onResume() {
  70.                 super.onResume();
  71.  
  72.                 me.enableCompass();
  73.         }
  74.  
  75.         @Override
  76.         public void onPause() {
  77.                 super.onPause();
  78.  
  79.                 me.disableCompass();
  80.         }
  81.  
  82.         @Override
  83.         protected boolean isRouteDisplayed() {
  84.                 return (false);
  85.         }
  86.  
  87.         @Override
  88.         public boolean onKeyDown(int keyCode, KeyEvent event) {
  89.                 if (keyCode == KeyEvent.KEYCODE_S) {
  90.                         map.setSatellite(!map.isSatellite());
  91.                         return (true);
  92.                 } else if (keyCode == KeyEvent.KEYCODE_Z) {
  93.                         map.displayZoomControls(true);
  94.                         return (true);
  95.                 }
  96.  
  97.                 return (super.onKeyDown(keyCode, event));
  98.         }
  99.  
  100.         private GeoPoint getPoint(double lat, double lon) {
  101.                 return (new GeoPoint((int) (lat * 1000000.0), (int) (lon * 1000000.0)));
  102.         }
  103.  
  104.         private class SitesOverlay extends ItemizedOverlay<OverlayItem> {
  105.                 private List<OverlayItem> items = new ArrayList<OverlayItem>();
  106.                 private Drawable marker = null;
  107.  
  108.                 public SitesOverlay(Drawable marker) {
  109.                         super(marker);
  110.                         this.marker = marker;
  111.  
  112.                         boundCenterBottom(marker);
  113.  
  114.                         items.add(new OverlayItem(getPoint(40.748963847316034,
  115.                                         -73.96807193756104), "UN", "United Nations"));
  116.                         items.add(new OverlayItem(getPoint(40.76866299974387,
  117.                                         -73.98268461227417), "Lincoln Center",
  118.                                         "Home of Jazz at Lincoln Center"));
  119.                         items.add(new OverlayItem(getPoint(40.765136435316755,
  120.                                         -73.97989511489868), "Carnegie Hall",
  121.                                         "Where you go with practice, practice, practice"));
  122.                         items.add(new OverlayItem(getPoint(40.70686417491799,
  123.                                         -74.01572942733765), "The Downtown Club",
  124.                                         "Original home of the Heisman Trophy"));
  125.  
  126.                         populate();
  127.                 }
  128.  
  129.                 @Override
  130.                 protected OverlayItem createItem(int i) {
  131.                         return (items.get(i));
  132.                 }
  133.  
  134.                 @Override
  135.                 protected boolean onTap(int i) {
  136.  
  137.                         <span style="font-weight: bold">item = getItem(i);
  138.                         geo = item.getPoint();
  139.                         addBubble(geo);</span> //We call the functtion addbubble passing the position of the item tapped
  140.                         return (true);
  141.                 }
  142.  
  143.                 @Override
  144.                 public int size() {
  145.                         return (items.size());
  146.                 }
  147.         }
  148.        
  149. //the main function about bubble
  150.         private void addBubble(GeoPoint point) {
  151.  
  152. //if there isn't any bubble on the screen enter
  153.                 if (viewBubble == null) {
  154.  
  155.                         parentBubble = (ViewGroup) map.getParent();
  156.                        //We inflate the view with the bubble
  157.                         viewBubble = getLayoutInflater().inflate(R.layout.bubble,
  158.                                         parentBubble, false);
  159.  
  160.                         //to position the bubble over the map. The -128 and -150 are the offset.
  161.                         MapView.LayoutParams mvlp = new MapView.LayoutParams(
  162.                                         MapView.LayoutParams.WRAP_CONTENT,
  163.                                         MapView.LayoutParams.WRAP_CONTENT, geo, -128, -150,
  164.                                         MapView.LayoutParams.LEFT);
  165.  
  166.                         FrameLayout f = (FrameLayout) viewBubble;
  167. //Fill the text
  168.                         ((TextView) f.findViewById(R.id.bubbleText))
  169.                                         .setText("Great Bubble!!");
  170.  
  171.                         // ((TextView)((FrameLayout)viewBubble))).findViewById(R.id.bubbleText))))
  172. //And the event.
  173.                         viewBubble.setOnClickListener(new OnClickListener() {
  174.  
  175.  
  176.                                 //When we touch the bubble it is removed. And make null viewBubble to reuse it.
  177.                                 @Override
  178.                                 public void onClick(View v) {
  179.                                         map.removeView(viewBubble);
  180.                                         viewBubble = null;
  181.  
  182.                                 }
  183.                         });
  184.                         //As you see, add in the map.
  185.                         map.addView(viewBubble, mvlp);
  186.                 }
  187.         }
  188.  
  189. }
  190.  
Parsed in 0.050 seconds, using GeSHi 1.0.8.4


//Finaly I explain how works the 9 patch bubble for who doesn't understant entirelly. I'm included :)

As you can see the first image 1_bub has lines at left and and above. It determines which parts of the image will be stretched. If you look the blue round arrow isn't green, so never will be deformed. If the bubble is stretched alot horitzontally the spike would be deformed but it won't happen because we put ems text limit and multi line.

The 2_bub has more border black lines. They limit the content text. Look the right preview images. The text will be inside the blue parts wich put margins arround the text. As 9 patch is clever, when the text grows the image expands without deformation.

Well. thats all.

The example could contain some errors and it would be better programmed. So please improve it, I like learn. :)
Attachments
2_bub.png
2_bub.png (152.31 KiB) Viewed 4542 times
1_bub.png
1_bub.png (175.65 KiB) Viewed 4542 times
bub.9.png
9 patch bubble
bub.9.png (5.07 KiB) Viewed 4542 times
eldruida
Freshman
Freshman
 
Posts: 2
Joined: Mon Apr 25, 2011 7:21 pm

Top

Re: Nice bubble in Android maps

Postby onlineadr » Wed May 04, 2011 9:18 am

oh so thats what 9 patch does :)
onlineadr
Experienced Developer
Experienced Developer
 
Posts: 59
Joined: Thu Apr 28, 2011 12:45 pm

Re: Nice bubble in Android maps

Postby muxe » Tue Aug 09, 2011 1:49 pm

Nice Tutorial, it helped me a lot.
I would modify the top pixels in the 9patch to two areas of the same size left and right of the spike. This way the spike never gets stretched and stays in the middle.
Attachments
bub.9.png
bub.9.png (4.23 KiB) Viewed 3770 times
muxe
Once Poster
Once Poster
 
Posts: 1
Joined: Tue Aug 09, 2011 1:43 pm

Top

Return to Map Tutorials

Who is online

Users browsing this forum: Google Feedfetcher and 3 guests