Skip to content
This repository has been archived by the owner on Oct 7, 2024. It is now read-only.

Commit

Permalink
Adds two map mini-window interaction example (#481)
Browse files Browse the repository at this point in the history
* initial commit of example setup

* tweaks

* more additions

* additions

* additions

* interface setup

* more experimentation

* changes

* added listeners in right place

* changes

* mini window communication works

* improvements

* tweaks

* refactor

* disabled map fragment ui

* removed onAttachFragment override

* string changes

* name refactoring

* changed map style

* name refactor

* javadoc

* removed unneeded class

* cleanup

* string tweak

* checkstyle
  • Loading branch information
Langston Smith authored Oct 19, 2017
1 parent 93f8c37 commit ea954fb
Show file tree
Hide file tree
Showing 7 changed files with 356 additions and 2 deletions.
7 changes: 7 additions & 0 deletions MapboxAndroidDemo/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,13 @@
android:name="android.support.PARENT_ACTIVITY"
android:value="com.mapbox.mapboxandroiddemo.MainActivity"/>
</activity>
<activity
android:name=".labs.InsetMapActivity"
android:label="@string/activity_labs_inset_map_title">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="com.mapbox.mapboxandroiddemo.MainActivity"/>
</activity>
<activity
android:name=".examples.dds.StyleCirclesCategoricallyActivity"
android:label="@string/activity_dds_style_circle_categorically_title">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@
import com.mapbox.mapboxandroiddemo.labs.LosAngelesTourismActivity;
import com.mapbox.mapboxandroiddemo.labs.MapillaryActivity;
import com.mapbox.mapboxandroiddemo.labs.MarkerFollowingRouteActivity;
import com.mapbox.mapboxandroiddemo.labs.InsetMapActivity;
import com.mapbox.mapboxandroiddemo.labs.PictureInPictureActivity;
import com.mapbox.mapboxandroiddemo.labs.RecyclerViewOnMapActivity;
import com.mapbox.mapboxandroiddemo.labs.RecyclerViewSymbolLayerActivity;
Expand Down Expand Up @@ -597,7 +598,7 @@ private void listItems(int id) {
R.string.activity_lab_picture_in_picture_title,
R.string.activity_lab_picture_in_picture_description,
new Intent(MainActivity.this, PictureInPictureActivity.class),
R.string.activity_lab_picture_in_picture_url, true
R.string.activity_lab_picture_in_picture_url, false
));
}
exampleItemModel.add(new ExampleItemModel(
Expand All @@ -606,11 +607,16 @@ private void listItems(int id) {
new Intent(MainActivity.this, RecyclerViewOnMapActivity.class),
R.string.activity_lab_rv_on_map_url, false
));
exampleItemModel.add(new ExampleItemModel(
R.string.activity_labs_inset_map_title,
R.string.activity_labs_inset_map_description,
new Intent(MainActivity.this, InsetMapActivity.class),
R.string.activity_labs_inset_map_url, true));
exampleItemModel.add(new ExampleItemModel(
R.string.activity_lab_rv_symbol_layer_on_map_title,
R.string.activity_lab_rv_symbol_layer_on_map_description,
new Intent(MainActivity.this, RecyclerViewSymbolLayerActivity.class),
R.string.activity_lab_rv_symbol_layer_on_map_url, false
R.string.activity_lab_rv_symbol_layer_on_map_url, true
));
currentCategory = R.id.nav_lab;
break;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,299 @@
package com.mapbox.mapboxandroiddemo.labs;

import android.content.Context;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AppCompatActivity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import com.mapbox.mapboxandroiddemo.R;
import com.mapbox.mapboxsdk.Mapbox;
import com.mapbox.mapboxsdk.camera.CameraPosition;
import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.maps.MapboxMapOptions;
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
import com.mapbox.mapboxsdk.utils.MapFragmentUtils;

public class InsetMapActivity extends AppCompatActivity {

private MapView mainMapMapView;
private MapboxMap mainLargeMapboxMap;
private OnMapMovedFragmentInterface onMapMovedFragmentInterfaceListener;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

// Mapbox access token is configured here. This needs to be called either in your application
// object or in the same activity which contains the mapview.
Mapbox.getInstance(this, getString(R.string.access_token));

// This contains the MapView in XML and needs to be called after the access token is configured.
setContentView(R.layout.activity_inset_map);

mainMapMapView = (MapView) findViewById(R.id.main_mapView);
mainMapMapView.onCreate(savedInstanceState);
mainMapMapView.getMapAsync(new OnMapReadyCallback() {
@Override
public void onMapReady(MapboxMap mapboxMap) {
InsetMapActivity.this.mainLargeMapboxMap = mapboxMap;
mainLargeMapboxMap.setOnCameraMoveListener(new MapboxMap.OnCameraMoveListener() {
@Override
public void onCameraMove() {
onMapMovedFragmentInterfaceListener.onMapMoved(mainLargeMapboxMap.getCameraPosition());
}
});
}
});

/* Custom version of the regular Mapbox SupportMapFragment class. A custom one is being built here
so that the interface call backs can be used in the appropriate places so that the example eventually
works*/
CustomSupportMapFragment customSupportMapFragment;
if (savedInstanceState == null) {

// Create fragment
final FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();

// Build map fragment options
MapboxMapOptions options = new MapboxMapOptions();
options.styleUrl("mapbox://styles/mapbox/cj5l80zrp29942rmtg0zctjto");
options.attributionEnabled(false);
options.logoEnabled(false);
options.compassEnabled(false);
options.scrollGesturesEnabled(false);
options.tiltGesturesEnabled(false);
options.rotateGesturesEnabled(false);
options.camera(new CameraPosition.Builder()
.target(new LatLng(11.302318, 106.025839))
.zoom(2)
.build());

// Create map fragment and pass through map options
customSupportMapFragment = CustomSupportMapFragment.newInstance(options);

// Add fragmentMap fragment to parent container
transaction.add(R.id.mini_map_fragment_container, customSupportMapFragment, "com.mapbox.fragmentMap");
transaction.commit();

} else {
customSupportMapFragment = (CustomSupportMapFragment)
getSupportFragmentManager().findFragmentByTag("com.mapbox.fragmentMap");
}
}

private void setOnDataListener(OnMapMovedFragmentInterface onMapMovedFragmentInterface) {
onMapMovedFragmentInterfaceListener = onMapMovedFragmentInterface;
}

public interface OnMapMovedFragmentInterface {
void onMapMoved(CameraPosition mainMapCameraPosition);
}

// Add the mainMapMapView lifecycle to the activity's lifecycle methods
@Override
public void onResume() {
super.onResume();
mainMapMapView.onResume();
}

@Override
protected void onStart() {
super.onStart();
mainMapMapView.onStart();
}

@Override
protected void onStop() {
super.onStop();
mainMapMapView.onStop();
}

@Override
public void onPause() {
super.onPause();
mainMapMapView.onPause();
}

@Override
public void onLowMemory() {
super.onLowMemory();
mainMapMapView.onLowMemory();
}

@Override
protected void onDestroy() {
super.onDestroy();
mainMapMapView.onDestroy();
}

@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
mainMapMapView.onSaveInstanceState(outState);
}

