Custom zoom buttons

427 views
Skip to first unread message

emux

unread,
Mar 23, 2014, 9:06:39 AM3/23/14
to mapsfo...@googlegroups.com
(Continuing the conversation from here)

I remember mapsforge 0.3.X having support for min / max zoom levels, but with its default zoom controls.
Its MapZoomControls class has setZoomLevelMin / setZoomLevelMax methods.

For different drawable at each button state (normal, disabled, pressed) you need
the StateListDrawable class. Take a look at the guide here.

But (if possible) it's really advisable to move to rescue branch.
A lot of these issues have been reworked/resolved there
and you don't need to invent the wheel again.

Emux
Cruiser - Cruiser Beta
Atlas - Atlas Beta

Daniele Germano

unread,
Mar 24, 2014, 8:33:55 AM3/24/14
to mapsfo...@googlegroups.com
Thanks for your patience.

I use the StateListDrwawable but it has no effect for the maxzoom level.

this is my selector for zoom in

    <?xml version="1.0" encoding="utf-8"?>

  <selector xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:state_focused="true" android:drawable="@drawable/zoom_in_focus"/>

<item android:state_pressed="true" android:drawable="@drawable/zoom_in_focus" />

<item android:state_enabled="false" android:drawable="@drawable/max_zoom_reached"/>

<item android:drawable="@drawable/zoom_in" /> 

  </selector> 


And this is the Activity


        private static final File MAP_FILE = new File(Environment.getExternalStorageDirectory().getPath() + "/Bluetooth/", "isle.map");

private static final Byte MIN_ZOOM_LEVEL = new Byte("12");

private static final Byte MAX_ZOOM_LEVEL = new Byte("22");

private byte zoomLevelMax;

private byte zoomLevelMin;


private MyLocationOverlay myLocationOverlay;

MapView mapView;


        private void configureMapView() {

FileOpenResult fileOpenResult = this.mapView.setMapFile(MAP_FILE);

if (!fileOpenResult.isSuccess()) {

Toast.makeText(this, fileOpenResult.getErrorMessage(), Toast.LENGTH_LONG).show();

}

}


        @Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

this.mapView = (MapView) findViewById(R.id.mapView);

this.mapView.setBuiltInZoomControls(false);

this.mapView.setClickable(true);

MapFileInfo mapFileInfo = this.mapView.getMapDatabase().getMapFileInfo();

this.mapView.getMapViewPosition().setCenter(mapFileInfo.boundingBox.getCenterPoint());

this.mapView.setFocusable(true);


zoomLevelMin = MIN_ZOOM_LEVEL;

zoomLevelMax = MAX_ZOOM_LEVEL;

                this.mapView.getMapZoomControls().setZoomLevelMin(zoomLevelMin); 

                this.mapView.getMapZoomControls().setZoomLevelMax(zoomLevelMax);


                MapScaleBar mapScaleBar = this.mapView.getMapScaleBar();

mapScaleBar.setShowMapScaleBar(true);


                ImageButton zoomIn = (ImageButton) findViewById(R.id.zoomIn);

zoomIn.setBackgroundResource(R.drawable.action_click_zoom_in);

zoomIn.setOnClickListener(new View.OnClickListener() {

public void onClick(View v) {


    mapView.getMapViewPosition().zoomIn();

   

    }


});

ImageButton zoomOut = (ImageButton) findViewById(R.id.zoomOut);

zoomOut.setBackgroundResource(R.drawable.action_click_zoom_out);

zoomOut.setOnClickListener(new View.OnClickListener() {

public void onClick(View v) {

   

    mapView.getMapViewPosition().zoomOut();


    }

}); 

  

configureMapView();

}

}



Seems that the selector can not see when the maxzoom is reached and insert the icon max_zoom_reached

emux

unread,
Mar 24, 2014, 9:34:09 AM3/24/14
to mapsfo...@googlegroups.com
You have to set at the zoom buttons their state, depending on current zoom level.

For example check for zoom level changes and when zoom level
reaches min / max zoom level then call zoomButton.setEnabled(false).

If you follow the steps through MapZoomControls.onZoomLevelChange
you'll see what happens at ZoomControls src code.

--

Daniele Germano

unread,
Mar 24, 2014, 11:55:33 AM3/24/14
to mapsfo...@googlegroups.com
Hi
The onZoomLevelChange report this

void onZoomLevelChange(int newZoomLevel) {

boolean zoomInEnabled = newZoomLevel < this.zoomLevelMax;

boolean zoomOutEnabled = newZoomLevel > this.zoomLevelMin;


this.zoomControls.setIsZoomInEnabled(zoomInEnabled);

this.zoomControls.setIsZoomOutEnabled(zoomOutEnabled);

}


The problem is that i don't know ho to implement a similar function to my activity.

