Improve Android Example Documentation, Animation Types (#3019)

This commit is contained in:
Bart Louwers
2024-11-14 23:46:58 +01:00
committed by GitHub
parent 38bf215e4f
commit e9afa1f461
17 changed files with 244 additions and 39 deletions

View File

@@ -23,8 +23,8 @@ jobs:
run: make mkdocs-build
- name: Deploy 🚀
uses: JamesIves/github-pages-deploy-action@v4.6.8
uses: JamesIves/github-pages-deploy-action@v4.6.9
with:
branch: gh-pages
folder: platform/android/site
target-folder: maplibre-native/android/examples/
target-folder: android/examples/

View File

@@ -5,11 +5,13 @@ on:
push:
branches:
- main
paths:
- 'docs/mdbook/**'
jobs:
build-docs:
gh-pages-mdbook-build:
name: Build
runs-on: ubuntu-22.04
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: extractions/setup-just@v2
@@ -27,10 +29,10 @@ jobs:
name: book
path: docs/mdbook/book/
deploy-docs:
needs: build-docs
gh-pages-mdbook-deploy:
needs: gh-pages-mdbook-build
name: Deploy
runs-on: ubuntu-22.04
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Download book

View File

@@ -10,11 +10,5 @@
- [Android Map Rendering Data Flow](design/android-map-rendering-data-flow.md)
- [Geometry Tile Worker](design/geometry-tile-worker.md)
- [MapLibre Native for Android](./android/README.md)
- [Quickstart](./android/getting-started-guide.md)
- [Annotation: Marker](./android/annotation-guide.md)
- [Location Component](./android/location-component-guide.md)
- [MapOptions Guide](./android/map-options-guide.md)
- [Profiling applications that use MapLibre Native](./profiling/README.md)
- [Tracy profiling](./profiling/tracy-profiling.md)

View File

@@ -24,12 +24,13 @@ import timber.log.Timber
* Shows how to use animate, ease and move camera update factory methods.
*/
class CameraAnimationTypeActivity : AppCompatActivity(), OnMapReadyCallback {
// # --8<-- [start:callback]
private val callback: CancelableCallback =
object : CancelableCallback {
override fun onCancel() {
Timber.i("Duration onCancel Callback called.")
Toast.makeText(
this@CameraAnimationTypeActivity.applicationContext,
applicationContext,
"Ease onCancel Callback called.",
Toast.LENGTH_LONG
)
@@ -39,13 +40,15 @@ class CameraAnimationTypeActivity : AppCompatActivity(), OnMapReadyCallback {
override fun onFinish() {
Timber.i("Duration onFinish Callback called.")
Toast.makeText(
this@CameraAnimationTypeActivity.applicationContext,
applicationContext,
"Ease onFinish Callback called.",
Toast.LENGTH_LONG
)
.show()
}
}
// # --8<-- [end:callback]
private lateinit var maplibreMap: MapLibreMap
private lateinit var mapView: MapView
private var cameraState = false
@@ -73,6 +76,7 @@ class CameraAnimationTypeActivity : AppCompatActivity(), OnMapReadyCallback {
// handle move button clicks
val moveButton = findViewById<View>(R.id.cameraMoveButton)
moveButton?.setOnClickListener { view: View? ->
// # --8<-- [start:moveCamera]
val cameraPosition =
CameraPosition.Builder()
.target(nextLatLng)
@@ -81,11 +85,13 @@ class CameraAnimationTypeActivity : AppCompatActivity(), OnMapReadyCallback {
.tilt(0.0)
.build()
maplibreMap.moveCamera(CameraUpdateFactory.newCameraPosition(cameraPosition))
// # --8<-- [end:moveCamera]
}
// handle ease button clicks
val easeButton = findViewById<View>(R.id.cameraEaseButton)
easeButton?.setOnClickListener { view: View? ->
// # --8<-- [start:easeCamera]
val cameraPosition =
CameraPosition.Builder()
.target(nextLatLng)
@@ -98,11 +104,13 @@ class CameraAnimationTypeActivity : AppCompatActivity(), OnMapReadyCallback {
7500,
callback
)
// # --8<-- [end:easeCamera]
}
// handle animate button clicks
val animateButton = findViewById<View>(R.id.cameraAnimateButton)
animateButton?.setOnClickListener { view: View? ->
// # --8<-- [start:animateCamera]
val cameraPosition =
CameraPosition.Builder().target(nextLatLng).bearing(270.0).tilt(20.0).build()
maplibreMap.animateCamera(
@@ -110,6 +118,7 @@ class CameraAnimationTypeActivity : AppCompatActivity(), OnMapReadyCallback {
7500,
callback
)
// # --8<-- [end:animateCamera]
}
}

View File

@@ -83,7 +83,9 @@ class CameraPositionActivity : FragmentActivity(), OnMapReadyCallback, View.OnCl
if (logCameraChanges) {
maplibreMap.addOnCameraIdleListener(idleListener)
maplibreMap.addOnCameraMoveCancelListener(moveCanceledListener)
// # --8<-- [start:addOnCameraMoveListener]
maplibreMap.addOnCameraMoveListener(moveListener)
// # --8<-- [end:addOnCameraMoveListener]
maplibreMap.addOnCameraMoveStartedListener(moveStartedListener)
} else {
maplibreMap.removeOnCameraIdleListener(idleListener)
@@ -151,12 +153,16 @@ class CameraPositionActivity : FragmentActivity(), OnMapReadyCallback, View.OnCl
ContextCompat.getColor(this@CameraPositionActivity, android.R.color.holo_green_dark)
)
}
// # --8<-- [start:moveListener]
private val moveListener = OnCameraMoveListener {
Timber.e("OnCameraMove")
fab.setColorFilter(
ContextCompat.getColor(this@CameraPositionActivity, android.R.color.holo_orange_dark)
)
}
// # --8<-- [end:moveListener]
private val moveCanceledListener = OnCameraMoveCanceledListener {
Timber.e("OnCameraMoveCanceled")
}
@@ -203,6 +209,7 @@ class CameraPositionActivity : FragmentActivity(), OnMapReadyCallback, View.OnCl
return
}
// # --8<-- [start:cameraPosition]
val cameraPosition = CameraPosition.Builder().target(LatLng(latitude, longitude)).zoom(zoom).bearing(bearing).tilt(tilt).build()
maplibreMap?.animateCamera(
@@ -218,6 +225,7 @@ class CameraPositionActivity : FragmentActivity(), OnMapReadyCallback, View.OnCl
}
}
)
// # --8<-- [end:cameraPosition]
Timber.v(cameraPosition.toString())
}
}

View File

@@ -44,22 +44,31 @@ class ManualZoomActivity : AppCompatActivity() {
override fun onOptionsItemSelected(item: MenuItem): Boolean {
return when (item.itemId) {
R.id.action_zoom_in -> {
// # --8<-- [start:zoomIn]
maplibreMap.animateCamera(CameraUpdateFactory.zoomIn())
// # --8<-- [end:zoomIn]
true
}
R.id.action_zoom_out -> {
// # --8<-- [start:zoomOut]
maplibreMap.animateCamera(CameraUpdateFactory.zoomOut())
// # --8<-- [end:zoomOut]
true
}
R.id.action_zoom_by -> {
// # --8<-- [start:zoomBy]
maplibreMap.animateCamera(CameraUpdateFactory.zoomBy(2.0))
// # --8<-- [end:zoomBy]
true
}
R.id.action_zoom_to -> {
// # --8<-- [start:zoomTo]
maplibreMap.animateCamera(CameraUpdateFactory.zoomTo(2.0))
// # --8<-- [end:zoomTo]
true
}
R.id.action_zoom_to_point -> {
// # --8<-- [start:zoomToPoint]
val view = window.decorView
maplibreMap.animateCamera(
CameraUpdateFactory.zoomBy(
@@ -67,6 +76,7 @@ class ManualZoomActivity : AppCompatActivity() {
Point(view.measuredWidth / 4, view.measuredHeight / 4)
)
)
// # --8<-- [end:zoomToPoint]
true
}
else -> super.onOptionsItemSelected(item)

View File

@@ -15,12 +15,6 @@ import timber.log.Timber
class MaxMinZoomActivity : AppCompatActivity(), OnMapReadyCallback {
private lateinit var mapView: MapView
private lateinit var maplibreMap: MapLibreMap
private val clickListener = OnMapClickListener {
if (this::maplibreMap.isInitialized) {
maplibreMap.setStyle(Style.Builder().fromUri(TestStyles.getPredefinedStyleWithFallback("Outdoor")))
}
true
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@@ -33,10 +27,20 @@ class MaxMinZoomActivity : AppCompatActivity(), OnMapReadyCallback {
override fun onMapReady(map: MapLibreMap) {
maplibreMap = map
maplibreMap.setStyle(TestStyles.getPredefinedStyleWithFallback("Streets"))
maplibreMap.setStyle(TestStyles.OPENFREEMAP_LIBERY)
// # --8<-- [start:zoomPreference]
maplibreMap.setMinZoomPreference(3.0)
maplibreMap.setMaxZoomPreference(5.0)
maplibreMap.addOnMapClickListener(clickListener)
// # --8<-- [end:zoomPreference]
// # --8<-- [start:addOnMapClickListener]
maplibreMap.addOnMapClickListener {
if (this::maplibreMap.isInitialized) {
maplibreMap.setStyle(Style.Builder().fromUri(TestStyles.AMERICANA))
}
true
}
// # --8<-- [end:addOnMapClickListener]
}
override fun onStart() {
@@ -66,9 +70,6 @@ class MaxMinZoomActivity : AppCompatActivity(), OnMapReadyCallback {
override fun onDestroy() {
super.onDestroy()
if (this::maplibreMap.isInitialized) {
maplibreMap.removeOnMapClickListener(clickListener)
}
mapView.onDestroy()
}

View File

@@ -60,10 +60,12 @@ class ScrollByActivity : AppCompatActivity(), OnMapReadyCallback {
val fab = findViewById<FloatingActionButton>(R.id.fab)
fab.setColorFilter(ContextCompat.getColor(this@ScrollByActivity, R.color.primary))
fab.setOnClickListener { _: View? ->
// # --8<-- [start:scrollBy]
maplibreMap.scrollBy(
(seekBarX.progress * MULTIPLIER_PER_PIXEL).toFloat(),
(seekBarY.progress * MULTIPLIER_PER_PIXEL).toFloat()
)
// # --8<-- [end:scrollBy]
}
}

View File

@@ -29,6 +29,7 @@
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textColor="@color/white"
android:text="@string/button_camera_move"/>
<Button
@@ -37,6 +38,7 @@
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textColor="@color/white"
android:text="@string/button_camera_ease"/>
<Button
@@ -45,6 +47,7 @@
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textColor="@color/white"
android:text="@string/button_camera_animate"/>
</LinearLayout>

View File

@@ -13,6 +13,11 @@
display: none;
}
.md-grid {
max-width: 1800px;
.md-nav--primary .md-nav__link[for=__toc] > .md-nav__icon,
.md-nav--primary .md-nav__link[for=__toc] ~ .md-nav {
display: none;
}
.md-copyright__highlight {
color: inherit;
}

View File

@@ -1,13 +1,64 @@
# Animation Types
!!! note
You can find the full source code of this example in [`CameraAnimationTypeActivity.kt`](https://github.com/maplibre/maplibre-native/blob/main/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/activity/camera/CameraAnimationTypeActivity.kt) of the MapLibreAndroidTestApp.
This example showcases the different animation types.
- **Move**: available via the `MapLibreMap.moveCamera` method.
- **Ease**: available via the `MapLibreMap.easeCamera` method.
- **Animate**: available via the `MapLibreMap.animateCamera` method.
It also shows how to pass callbacks that are called when an animation is cancelled.
### Move
```kotlin title="CameraAnimationTypeActivity.kt"
--8<-- "MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/camera/CameraAnimationTypeActivity.kt"
The `MapLibreMap.moveCamera` method jumps to the camera position provided.
```kotlin
--8<-- "MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/camera/CameraAnimationTypeActivity.kt:moveCamera"
```
<figure markdown="span">
<video controls width="250" poster="https://maplibre-native.s3.eu-central-1.amazonaws.com/android-documentation-resources/move_animation_thumbnail.jpg">
<source src="https://maplibre-native.s3.eu-central-1.amazonaws.com/android-documentation-resources/move_animation.mp4" />
</video>
</figure>
### Ease
The `MapLibreMap.moveCamera` eases to the camera position provided (with constant ground speed).
```kotlin
--8<-- "MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/camera/CameraAnimationTypeActivity.kt:easeCamera"
```
<figure markdown="span">
<video preload="none" controls width="250" poster="https://maplibre-native.s3.eu-central-1.amazonaws.com/android-documentation-resources/ease_animation_thumbnail.jpg">
<source src="https://maplibre-native.s3.eu-central-1.amazonaws.com/android-documentation-resources/ease_animation.mp4" />
</video>
</figure>
### Animate
The `MapLibreMap.animateCamera` uses a powered flight animation move to the camera position provided[^1].
[^1]: The implementation is based on Van Wijk, Jarke J.; Nuij, Wim A. A. “Smooth and efficient zooming and panning.” INFOVIS ’03. pp. 15–22. [https://www.win.tue.nl/~vanwijk/zoompan.pdf#page=5](https://www.win.tue.nl/~vanwijk/zoompan.pdf#page=5)
```kotlin
--8<-- "MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/camera/CameraAnimationTypeActivity.kt:animateCamera"
```
<figure markdown="span">
<video preload="none" controls width="250" poster="https://maplibre-native.s3.eu-central-1.amazonaws.com/android-documentation-resources/animate_animation_thumbnail.jpg">
<source src="https://maplibre-native.s3.eu-central-1.amazonaws.com/android-documentation-resources/animate_animation.mp4" />
</video>
</figure>
## Animation Callbacks
In the previous section a `CancellableCallback` was passed to the last two animation methods. This callback shows a toast message when the animation is cancelled or when it is finished.
```kotlin
--8<-- "MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/camera/CameraAnimationTypeActivity.kt:callback"
```

View File

@@ -1,7 +1,35 @@
# CameraPosition Capabilities
!!! note
You can find the full source code of this example in [`CameraPositionActivity.kt`](https://github.com/maplibre/maplibre-native/blob/main/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/camera/CameraPositionActivity.kt) of the MapLibreAndroidTestApp.
This example showcases how to listen to camera change events.
```kotlin title="CameraPositionActivity.kt"
--8<-- "MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/camera/CameraPositionActivity.kt"
```
<figure markdown="span">
<video controls width="250" poster="https://maplibre-native.s3.eu-central-1.amazonaws.com/android-documentation-resources/cameraposition_thumbnail.jpg">
<source src="https://maplibre-native.s3.eu-central-1.amazonaws.com/android-documentation-resources/cameraposition.mp4" />
</video>
</figure>
The camera animation is kicked off with this code:
```kotlin
--8<-- "MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/camera/CameraPositionActivity.kt:cameraPosition"
```
Notice how the color of the button in the bottom right changes color. Depending on the state of the camera.
We can listen for changes to the state of the camera by registering a `OnCameraMoveListener`, `OnCameraIdleListener`, `OnCameraMoveCanceledListener` or `OnCameraMoveStartedListener` with the `MapLibreMap`. For example, the `OnCameraMoveListener` is defined with:
```kotlin
--8<-- "MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/camera/CameraPositionActivity.kt:moveListener"
```
And registered with:
```kotlin
--8<-- "MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/camera/CameraPositionActivity.kt:addOnCameraMoveListener"
```
Refer to the full example to learn the methods to register the other types of camera change events.

View File

@@ -3,16 +3,17 @@
!!! note
You can find the full source code of this example in [`LatLngBoundsActivity.kt`](https://github.com/maplibre/maplibre-native/blob/main/platform/android/testapp/activity/camera/LatLngBoundsActivity.kt) of the MapLibreAndroidTestApp.
You can find the full source code of this example in [`LatLngBoundsActivity.kt`](https://github.com/maplibre/maplibre-native/blob/main/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/camera/LatLngBoundsActivity.kt) of the MapLibreAndroidTestApp.
This example demonstrates setting the camera to some bounds defined by some features. It sets these bounds when the map is initialized and when the [bottom sheet](https://m2.material.io/components/sheets-bottom) is opened or closed.
<figure markdown="span">
<video controls width="250">
<source src="https://github.com/user-attachments/assets/46a89dfb-3abc-448a-be53-8abe39b2919b" />
</video>
<video controls width="250" poster="https://maplibre-native.s3.eu-central-1.amazonaws.com/android-documentation-resources/lat_lng_bounds_thumbnail.jpg">
<source src="https://maplibre-native.s3.eu-central-1.amazonaws.com/android-documentation-resources/lat_lng_bounds.mp4" />
</video>
</figure>
Here you can see how the feature collection is loaded and how `MapLibreMap.getCameraForLatLngBounds` is used to set the bounds during map initialization:
```kotlin

View File

@@ -0,0 +1,28 @@
# Min/Max Zoom
!!! note
You can find the full source code of this example in [`MaxMinZoomActivity.kt`](https://github.com/maplibre/maplibre-native/blob/main/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/camera/MaxMinZoomActivity.kt) of the MapLibreAndroidTestApp.
This example shows how to configure a maximum and a minimum zoom level.
```kotlin
--8<-- "MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/camera/MaxMinZoomActivity.kt:zoomPreference"
```
## Bonus: Add Click Listener
As a bonus, this example also shows how you can define a click listener to the map.
```kotlin
--8<-- "MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/camera/MaxMinZoomActivity.kt:addOnMapClickListener"
```
You can remove a click listener again with `MapLibreMap.removeOnMapClickListener`. To use this API you need to assign the click listener to a variable, since you need to pass the listener to that method.
<figure markdown="span">
<video controls width="250" poster="https://maplibre-native.s3.eu-central-1.amazonaws.com/android-documentation-resources/max_min_zoom_thumbnail.jpg">
<source src="https://maplibre-native.s3.eu-central-1.amazonaws.com/android-documentation-resources/max_min_zoom.mp4" />
</video>
</figure>

View File

@@ -0,0 +1,15 @@
# Scroll by Method
!!! note
You can find the full source code of this example in [`ScrollByActivity.kt`](https://github.com/maplibre/maplibre-native/blob/main/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/camera/ScrollByActivity.kt) of the MapLibreAndroidTestApp.
This example shows how you can move the map by x/y pixels.
```kotlin
--8<-- "MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/camera/ScrollByActivity.kt:scrollBy"
```
<figure markdown="span">
![Screenshot of Example Activity to move the map by some pixels](https://github.com/user-attachments/assets/f8ae0ec7-a165-4fb3-ab9f-bfb5579c7dd8){ width="300" }
</figure>

View File

@@ -0,0 +1,46 @@
# Zoom Methods
!!! note
You can find the full source code of this example in [`ManualZoomActivity.kt`](https://github.com/maplibre/maplibre-native/blob/main/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/camera/ManualZoomActivity.kt) of the MapLibreAndroidTestApp.
This example shows different methods of zooming in.
<figure markdown="span">
<video controls width="250" poster="https://maplibre-native.s3.eu-central-1.amazonaws.com/android-documentation-resources/zoom_methods_thumbnail.jpg">
<source src="https://maplibre-native.s3.eu-central-1.amazonaws.com/android-documentation-resources/zoom_methods.mp4" />
</video>
</figure>
Each method uses `MapLibreMap.animateCamera`, but with a different `CameraUpdateFactory`.
#### Zooming In
```kotlin
--8<-- "MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/camera/ManualZoomActivity.kt:zoomIn"
```
#### Zooming Out
```kotlin
--8<-- "MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/camera/ManualZoomActivity.kt:zoomOut"
```
#### Zoom By Some Amount of Zoom Levels
```kotlin
--8<-- "MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/camera/ManualZoomActivity.kt:zoomBy"
```
#### Zoom to a Zoom Level
```kotlin
--8<-- "MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/camera/ManualZoomActivity.kt:zoomTo"
```
#### Zoom to a Point
```kotlin
--8<-- "MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/camera/ManualZoomActivity.kt:zoomToPoint"
```

View File

@@ -1,8 +1,9 @@
site_name: MapLibre Android Examples
site_url: https://www.maplibre.org/maplibre-native/android/examples
repo_url: https://github.com/louwers/maplibre-native
repo_url: https://github.com/maplibre/maplibre-native
site_description: MapLibre Android Examples
edit_uri: edit/main/platform/android/docs
copyright: Map data from <a href="https://openstreetmap.org/copyright">OpenStreetMap</a>
extra_css:
- assets/extra.css
theme:
@@ -15,6 +16,7 @@ theme:
- navigation.instant
- navigation.sections
- content.action.edit
- toc.integrate
palette:
- media: "(prefers-color-scheme)"
toggle: