-
Notifications
You must be signed in to change notification settings - Fork 75
Use View for Label
Nutiteq edited this page Jun 9, 2014
·
9 revisions
Simple map object labels (DefaultLabel class) provide limited features (labels are essentially bitmaps). You can set their text, detect click on them, but this is it. For more complex case, you can use ViewLabel class to embed any Android view into the label. Probably the most useful case would be to embed WebView into the label. There are several ways how to accomplish this.
ViewLabel takes takes any Android view (e.g. WebView) or layout (e.g. LinearLayout) as argument.
WebView webView = new WebView(this);
webView.getSettings().setJavaScriptEnabled(true);
// to force opening URLs in same view, not in Android Browser
webView.setWebViewClient(new WebViewClient() {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
return super.shouldOverrideUrlLoading(view, url);
}
});
// It is important to set size, exception will come otherwise
webView.measure(400, 400);
webView.layout(0, 0, 400, 300);
webView.loadUrl("http://www.android.com");
Label label = new ViewLabel("Android!", webView, new Handler());
You can also add new view to your screen and control the contents from MapListener events (click on vector object, or click on Label).
- Use RelativeLayout for your map view. This gives you possibility to add other views to any location on top of map. So my main.xml would be:
<?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"
android:id="@+id/mainView"
>
<com.nutiteq.MapView
android:id="@+id/mapView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>
</RelativeLayout>
- Add a view to this layout, I use here WebView which can have HTML. It is nested to another RelativeLayout, so you can position it freely on screen:
<?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"
android:id="@+id/mainView"
>
<com.nutiteq.MapView
android:id="@+id/mapView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>
<RelativeLayout
android:layout_width="320dp"
android:layout_height="300dp"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_marginLeft="15dp"
android:layout_marginTop="15dp" >
<WebView
android:id="@+id/webView1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:visibility="gone"
/>
</RelativeLayout>
</RelativeLayout>
- To have nice sample I created a Wikipedia place layer, which uses Geonames Wikipedia web service. It fetches data based on BBOX, using two classes:
- Add the layer to map, define nice markers. Remember to add also some image (I use Wikipedia logo) as wikipedia_logo.png file to res/drawable
Bitmap wikiMarker = UnscaledBitmapLoader.decodeResource(getResources(), R.drawable.wikipedia_logo);
MarkerStyle wikiStyle = MarkerStyle.builder().setBitmap(wikiMarker).setColor(Color.WHITE).setSize(0.2f).build();
StyleSet<MarkerStyle> wikiStyleSet= new StyleSet<MarkerStyle>(wikiStyle);
WikipediaLayer wikipediaLayer = new WikipediaLayer(this.proj,wikiStyleSet);
mapView.getLayers().addLayer(wikipediaLayer);
- Now create a MapListener which gets map object (Marker) and usual label presses. This listener has following functions:
- Initialize WebView for Activity. Note that this needs to be re-called for every activity creation (orientation flip), as you have new activity there.
- When user clicks a map (not an object), then popup is hidden.
- When user clicks map Marker or Label then fill WebView with HTML describing object content and make WebView visible.
Here is the code: LabelOverlayListener.java
- Add the listener to MapView:
getMapView().getOptions().setMapListener(new LabelOverlayListener(this));
- To live over context changes / Activity recreations inform the listener also about new activity. It is just one line in Activity onCreate(), here it is with context:
// device rotation state restore, saved in
// onRetainNonConfigurationInstance()
Components retainObject = (Components) getLastNonConfigurationInstance();
if (retainObject != null) {
getMapView().setComponents(retainObject);
// Following line is added to handle overlay label updates:
((LabelOverlayListener) getMapView().getOptions().getMapListener()).initWebView(this);
getMapView().startMapping();
return;
} else {
getMapView().setComponents(new Components());
}
- The result should look like following: