android – Placing Zoom Controls in a MapView-ThrowExceptions

Exception or error:

I’m trying to get the zoom controls to show up in a mapview, the following code almost works, but the zoom controls appear in the top left of the mapview, not the bottom center like I’m specifying via setGravity(). Can someone enlighten me as to what I’m missing?

zoomView = (LinearLayout) mapView.getZoomControls();
zoomView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,ViewGroup.LayoutParams.WRAP_CONTENT)); 
zoomView.setGravity(Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL);
mapView.addView(zoomView);

These views/layouts are all constructed programmatically, there is no layout file to tweak.

How to solve:

Add the following line to the OnCreate() method of your MapView Class:

view.setBuiltInZoomControls(true);

###

The trick here is to place another Layout container where you want to put the ZoomControls and then insert the ZoomControls into that.

The real trick is to use the RelativeLayout rather than LinearLayout to position the elements, as shown in this sample layout.xml:

<?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/myMapView"
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent"
    android:enabled="true"
    android:clickable="true"
    android:apiKey="MY_MAP_API_KEY"
  />
  <LinearLayout android:id="@+id/layout_zoom" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:layout_alignParentBottom="true" 
    android:layout_centerHorizontal="true" 
  /> 
</RelativeLayout> 

The layout_zoom LinearLayout element is positioned in the bottom center of the screen, placing it over the middle/bottom of the MapView.

Then within your Activity’s onCreate, get a reference to the layout_zoom element and insert the ZoomControl into it, much like you’ve already done:

LinearLayout zoomLayout =(LinearLayout)findViewById(R.id.layout_zoom);  
View zoomView = myMapView.getZoomControls(); 
zoomLayout.addView(zoomView, new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); 
myMapView.displayZoomControls(true);

The ZoomControls should now appear on a long click, without stealing the map touch events.

###

The above didn’t work for me, but this does (to place the control on the bottom right):

mapView.setBuiltInZoomControls(true);
ZoomButtonsController zbc = mapView.getZoomButtonsController();
ViewGroup container = zbc.getContainer();
for (int i = 0; i < container.getChildCount(); i++) {
    View child = container.getChildAt(i);
    if (child instanceof ZoomControls) {
        FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) child.getLayoutParams();
        lp.gravity = Gravity.RIGHT | Gravity.BOTTOM;
        child.requestLayout();
        break;
    } 
}

###

Reto : thanks for your reply, but the idea was to do it without using XML layouts.

I eventually worked out the problem. Because a MapView is a subclass of ViewGroup, you can easily add child views (like the zoom controls). All you need is a MapView.LayoutParams instance and you’re good to go. I did something like this (puts zoom controls in the bottom center of the mapview).

  // layout to insert zoomcontrols at the bottom center of a mapview
  MapView.LayoutParams params = MapView.LayoutParams(
    LayoutParams.WRAP_CONTENT,
    LayoutParams.WRAP_CONTENT,
    mapViewWidth / 2, mapViewHeight,
    MapView.LayoutParams.BOTTOM_CENTER);

  // add zoom controls
  mapView.addView(mapView.getZoomControls(), params);

###

from the google groups thread i found this:

ZoomControls without XML:

   public class MyMapActivity extends MapActivity {  public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        RelativeLayout relativeLayout = new RelativeLayout(this);
        setContentView(relativeLayout);

        final MapView mapView = new MapView(this, DEBUG_MAP_API_KEY);
        RelativeLayout.LayoutParams mapViewLayoutParams = new
RelativeLayout.LayoutParams
(RelativeLayout.LayoutParams.FILL_PARENT,RelativeLayout.LayoutParams.FILL_PARENT );
        relativeLayout.addView(mapView, mapViewLayoutParams);

        RelativeLayout.LayoutParams zoomControlsLayoutParams = new
RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT );
        zoomControlsLayoutParams.addRule
(RelativeLayout.ALIGN_PARENT_BOTTOM);
        zoomControlsLayoutParams.addRule
(RelativeLayout.CENTER_HORIZONTAL);

        relativeLayout.addView(mapView.getZoomControls(),
zoomControlsLayoutParams);

        mapView.setClickable(true);
        mapView.setEnabled(true);

 } 

was 100% working for me with SDK1.1

###

Unfortunately I cant add a comment to Jason Hudgins approved solution from Nov 28 at 6:32 but I got a tiny error with his code:

In this line:

MapView.LayoutParams params = MapView.LayoutParams(

The error Eclipse gave me was

“The method LayoutParams(int, int,
int, int, int) is undefined for the
type MapView”

instead, creating a new MapView.LayoutParams object fixed it, like this:

MapView.LayoutParams params = **new** MapView.LayoutParams(

It took me some time to find out, as I am a n00b 😀

###

You can try this:

MapView map = (MapView)findViewById(R.id.mapview);
map.setBuiltInZoomControls(true);

###

Reto – the problem with using FILL_PARENT is that the zoom control then “steals” all of the touch events; so that you can’t pan the map while the zoom controls are visible. Do you know how to prevent this?

Leave a Reply

Your email address will not be published. Required fields are marked *