The onZoomLevelChange says that unti the current zoom in less than the max zoom, to set the zoom in enable.

But how can implement a similar function as you suggest, means, check the current zoom level and set the zoomButton.setEnabled(false) ?


I know that if i just put the zoomButton.setEnabled(false). inside the zoom max click method, it return false, show different icon and do not allow to zoom, but i can't understand how to first check the actual zoom level and start zoomButton.setEnabled(false) when max zoom is reached. 

emux

unread,
Mar 24, 2014, 12:18:13 PM3/24/14
to mapsfo...@googlegroups.com
At rescue branch you can use observer functionality.

At 0.3.X versions you can subclass MapView and override dispatchDraw like:

int oldZoomLevel = -1;

@Override
protected void dispatchDraw(Canvas canvas) {
   
super.dispatchDraw(canvas);

   
if (getMapViewPosition().getZoomLevel() != oldZoomLevel) {
       
// Update zoom controls here
        oldZoomLevel
= getMapViewPosition().getZoomLevel();
   
}
}

Daniele Germano

unread,
Mar 24, 2014, 2:06:28 PM3/24/14
to mapsfo...@googlegroups.com
I have try, but it throw a nullPointerException

03-24 18:57:33.384: E/AndroidRuntime(22148): FATAL EXCEPTION: main
03-24 18:57:33.384: E/AndroidRuntime(22148): java.lang.NullPointerException
03-24 18:57:33.384: E/AndroidRuntime(22148): at org.mapsforge.android.maps.MapView.dispatchDraw(MapView.java:610)
03-24 18:57:33.384: E/AndroidRuntime(22148): at android.view.View.draw(View.java:14544)
03-24 18:57:33.384: E/AndroidRuntime(22148): at android.view.View.getDisplayList(View.java:13476)
03-24 18:57:33.384: E/AndroidRuntime(22148): at android.view.View.getDisplayList(View.java:13520)
03-24 18:57:33.384: E/AndroidRuntime(22148): at android.view.View.draw(View.java:14254)
03-24 18:57:33.384: E/AndroidRuntime(22148): at android.view.ViewGroup.drawChild(ViewGroup.java:3155)
03-24 18:57:33.384: E/AndroidRuntime(22148): at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3024)
03-24 18:57:33.384: E/AndroidRuntime(22148): at android.view.View.getDisplayList(View.java:13474)
03-24 18:57:33.384: E/AndroidRuntime(22148): at android.view.View.getDisplayList(View.java:13520)
03-24 18:57:33.384: E/AndroidRuntime(22148): at android.view.View.draw(View.java:14254)
03-24 18:57:33.384: E/AndroidRuntime(22148): at android.view.ViewGroup.drawChild(ViewGroup.java:3155)
03-24 18:57:33.384: E/AndroidRuntime(22148): at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3024)
03-24 18:57:33.384: E/AndroidRuntime(22148): at android.view.View.getDisplayList(View.java:13474)
03-24 18:57:33.384: E/AndroidRuntime(22148): at android.view.View.getDisplayList(View.java:13520)
03-24 18:57:33.384: E/AndroidRuntime(22148): at android.view.View.draw(View.java:14254)
03-24 18:57:33.384: E/AndroidRuntime(22148): at android.view.ViewGroup.drawChild(ViewGroup.java:3155)
03-24 18:57:33.384: E/AndroidRuntime(22148): at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3024)
03-24 18:57:33.384: E/AndroidRuntime(22148): at android.view.View.getDisplayList(View.java:13474)
03-24 18:57:33.384: E/AndroidRuntime(22148): at android.view.View.getDisplayList(View.java:13520)
03-24 18:57:33.384: E/AndroidRuntime(22148): at android.view.View.draw(View.java:14254)
03-24 18:57:33.384: E/AndroidRuntime(22148): at android.view.ViewGroup.drawChild(ViewGroup.java:3155)
03-24 18:57:33.384: E/AndroidRuntime(22148): at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3024)
03-24 18:57:33.384: E/AndroidRuntime(22148): at android.view.View.draw(View.java:14544)
03-24 18:57:33.384: E/AndroidRuntime(22148): at android.widget.FrameLayout.draw(FrameLayout.java:467)
03-24 18:57:33.384: E/AndroidRuntime(22148): at com.android.internal.policy.impl.PhoneWindow$DecorView.draw(PhoneWindow.java:2584)
03-24 18:57:33.384: E/AndroidRuntime(22148): at android.view.View.getDisplayList(View.java:13476)
03-24 18:57:33.384: E/AndroidRuntime(22148): at android.view.View.getDisplayList(View.java:13520)
03-24 18:57:33.384: E/AndroidRuntime(22148): at android.view.HardwareRenderer$GlRenderer.draw(HardwareRenderer.java:1198)
03-24 18:57:33.384: E/AndroidRuntime(22148): at android.view.ViewRootImpl.draw(ViewRootImpl.java:2499)
03-24 18:57:33.384: E/AndroidRuntime(22148): at android.view.ViewRootImpl.performDraw(ViewRootImpl.java:2365)
03-24 18:57:33.384: E/AndroidRuntime(22148): at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2168)
03-24 18:57:33.384: E/AndroidRuntime(22148): at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1230)
03-24 18:57:33.384: E/AndroidRuntime(22148): at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:5089)
03-24 18:57:33.384: E/AndroidRuntime(22148): at android.view.Choreographer$CallbackRecord.run(Choreographer.java:791)
03-24 18:57:33.384: E/AndroidRuntime(22148): at android.view.Choreographer.doCallbacks(Choreographer.java:591)
03-24 18:57:33.384: E/AndroidRuntime(22148): at android.view.Choreographer.doFrame(Choreographer.java:561)
03-24 18:57:33.384: E/AndroidRuntime(22148): at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:777)
03-24 18:57:33.384: E/AndroidRuntime(22148): at android.os.Handler.handleCallback(Handler.java:725)
03-24 18:57:33.384: E/AndroidRuntime(22148): at android.os.Handler.dispatchMessage(Handler.java:92)
03-24 18:57:33.384: E/AndroidRuntime(22148): at android.os.Looper.loop(Looper.java:137)
03-24 18:57:33.384: E/AndroidRuntime(22148): at android.app.ActivityThread.main(ActivityThread.java:5283)
03-24 18:57:33.384: E/AndroidRuntime(22148): at java.lang.reflect.Method.invokeNative(Native Method)
03-24 18:57:33.384: E/AndroidRuntime(22148): at java.lang.reflect.Method.invoke(Method.java:511)
03-24 18:57:33.384: E/AndroidRuntime(22148): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1102)
03-24 18:57:33.384: E/AndroidRuntime(22148): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:869)
03-24 18:57:33.384: E/AndroidRuntime(22148): at dalvik.system.NativeStart.main(Native Method)
03-24 18:57:33.444: E/dalvikvm(22148): adjustAdaptiveCoef max=8388608, min=2097152, ut=256

emux

unread,
Mar 24, 2014, 2:14:05 PM3/24/14
to mapsfo...@googlegroups.com
Which mapsforge are you using?
Because MapView 0.3.1 does not have code at line 610.

--

Daniele Germano

unread,
Mar 25, 2014, 7:51:33 AM3/25/14
to mapsfo...@googlegroups.com
Sorry, i forgot to tell you, i use the 0.3.1 snapshot

Daniele Germano

unread,
Mar 25, 2014, 5:55:21 PM3/25/14
to mapsfo...@googlegroups.com
I finally found a solution to my problem. Instead of use the class you suggest, i study it and change my activity like this:


    zoomIn.setOnClickListener(new View.OnClickListener() {

    public void onClick(View v) {


    mapView.getMapViewPosition().zoomIn();

 

    if(mapView.getMapViewPosition().getZoomLevel() == zoomLevelMax){

   

    zoomOut.setEnabled(true);

    zoomIn.setEnabled(false);

    zoomLevelMax = mapView.getMapViewPosition().getZoomLevel();

    }

   

    else{

    zoomIn.setEnabled(true);

    zoomOut.setEnabled(true);

    }

    }

});


zoomOut.setOnClickListener(new View.OnClickListener() {

    public void onClick(View v) {

   

    mapView.getMapViewPosition().zoomOut();

   

    if(mapView.getMapViewPosition().getZoomLevel() == zoomLevelMin){

   

    zoomOut.setEnabled(false);

    zoomIn.setEnabled(true);

    zoomLevelMin = mapView.getMapViewPosition().getZoomLevel();


    }

   

    else{

   

    zoomIn.setEnabled(true);

    zoomOut.setEnabled(true);


    }

   

    }

}); 



It works perfect.


Thanks again for your time.

Alain Márquez Pérez

unread,
May 11, 2016, 4:24:11 PM5/11/16
to mapsforge-dev
hi, can u provide me some examples(a link, maybe) of xml code for rendering custom zoom buttons????

Emux

unread,
May 11, 2016, 4:28:12 PM5/11/16
to mapsfo...@googlegroups.com
Have a look in Samples app, we demonstrate how to use custom zoom buttons.

--
Emux

Alain Márquez Pérez

unread,
May 25, 2016, 9:49:14 AM5/25/16
to mapsforge-dev
sorry... the link is broken, can u show me the sample code???

Emux

unread,
May 25, 2016, 10:02:18 AM5/25/16
to mapsfo...@googlegroups.com
Reply all
Reply to author
Forward
0 new messages