/**
* Custom version of the regular Mapbox SupportMapFragment class. A custom one is being built here
* so that the interface call backs can be used in the appropriate places so that the example eventually
* works
*
* @see #getMapAsync(OnMapReadyCallback)
*/
public static class CustomSupportMapFragment extends Fragment implements
InsetMapActivity.OnMapMovedFragmentInterface {

private MapView fragmentMap;
private OnMapReadyCallback onMapReadyCallback;
private CameraPosition cameraPositionForFragmentMap;
private static final int ZOOM_DISTANCE_BETWEEN_MAIN_AND_FRAGMENT_MAPS = 3;

/**
* Creates a CustomSupportMapFragment instance
*
* @param mapboxMapOptions The configuration options to be used.
* @return CustomSupportMapFragment created.
*/
public static CustomSupportMapFragment newInstance(@Nullable MapboxMapOptions mapboxMapOptions) {
CustomSupportMapFragment mapFragment = new CustomSupportMapFragment();
mapFragment.setArguments(MapFragmentUtils.createFragmentArgs(mapboxMapOptions));
return mapFragment;
}

// Override method for OnMapMovedFragmentInterface
@Override
public void onMapMoved(final CameraPosition mainMapCameraPosition) {

cameraPositionForFragmentMap = new CameraPosition.Builder()
.target(mainMapCameraPosition.target)
.zoom(mainMapCameraPosition.zoom - ZOOM_DISTANCE_BETWEEN_MAIN_AND_FRAGMENT_MAPS)
.bearing(mainMapCameraPosition.bearing)
.tilt(mainMapCameraPosition.tilt)
.build();

fragmentMap.getMapAsync(new OnMapReadyCallback() {
@Override
public void onMapReady(final MapboxMap mapInFragment) {
mapInFragment.moveCamera(CameraUpdateFactory.newCameraPosition(cameraPositionForFragmentMap));
}
});
}

@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
((InsetMapActivity) getActivity()).setOnDataListener(this);
}

