Skip to content

Commit 7c1e6bc

Browse files
committed
Add new moveToMarker api using a destination scale, and improve animation
1 parent 09578b1 commit 7c1e6bc

File tree

6 files changed

+67
-53
lines changed

6 files changed

+67
-53
lines changed

Readme.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
[ ![Download](https://api.bintray.com/packages/peterlaurence/maven/mapview/images/download.svg?version=2.0.8) ](https://bintray.com/peterlaurence/maven/mapview/2.0.8/link)
1+
[ ![Download](https://api.bintray.com/packages/peterlaurence/maven/mapview/images/download.svg?version=2.0.9) ](https://bintray.com/peterlaurence/maven/mapview/2.0.9/link)
22

33
# MapView
44

@@ -60,7 +60,7 @@ There are some breaking changes, although most of them are just package refactor
6060

6161
Add this to your module's build.gradle
6262
```groovy
63-
implementation 'com.peterlaurence:mapview:2.0.8'
63+
implementation 'com.peterlaurence:mapview:2.0.9'
6464
```
6565

6666
## Origin and motivation

mapview/build.gradle

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ apply plugin: 'kotlin-android'
55
apply plugin: 'kotlin-android-extensions'
66
apply plugin: 'kotlinx-serialization'
77

8-
def versionTag = "2.0.8"
8+
def versionTag = "2.0.9"
99

1010
androidExtensions {
1111
experimental = true
@@ -23,7 +23,6 @@ buildscript {
2323
android {
2424
compileSdkVersion 29
2525

26-
2726
defaultConfig {
2827
minSdkVersion 24
2928
targetSdkVersion 29

mapview/src/main/java/com/peterlaurence/mapview/api/MarkerApi.kt

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import com.peterlaurence.mapview.markers.MarkerTapListener
99
* Add a marker to the the MapView. The marker can be any View.
1010
* No LayoutParams are required; the View will be laid out using WRAP_CONTENT for both width and height, and positioned based on the parameters.
1111
*
12-
* @param view View instance to be added to the TileView.
12+
* @param view View instance to be added to the MapView.
1313
* @param x Relative x position the View instance should be positioned at.
1414
* @param y Relative y position the View instance should be positioned at.
1515
* @param relativeAnchorLeft The x-axis position of a marker will be offset by a number equal to the width of the marker multiplied by this value.
@@ -66,39 +66,58 @@ fun MapView.getMarkerFromPosition(x: Double, y: Double): View? {
6666
}
6767

6868
/**
69-
* Scroll the TileView so that the View passed is centered in the viewport.
69+
* Scrolls the MapView so that the View passed is centered in the viewport.
70+
* The scale remains constant.
7071
*
71-
* @param view The View marker that the TileView should center on.
72-
* @param shouldAnimate True if the movement should use a transition effect.
72+
* The scroll position is animated if [shouldAnimate] is set to `true`.
73+
*
74+
* @param view The marker that the MapView should center on.
75+
* @param shouldAnimate `true` if the movement should use a transition effect.
7376
*/
7477
@Suppress("unused")
7578
fun MapView.moveToMarker(view: View, shouldAnimate: Boolean) {
79+
moveToMarker(view, scale, shouldAnimate)
80+
}
81+
82+
/**
83+
* Scrolls the MapView so that the marker passed is centered in the viewport.
84+
* Takes an additional [destinationScale] parameter.
85+
*
86+
* The scroll position and scale are animated if [shouldAnimate] is set to `true`.
87+
*
88+
* @param view The marker that the MapView should center on.
89+
* @param destinationScale The scale of the MapView when centered on the marker
90+
* @param shouldAnimate True if the movement should use a transition effect.
91+
*/
92+
@Suppress("unused")
93+
fun MapView.moveToMarker(view: View, destinationScale: Float, shouldAnimate: Boolean) {
7694
if (markerLayout?.indexOfChild(view) == -1) {
7795
throw IllegalStateException("The view passed is not an existing marker")
7896
}
7997
val params = view.layoutParams
8098
if (params is MarkerLayoutParams) {
81-
val scaledX = (params.x * scale).toInt()
82-
val scaledY = (params.y * scale).toInt()
99+
val scaledX = (params.x * destinationScale).toInt()
100+
val scaledY = (params.y * destinationScale).toInt()
83101
if (shouldAnimate) {
84-
slideToAndCenter(scaledX, scaledY)
102+
slideToAndCenterWithScale(scaledX, scaledY, destinationScale)
85103
} else {
104+
scale = destinationScale
86105
scrollToAndCenter(scaledX, scaledY)
87106
}
88107
}
89108
}
90109

91110
/**
92-
* Removes a marker View from the TileView's view tree.
111+
* Removes a marker from the MapView's view tree.
93112
*
94-
* @param view The marker View to be removed.
113+
* @param view The marker to be removed.
95114
*/
96115
fun MapView.removeMarker(view: View) {
97116
markerLayout?.removeMarker(view)
98117
}
99118

100119
/**
101-
* Add a callout to the the MapView. The callout can be any View.
120+
* Add a callout to the the MapView. The callout can be any View.
102121
* No LayoutParams are required; the View will be laid out using WRAP_CONTENT for both width and height, and positioned based on the parameters.
103122
*
104123
* @param view View instance to be added to the MapView.

mapview/src/main/java/com/peterlaurence/mapview/core/CoordinateTranslater.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ class CoordinateTranslater(val baseWidth: Int, val baseHeight: Int, val left: Do
5151
* and an angle alpha. This return the X coordinate by applying a rotation of -alpha around the
5252
* center.
5353
*/
54+
@Suppress("unused")
5455
fun reverseRotationX(rd: ReferentialData, x: Float, y: Float): Double {
5556
val centerX = rd.centerX * baseWidth * rd.scale
5657
val centerY = rd.centerY * baseHeight * rd.scale
@@ -62,6 +63,7 @@ class CoordinateTranslater(val baseWidth: Int, val baseHeight: Int, val left: Do
6263
* and an angle alpha. This return the Y coordinate by applying a rotation of -alpha around the
6364
* center.
6465
*/
66+
@Suppress("unused")
6567
fun reverseRotationY(rd: ReferentialData, x: Float, y: Float): Double {
6668
val centerX = rd.centerX * baseWidth * rd.scale
6769
val centerY = rd.centerY * baseHeight * rd.scale

mapview/src/main/java/com/peterlaurence/mapview/layout/GestureLayout.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,7 @@ abstract class GestureLayout @JvmOverloads constructor(context: Context, attrs:
231231
* @param x Horizontal destination point.
232232
* @param y Vertical destination point.
233233
*/
234+
@Suppress("unused")
234235
fun slideToAndCenter(x: Int, y: Int) {
235236
slideTo(x - halfWidth, y - halfHeight)
236237
}

mapview/src/main/java/com/peterlaurence/mapview/layout/animators/ZoomPanAnimator.kt

Lines changed: 32 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -2,89 +2,88 @@ package com.peterlaurence.mapview.layout.animators
22

33
import android.animation.Animator
44
import android.animation.ValueAnimator
5-
import android.view.animation.Interpolator
6-
import kotlin.math.pow
5+
import android.view.animation.AccelerateInterpolator
76

87
class ZoomPanAnimator(private val listener: OnZoomPanAnimationListener) : ValueAnimator(),
98
ValueAnimator.AnimatorUpdateListener, Animator.AnimatorListener {
109

11-
private val mStartState = ZoomPanState()
12-
private val mEndState = ZoomPanState()
13-
private var mHasPendingZoomUpdates: Boolean = false
14-
private var mHasPendingPanUpdates: Boolean = false
10+
private val startState = ZoomPanState()
11+
private val endState = ZoomPanState()
12+
private var hasPendingZoomUpdates: Boolean = false
13+
private var hasPendingPanUpdates: Boolean = false
1514

1615
init {
1716
addUpdateListener(this)
1817
addListener(this)
1918
setFloatValues(0f, 1f)
20-
interpolator = FastEaseInInterpolator()
19+
interpolator = AccelerateInterpolator()
2120
}
2221

2322
private fun setupPanAnimation(x: Int, y: Int): Boolean {
24-
mStartState.x = listener.getScrollX()
25-
mStartState.y = listener.getScrollY()
26-
mEndState.x = x
27-
mEndState.y = y
28-
return mStartState.x != mEndState.x || mStartState.y != mEndState.y
23+
startState.x = listener.getScrollX()
24+
startState.y = listener.getScrollY()
25+
endState.x = x
26+
endState.y = y
27+
return startState.x != endState.x || startState.y != endState.y
2928
}
3029

3130
private fun setupZoomAnimation(scale: Float): Boolean {
32-
mStartState.scale = listener.getScale()
33-
mEndState.scale = scale
34-
return mStartState.scale != mEndState.scale
31+
startState.scale = listener.getScale()
32+
endState.scale = scale
33+
return startState.scale != endState.scale
3534
}
3635

3736
fun animateZoomPan(x: Int, y: Int, scale: Float) {
38-
mHasPendingZoomUpdates = setupZoomAnimation(scale)
39-
mHasPendingPanUpdates = setupPanAnimation(x, y)
40-
if (mHasPendingPanUpdates || mHasPendingZoomUpdates) {
37+
hasPendingZoomUpdates = setupZoomAnimation(scale)
38+
hasPendingPanUpdates = setupPanAnimation(x, y)
39+
if (hasPendingPanUpdates || hasPendingZoomUpdates) {
4140
start()
4241
}
4342
}
4443

4544
fun animateZoom(scale: Float) {
46-
mHasPendingZoomUpdates = setupZoomAnimation(scale)
47-
if (mHasPendingZoomUpdates) {
45+
hasPendingZoomUpdates = setupZoomAnimation(scale)
46+
if (hasPendingZoomUpdates) {
4847
start()
4948
}
5049
}
5150

5251
fun animatePan(x: Int, y: Int) {
53-
mHasPendingPanUpdates = setupPanAnimation(x, y)
54-
if (mHasPendingPanUpdates) {
52+
hasPendingPanUpdates = setupPanAnimation(x, y)
53+
if (hasPendingPanUpdates) {
5554
start()
5655
}
5756
}
5857

5958
override fun onAnimationUpdate(animation: ValueAnimator) {
6059
val progress = animation.animatedValue as Float
61-
if (mHasPendingZoomUpdates) {
62-
val scale = mStartState.scale + (mEndState.scale - mStartState.scale) * progress
60+
if (hasPendingZoomUpdates) {
61+
val scale = startState.scale + (endState.scale - startState.scale) * progress
6362
listener.setScale(scale)
6463
}
65-
if (mHasPendingPanUpdates) {
66-
val x = (mStartState.x + (mEndState.x - mStartState.x) * progress).toInt()
67-
val y = (mStartState.y + (mEndState.y - mStartState.y) * progress).toInt()
64+
if (hasPendingPanUpdates) {
65+
val x = (startState.x + (endState.x - startState.x) * progress).toInt()
66+
val y = (startState.y + (endState.y - startState.y) * progress).toInt()
6867
listener.scrollTo(x, y)
6968
}
7069
}
7170

7271
override fun onAnimationStart(animator: Animator) {
73-
if (mHasPendingZoomUpdates) {
72+
if (hasPendingZoomUpdates) {
7473
listener.setIsScaling(true)
7574
}
76-
if (mHasPendingPanUpdates) {
75+
if (hasPendingPanUpdates) {
7776
listener.setIsSliding(true)
7877
}
7978
}
8079

8180
override fun onAnimationEnd(animator: Animator) {
82-
if (mHasPendingZoomUpdates) {
83-
mHasPendingZoomUpdates = false
81+
if (hasPendingZoomUpdates) {
82+
hasPendingZoomUpdates = false
8483
listener.setIsScaling(false)
8584
}
86-
if (mHasPendingPanUpdates) {
87-
mHasPendingPanUpdates = false
85+
if (hasPendingPanUpdates) {
86+
hasPendingPanUpdates = false
8887
listener.setIsSliding(false)
8988
}
9089
}
@@ -103,12 +102,6 @@ class ZoomPanAnimator(private val listener: OnZoomPanAnimationListener) : ValueA
103102
var scale: Float = 0.toFloat()
104103
}
105104

106-
private class FastEaseInInterpolator : Interpolator {
107-
override fun getInterpolation(input: Float): Float {
108-
return (1 - (1 - input).toDouble().pow(8.0)).toFloat()
109-
}
110-
}
111-
112105
interface OnZoomPanAnimationListener {
113106
fun setIsScaling(isScaling: Boolean)
114107
fun setIsSliding(isSliding: Boolean)

0 commit comments

Comments
 (0)