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:
Using xml Syntax Highlighting
- <?xml version="1.0" encoding="utf-8"?>
- <RelativeLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent">
- <com.google.android.maps.MapView
- android:id="@+id/map"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:apiKey="00yHj0k7_7vxbuQ9zwyXI4bNMJrAjYrJ9KKHgbQ"
- android:clickable="true" />
- </RelativeLayout>
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
Using java Syntax Highlighting
- /* Copyright (c) 2008-2011 -- CommonsWare, LLC
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
- http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- */
- package com.commonsware.android.maps;
- import java.util.ArrayList;
- import java.util.List;
- import android.graphics.drawable.Drawable;
- import android.os.Bundle;
- import android.view.KeyEvent;
- import android.view.View;
- import android.view.View.OnClickListener;
- import android.view.ViewGroup;
- import android.widget.FrameLayout;
- import android.widget.TextView;
- import com.google.android.maps.GeoPoint;
- import com.google.android.maps.ItemizedOverlay;
- import com.google.android.maps.MapActivity;
- import com.google.android.maps.MapView;
- import com.google.android.maps.MyLocationOverlay;
- import com.google.android.maps.OverlayItem;
- public class NooYawk extends MapActivity {
- private MapView map = null;
- private MyLocationOverlay me = null;
- private View viewBubble;
- private ViewGroup parentBubble;
- <span style="font-weight: bold">private OverlayItem item;
- private GeoPoint geo;</span>
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
- map = (MapView) findViewById(R.id.map);
- map.getController().setCenter(
- getPoint(40.76793169992044, -73.98180484771729));
- map.getController().setZoom(17);
- map.setBuiltInZoomControls(true);
- Drawable marker = getResources().getDrawable(R.drawable.marker);
- marker.setBounds(0, 0, marker.getIntrinsicWidth(),
- marker.getIntrinsicHeight());
- map.getOverlays().add(new SitesOverlay(marker));
- me = new MyLocationOverlay(this, map);
- map.getOverlays().add(me);
- }
- @Override
- public void onResume() {
- super.onResume();
- me.enableCompass();
- }
- @Override
- public void onPause() {
- super.onPause();
- me.disableCompass();
- }
- @Override
- protected boolean isRouteDisplayed() {
- return (false);
- }
- @Override
- public boolean onKeyDown(int keyCode, KeyEvent event) {
- if (keyCode == KeyEvent.KEYCODE_S) {
- map.setSatellite(!map.isSatellite());
- return (true);
- } else if (keyCode == KeyEvent.KEYCODE_Z) {
- map.displayZoomControls(true);
- return (true);
- }
- return (super.onKeyDown(keyCode, event));
- }
- private GeoPoint getPoint(double lat, double lon) {
- return (new GeoPoint((int) (lat * 1000000.0), (int) (lon * 1000000.0)));
- }
- private class SitesOverlay extends ItemizedOverlay<OverlayItem> {
- private List<OverlayItem> items = new ArrayList<OverlayItem>();
- private Drawable marker = null;
- public SitesOverlay(Drawable marker) {
- super(marker);
- this.marker = marker;
- boundCenterBottom(marker);
- items.add(new OverlayItem(getPoint(40.748963847316034,
- -73.96807193756104), "UN", "United Nations"));
- items.add(new OverlayItem(getPoint(40.76866299974387,
- -73.98268461227417), "Lincoln Center",
- "Home of Jazz at Lincoln Center"));
- items.add(new OverlayItem(getPoint(40.765136435316755,
- -73.97989511489868), "Carnegie Hall",
- "Where you go with practice, practice, practice"));
- items.add(new OverlayItem(getPoint(40.70686417491799,
- -74.01572942733765), "The Downtown Club",
- "Original home of the Heisman Trophy"));
- populate();
- }
- @Override
- protected OverlayItem createItem(int i) {
- return (items.get(i));
- }
- @Override
- protected boolean onTap(int i) {
- <span style="font-weight: bold">item = getItem(i);
- geo = item.getPoint();
- addBubble(geo);</span> //We call the functtion addbubble passing the position of the item tapped
- return (true);
- }
- @Override
- public int size() {
- return (items.size());
- }
- }
- //the main function about bubble
- private void addBubble(GeoPoint point) {
- //if there isn't any bubble on the screen enter
- if (viewBubble == null) {
- parentBubble = (ViewGroup) map.getParent();
- //We inflate the view with the bubble
- viewBubble = getLayoutInflater().inflate(R.layout.bubble,
- parentBubble, false);
- //to position the bubble over the map. The -128 and -150 are the offset.
- MapView.LayoutParams mvlp = new MapView.LayoutParams(
- MapView.LayoutParams.WRAP_CONTENT,
- MapView.LayoutParams.WRAP_CONTENT, geo, -128, -150,
- MapView.LayoutParams.LEFT);
- FrameLayout f = (FrameLayout) viewBubble;
- //Fill the text
- ((TextView) f.findViewById(R.id.bubbleText))
- .setText("Great Bubble!!");
- // ((TextView)((FrameLayout)viewBubble))).findViewById(R.id.bubbleText))))
- //And the event.
- viewBubble.setOnClickListener(new OnClickListener() {
- //When we touch the bubble it is removed. And make null viewBubble to reuse it.
- @Override
- public void onClick(View v) {
- map.removeView(viewBubble);
- viewBubble = null;
- }
- });
- //As you see, add in the map.
- map.addView(viewBubble, mvlp);
- }
- }
- }
Parsed in 0.049 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.