/**
* Creates the fragment view hierarchy.
*
* @param inflater Inflater used to inflate content.
* @param container The parent layout for the fragmentMap fragment.
* @param savedInstanceState The saved instance state for the fragmentMap fragment.
* @return The view created
*/
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
Context context = inflater.getContext();
return fragmentMap = new MapView(context, MapFragmentUtils.resolveArgs(context, getArguments()));
}

/**
* Called when the fragment view hierarchy is created.
*
* @param view The content view of the fragment
* @param savedInstanceState THe saved instance state of the framgnt
*/
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
fragmentMap.onCreate(savedInstanceState);
}

/**
* Called when the fragment is visible for the users.
*/
@Override
public void onStart() {
super.onStart();
fragmentMap.onStart();
fragmentMap.getMapAsync(onMapReadyCallback);
}

/**
* Called when the fragment is ready to be interacted with.
*/
@Override
public void onResume() {
super.onResume();
fragmentMap.onResume();
}

/**
* Called when the fragment is pausing.
*/
@Override
public void onPause() {
super.onPause();
fragmentMap.onPause();
}

/**
* Called when the fragment state needs to be saved.
*
* @param outState The saved state
*/
@Override
public void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState);
fragmentMap.onSaveInstanceState(outState);
}

/**
* Called when the fragment is no longer visible for the user.
*/
@Override
public void onStop() {
super.onStop();
fragmentMap.onStop();
}

/**
* Called when the fragment receives onLowMemory call from the hosting Activity.
*/
@Override
public void onLowMemory() {
super.onLowMemory();
fragmentMap.onLowMemory();
}

/**
* Called when the fragment is view hiearchy is being destroyed.
*/
@Override
public void onDestroyView() {
super.onDestroyView();
fragmentMap.onDestroy();
}

/**
* Sets a callback object which will be triggered when the MapboxMap instance is ready to be used.
*
* @param onMapReadyCallback The callback to be invoked.
*/
public void getMapAsync(@NonNull final OnMapReadyCallback onMapReadyCallback) {
this.onMapReadyCallback = onMapReadyCallback;
}
}
}

39 changes: 39 additions & 0 deletions MapboxAndroidDemo/src/main/res/layout/activity_inset_map.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:mapbox="http://schemas.android.com/apk/res-auto"
xmlns:maps="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">

<android.support.v7.widget.CardView
android:id="@+id/cardview"
android:layout_width="150dp"
android:layout_height="150dp"
android:layout_gravity="bottom|end"
android:layout_marginBottom="16dp"
android:layout_marginEnd="16dp"
android:layout_marginRight="16dp"
app:cardCornerRadius="2dp"
app:cardElevation="@dimen/cardview_default_elevation">

<FrameLayout
android:id="@+id/mini_map_fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent"/>

</android.support.v7.widget.CardView>

<com.mapbox.mapboxsdk.maps.MapView
android:id="@+id/main_mapView"
android:layout_width="match_parent"
android:layout_height="match_parent"
mapbox:mapbox_cameraTargetLat="11.302318"
mapbox:mapbox_cameraTargetLng="106.025839"
mapbox:mapbox_cameraZoom="5.11"
mapbox:mapbox_cameraZoomMin="3"
mapbox:mapbox_styleUrl="mapbox://styles/mapbox/cj5l80zrp29942rmtg0zctjto"
maps:mapbox_enableZMediaOverlay="true"/>

</FrameLayout>
Original file line number Diff line number Diff line change
Expand Up @@ -73,5 +73,6 @@
<string name="activity_lab_rv_on_map_description">Manipulate the map based on recyclerview interactions.</string>
<string name="activity_lab_rv_symbol_layer_on_map_description">Add markers via SymbolLayer and manipulate the map based on recyclerview interactions.</string>
<string name="activity_lab_mapillary_description">Add Mapillary vector tiles to a map</string>
<string name="activity_labs_inset_map_description">Show a smaller inset map fragment and link it to a larger map for two map interaction. Great for gaming!</string>

</resources>
Loading

0 comments on commit ea954fb

Please sign in to comment.