diff options
author | Tobrun <tobrun.van.nuland@gmail.com> | 2019-06-24 09:08:26 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-06-24 09:08:26 +0200 |
commit | e60b48eca9e752a09e54d4b1277ac1ab6aec5629 (patch) | |
tree | 6b452cd90e2257eaeca97ea1f6140b3784a669cb | |
parent | f7f74a6deb57ad4ac22a30604a0dce39024feca2 (diff) | |
download | qtlocation-mapboxgl-e60b48eca9e752a09e54d4b1277ac1ab6aec5629.tar.gz |
[android] - update LatLngBounds example with animating bottomsheet scroll behavior (#14924)
5 files changed, 328 insertions, 198 deletions
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/assets/points-sf.geojson b/platform/android/MapboxGLAndroidSDKTestApp/src/main/assets/points-sf.geojson new file mode 100644 index 0000000000..9c96c4ef9f --- /dev/null +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/assets/points-sf.geojson @@ -0,0 +1,115 @@ +{ + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Point", + "coordinates": [ + 237.5580596923828, + 37.78563944612241 + ] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Point", + "coordinates": [ + 237.58346557617185, + 37.743571187449064 + ] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Point", + "coordinates": [ + 237.51068115234375, + 37.72347854862523 + ] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Point", + "coordinates": [ + 237.51583099365234, + 37.77125750792944 + ] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Point", + "coordinates": [ + 237.5913619995117, + 37.795406713958236 + ] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Point", + "coordinates": [ + 237.56080627441403, + 37.69441603823106 + ] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Point", + "coordinates": [ + 237.62981414794922, + 37.722392304715825 + ] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Point", + "coordinates": [ + 237.52235412597656, + 37.807071480609274 + ] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Point", + "coordinates": [ + 237.53608703613278, + 37.75334401310656 + ] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Point", + "coordinates": [ + 237.57591247558594, + 37.77071473849609 + ] + } + } + ] +}
\ No newline at end of file diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/LatLngBoundsActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/LatLngBoundsActivity.java deleted file mode 100644 index 6d73ee776e..0000000000 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/LatLngBoundsActivity.java +++ /dev/null @@ -1,172 +0,0 @@ -package com.mapbox.mapboxsdk.testapp.activity.camera; - -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.design.widget.BottomSheetBehavior; -import android.support.v7.app.AppCompatActivity; -import android.view.View; - -import com.mapbox.mapboxsdk.annotations.MarkerOptions; -import com.mapbox.mapboxsdk.camera.CameraUpdateFactory; -import com.mapbox.mapboxsdk.geometry.LatLng; -import com.mapbox.mapboxsdk.geometry.LatLngBounds; -import com.mapbox.mapboxsdk.maps.MapView; -import com.mapbox.mapboxsdk.maps.MapboxMap; -import com.mapbox.mapboxsdk.maps.Style; -import com.mapbox.mapboxsdk.testapp.R; -import com.mapbox.mapboxsdk.testapp.view.LockableBottomSheetBehavior; - -import java.util.ArrayList; -import java.util.List; - -/** - * Test activity showcasing using the LatLngBounds camera API. - */ -public class LatLngBoundsActivity extends AppCompatActivity implements View.OnClickListener { - - private static final List<LatLng> LOCATIONS = new ArrayList<LatLng>() { - { - add(new LatLng(37.806866, -122.422502)); - add(new LatLng(37.812905, -122.477605)); - add(new LatLng(37.826944, -122.423188)); - add(new LatLng(37.752676, -122.447736)); - add(new LatLng(37.769305, -122.479322)); - add(new LatLng(37.749834, -122.417867)); - add(new LatLng(37.756149, -122.405679)); - add(new LatLng(37.751403, -122.387397)); - add(new LatLng(37.793064, -122.391517)); - add(new LatLng(37.769122, -122.427394)); - } - }; - private static final LatLngBounds BOUNDS = new LatLngBounds.Builder().includes(LOCATIONS).build(); - private static final int ANIMATION_DURATION_LONG = 450; - private static final int ANIMATION_DURATION_SHORT = 250; - private static final int BOUNDS_PADDING_DIVIDER_SMALL = 3; - private static final int BOUNDS_PADDING_DIVIDER_LARGE = 9; - - private MapView mapView; - private MapboxMap mapboxMap; - private View bottomSheet; - private LockableBottomSheetBehavior bottomSheetBehavior; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_latlngbounds); - initBottomSheet(); - initMapView(savedInstanceState); - } - - private void initMapView(Bundle savedInstanceState) { - mapView = findViewById(R.id.mapView); - mapView.onCreate(savedInstanceState); - mapView.getMapAsync(map -> { - mapboxMap = map; - disableGestures(); - moveToBounds(bottomSheet.getMeasuredHeight(), BOUNDS_PADDING_DIVIDER_SMALL, ANIMATION_DURATION_SHORT); - loadStyle(); - }); - } - - private void loadStyle() { - mapboxMap.setStyle(new Style.Builder().fromUri(Style.MAPBOX_STREETS), style -> { - addMarkers(); - initFab(); - }); - } - - private void disableGestures() { - mapboxMap.getUiSettings().setTiltGesturesEnabled(false); - mapboxMap.getUiSettings().setRotateGesturesEnabled(false); - } - - private void addMarkers() { - for (LatLng location : LOCATIONS) { - mapboxMap.addMarker(new MarkerOptions().position(location)); - } - } - - private void initFab() { - findViewById(R.id.fab).setOnClickListener(this); - } - - @Override - public void onClick(View v) { - bottomSheetBehavior.setState(BottomSheetBehavior.STATE_HIDDEN); - v.animate().alpha(0.0f).setDuration(ANIMATION_DURATION_SHORT); - } - - private void initBottomSheet() { - bottomSheet = findViewById(R.id.bottom_sheet); - bottomSheetBehavior = (LockableBottomSheetBehavior) BottomSheetBehavior.from(bottomSheet); - bottomSheetBehavior.setLocked(true); - bottomSheetBehavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() { - @Override - public void onStateChanged(@NonNull View bottomSheet, int newState) { - if (newState == BottomSheetBehavior.STATE_SETTLING && mapboxMap != null) { - moveToBounds(0, BOUNDS_PADDING_DIVIDER_LARGE, ANIMATION_DURATION_LONG); - } - } - - @Override - public void onSlide(@NonNull View bottomSheet, float slideOffset) { - - } - }); - } - - private void moveToBounds(int verticalOffset, int boundsPaddingDivider, int duration) { - int paddingHorizontal = mapView.getMeasuredWidth() / boundsPaddingDivider; - int paddingVertical = (mapView.getMeasuredHeight() - verticalOffset) / boundsPaddingDivider; - mapboxMap.animateCamera(CameraUpdateFactory.newLatLngBounds( - BOUNDS, - paddingHorizontal, - paddingVertical, - paddingHorizontal, - paddingVertical + verticalOffset), - duration - ); - } - - @Override - protected void onStart() { - super.onStart(); - mapView.onStart(); - } - - @Override - protected void onResume() { - super.onResume(); - mapView.onResume(); - } - - @Override - protected void onPause() { - super.onPause(); - mapView.onPause(); - } - - @Override - protected void onStop() { - super.onStop(); - mapView.onStop(); - } - - @Override - public void onLowMemory() { - super.onLowMemory(); - mapView.onLowMemory(); - } - - @Override - protected void onDestroy() { - super.onDestroy(); - mapView.onDestroy(); - } - - @Override - protected void onSaveInstanceState(Bundle outState) { - super.onSaveInstanceState(outState); - mapView.onSaveInstanceState(outState); - } -} diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/LatLngBoundsActivity.kt b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/LatLngBoundsActivity.kt new file mode 100644 index 0000000000..6f318f77eb --- /dev/null +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/LatLngBoundsActivity.kt @@ -0,0 +1,167 @@ +package com.mapbox.mapboxsdk.testapp.activity.camera + +import android.content.Context +import android.os.Bundle +import android.support.design.widget.BottomSheetBehavior +import android.support.v7.app.AppCompatActivity +import android.view.View +import com.mapbox.geojson.FeatureCollection +import com.mapbox.geojson.FeatureCollection.fromJson +import com.mapbox.geojson.Point +import com.mapbox.mapboxsdk.geometry.LatLng +import com.mapbox.mapboxsdk.geometry.LatLngBounds +import com.mapbox.mapboxsdk.maps.MapboxMap +import com.mapbox.mapboxsdk.maps.Style +import com.mapbox.mapboxsdk.style.layers.Property.ICON_ANCHOR_CENTER +import com.mapbox.mapboxsdk.style.layers.PropertyFactory.* +import com.mapbox.mapboxsdk.style.layers.SymbolLayer +import com.mapbox.mapboxsdk.style.sources.GeoJsonSource +import com.mapbox.mapboxsdk.testapp.R +import com.mapbox.mapboxsdk.testapp.utils.GeoParseUtil.loadStringFromAssets +import com.mapbox.mapboxsdk.utils.BitmapUtils +import kotlinx.android.synthetic.main.activity_latlngbounds.* +import java.net.URISyntaxException + +/** + * Test activity showcasing using the LatLngBounds camera API. + */ +class LatLngBoundsActivity : AppCompatActivity() { + + private lateinit var mapboxMap: MapboxMap + private lateinit var bottomSheetBehavior: BottomSheetBehavior<*> + private lateinit var bounds: LatLngBounds + + private val peekHeight by lazy { + 375.toPx(this) //375dp + } + + private val additionalPadding by lazy { + 32.toPx(this) //32dp + } + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_latlngbounds) + initMapView(savedInstanceState) + } + + private fun initMapView(savedInstanceState: Bundle?) { + mapView.onCreate(savedInstanceState) + mapView.getMapAsync { map -> + mapboxMap = map + + val featureCollection: FeatureCollection = fromJson(loadStringFromAssets(this, "points-sf.geojson")) + bounds = createBounds(featureCollection) + + map.getCameraForLatLngBounds(bounds, createPadding(peekHeight))?.let { + map.cameraPosition = it + } + + try { + loadStyle(featureCollection) + } catch (e: URISyntaxException) { + e.printStackTrace() + } + } + } + + private fun loadStyle(featureCollection: FeatureCollection) { + mapboxMap.setStyle(Style.Builder() + .fromUri(Style.MAPBOX_STREETS) + .withLayer(SymbolLayer("symbol", "symbol") + .withProperties( + iconAllowOverlap(true), + iconIgnorePlacement(true), + iconImage("icon"), + iconAnchor(ICON_ANCHOR_CENTER) + ) + ) + .withSource(GeoJsonSource("symbol", featureCollection)) + .withImage("icon", BitmapUtils.getDrawableFromRes(this@LatLngBoundsActivity, R.drawable.ic_android)!!) + ) { + initBottomSheet() + fab.setOnClickListener { bottomSheetBehavior.state = BottomSheetBehavior.STATE_EXPANDED } + } + } + + private fun initBottomSheet() { + bottomSheetBehavior = BottomSheetBehavior.from(bottomSheet) + bottomSheetBehavior.setBottomSheetCallback(object : BottomSheetBehavior.BottomSheetCallback() { + override fun onSlide(bottomSheet: View, slideOffset: Float) { + val offset = convertSlideOffset(slideOffset) + val bottomPadding = (peekHeight * offset).toInt() + + mapboxMap.getCameraForLatLngBounds(bounds, createPadding(bottomPadding))?.let { + mapboxMap.cameraPosition = it + } + } + + override fun onStateChanged(bottomSheet: View, newState: Int) { + // no-op + } + }) + } + + // slideOffset ranges from NaN to -1.0, range from 1.0 to 0 instead + fun convertSlideOffset(slideOffset: Float): Float { + return if (slideOffset.equals(Float.NaN)) { + 1.0f + } else { + 1 + slideOffset + } + } + + fun createPadding(bottomPadding: Int): IntArray { + return intArrayOf(additionalPadding, additionalPadding, additionalPadding, bottomPadding) + } + + private fun createBounds(featureCollection: FeatureCollection): LatLngBounds { + val boundsBuilder = LatLngBounds.Builder() + featureCollection.features()?.let { + for (feature in it) { + val point = feature.geometry() as Point + boundsBuilder.include(LatLng(point.latitude(), point.longitude())) + } + } + return boundsBuilder.build() + } + + override fun onStart() { + super.onStart() + mapView.onStart() + } + + override fun onResume() { + super.onResume() + mapView.onResume() + } + + override fun onPause() { + super.onPause() + mapView.onPause() + } + + override fun onStop() { + super.onStop() + mapView.onStop() + } + + override fun onLowMemory() { + super.onLowMemory() + mapView.onLowMemory() + } + + override fun onDestroy() { + super.onDestroy() + mapView.onDestroy() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + mapView.onSaveInstanceState(outState) + } + +} + +fun Int.toPx(context: Context): Int = (this * context.resources.displayMetrics.density).toInt() + diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_arrow_upward.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_arrow_upward.xml new file mode 100644 index 0000000000..c64ae35166 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_arrow_upward.xml @@ -0,0 +1,9 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0"> + <path + android:fillColor="#FF000000" + android:pathData="M4,12l1.41,1.41L11,7.83V20h2V7.83l5.58,5.59L20,12l-8,-8 -8,8z"/> +</vector> diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_latlngbounds.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_latlngbounds.xml index e565c3c9d1..e25fd1882c 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_latlngbounds.xml +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_latlngbounds.xml @@ -1,36 +1,47 @@ <?xml version="1.0" encoding="utf-8"?> <android.support.design.widget.CoordinatorLayout - xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:app="http://schemas.android.com/apk/res-auto" - android:id="@+id/coordinator_layout" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:fitsSystemWindows="true" - android:orientation="vertical"> - - <com.mapbox.mapboxsdk.maps.MapView - android:id="@id/mapView" + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" + android:id="@+id/coordinator_layout" android:layout_width="match_parent" android:layout_height="match_parent" - app:layout_behavior="@string/appbar_scrolling_view_behavior"/> + android:fitsSystemWindows="true" + android:orientation="vertical"> + + <com.mapbox.mapboxsdk.maps.MapView + android:id="@id/mapView" + android:layout_width="match_parent" + android:layout_height="match_parent" + app:layout_behavior="@string/appbar_scrolling_view_behavior"/> <android.support.v4.widget.NestedScrollView - android:id="@+id/bottom_sheet" - android:layout_width="match_parent" - android:layout_height="375dp" - android:background="@color/primaryDark" - app:behavior_hideable="true" - app:behavior_skipCollapsed="false" - app:layout_behavior="com.mapbox.mapboxsdk.testapp.view.LockableBottomSheetBehavior"/> + android:id="@+id/bottomSheet" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:background="@color/primaryDark" + app:behavior_hideable="true" + app:behavior_peekHeight="375dp" + app:layout_behavior="android.support.design.widget.BottomSheetBehavior"> + + <TextView + android:text="Hello World" + android:gravity="center" + android:textSize="120sp" + android:textColor="@android:color/white" + android:background="@color/primary" + android:layout_width="match_parent" + android:layout_height="375dp"/> + + </android.support.v4.widget.NestedScrollView> <android.support.design.widget.FloatingActionButton - android:id="@+id/fab" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_margin="@dimen/fab_margin" - android:src="@drawable/ic_arrow_downward" - app:backgroundTint="@color/primary" - app:layout_anchor="@id/bottom_sheet" - app:layout_anchorGravity="top|end"/> + android:id="@+id/fab" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_margin="@dimen/fab_margin" + android:src="@drawable/ic_arrow_upward" + app:backgroundTint="@color/primary" + app:layout_anchor="@id/bottomSheet" + app:layout_anchorGravity="top|end"/> </android.support.design.widget.CoordinatorLayout>
\ No newline at end of file |