Skip to content

Commit de58abf

Browse files
authored
feat: added parameter to modify duration to AnimationUtil (#1505)
* feat: added parameter to modify duration to AnimationUtil * feat: link as HTML * feat: added test * feat: headers * feat: headers
1 parent 0c56a37 commit de58abf

File tree

4 files changed

+101
-5
lines changed

4 files changed

+101
-5
lines changed

gradle/libs.versions.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ dokka-gradle-plugin = { module = "org.jetbrains.dokka:dokka-gradle-plugin", vers
2626
gradle = { module = "com.android.tools.build:gradle", version.ref = "gradle" }
2727
jacoco-android = { module = "com.mxalbert.gradle:jacoco-android", version.ref = "jacoco-android" }
2828
kotlin-gradle-plugin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin" }
29+
kotlin-test = { module = "org.jetbrains.kotlin:kotlin-test", version.ref = "kotlin" }
2930
lifecycle-extensions = { module = "androidx.lifecycle:lifecycle-extensions", version.ref = "lifecycle-extensions" }
3031
lifecycle-viewmodel-ktx = { module = "androidx.lifecycle:lifecycle-viewmodel-ktx", version.ref = "lifecycle-viewmodel-ktx" }
3132
kotlin-stdlib-jdk8 = { module = "org.jetbrains.kotlin:kotlin-stdlib-jdk8", version.ref = "kotlin" }

library/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ dependencies {
6868
testImplementation(libs.robolectric)
6969
testImplementation(libs.kxml2)
7070
testImplementation(libs.mockk)
71+
testImplementation (libs.kotlin.test)
7172
implementation(libs.kotlin.stdlib.jdk8)
7273
}
7374

library/src/main/java/com/google/maps/android/ui/AnimationUtil.java

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,20 +29,35 @@
2929
* <p>
3030
*/
3131
public class AnimationUtil {
32-
32+
3333
/**
3434
* Animates a marker from it's current position to the provided finalPosition
3535
*
3636
* @param marker marker to animate
3737
* @param finalPosition the final position of the marker after the animation
3838
*/
39-
public static void animateMarkerTo(final Marker marker, final LatLng finalPosition) {
39+
public static void animateMarkerTo(final Marker marker, final LatLng finalPosition) {
40+
animateMarkerTo(marker, finalPosition, 2000); // delegate to new version
41+
}
42+
43+
44+
/**
45+
* Animates a marker from its current position to the provided finalPosition.
46+
*
47+
* @param marker marker to animate
48+
* @param finalPosition the final position of the marker after the animation
49+
* @param durationInMs the duration of the animation in milliseconds
50+
*/
51+
public static void animateMarkerTo(
52+
final Marker marker,
53+
final LatLng finalPosition,
54+
final long durationInMs
55+
) {
4056
final LatLngInterpolator latLngInterpolator = new LatLngInterpolator.Linear();
4157
final LatLng startPosition = marker.getPosition();
4258
final Handler handler = new Handler();
4359
final long start = SystemClock.uptimeMillis();
4460
final Interpolator interpolator = new AccelerateDecelerateInterpolator();
45-
final float durationInMs = 2000;
4661

4762
handler.post(new Runnable() {
4863
long elapsed;
@@ -55,7 +70,7 @@ public static void animateMarkerTo(final Marker marker, final LatLng finalPositi
5570
public void run() {
5671
// Calculate progress using interpolator
5772
elapsed = SystemClock.uptimeMillis() - start;
58-
t = elapsed / durationInMs;
73+
t = elapsed / (float) durationInMs;
5974
v = interpolator.getInterpolation(t);
6075

6176
marker.setPosition(latLngInterpolator.interpolate(v, startPosition, finalPosition));
@@ -70,7 +85,7 @@ public void run() {
7085
}
7186

7287
/**
73-
* For other LatLngInterpolator interpolators, see https://gist.github.com/broady/6314689
88+
* For other LatLngInterpolator interpolators, see <a href="https://gist.github.com/broady/6314689">link here</a>
7489
*/
7590
interface LatLngInterpolator {
7691

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
/*
2+
* Copyright 2025 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.google.maps.android
18+
19+
import com.google.android.gms.maps.model.LatLng
20+
import com.google.android.gms.maps.model.Marker
21+
import com.google.maps.android.ui.AnimationUtil
22+
import io.mockk.*
23+
import org.junit.After
24+
import org.junit.Before
25+
import org.junit.Test
26+
import org.junit.runner.RunWith
27+
import org.robolectric.RobolectricTestRunner
28+
import org.robolectric.Shadows
29+
import java.util.concurrent.TimeUnit
30+
import kotlin.test.assertEquals
31+
32+
@RunWith(RobolectricTestRunner::class)
33+
class AnimationUtilTest {
34+
35+
private lateinit var marker: Marker
36+
private lateinit var currentPosition: LatLng
37+
38+
@Before
39+
fun setUp() {
40+
marker = mockk(relaxed = true)
41+
42+
// Initial position
43+
currentPosition = LatLng(0.0, 0.0)
44+
45+
// Mock the marker position getter and setter
46+
every { marker.position } answers { currentPosition }
47+
every { marker.setPosition(any()) } answers {
48+
currentPosition = firstArg()
49+
Unit
50+
}
51+
}
52+
53+
@After
54+
fun tearDown() {
55+
unmockkAll()
56+
}
57+
58+
@Test
59+
fun `animateMarkerTo moves marker to final position with a buffer tolerance`() {
60+
val finalPosition = LatLng(10.0, 10.0)
61+
val durationMs = 100L
62+
63+
// Start the animation
64+
AnimationUtil.animateMarkerTo(marker, finalPosition, durationMs)
65+
66+
val mainLooper = Shadows.shadowOf(android.os.Looper.getMainLooper())
67+
68+
// Simulate time passing in 16ms increments until we exceed the animation duration
69+
var timePassed = 0L
70+
while (timePassed <= durationMs + 100) { // Allowing a little buffer for completion
71+
mainLooper.idleFor(16, TimeUnit.MILLISECONDS)
72+
timePassed += 16
73+
}
74+
75+
// Check the final position — allowing a reasonable tolerance (0.5 or more)
76+
assertEquals(10.0, currentPosition.latitude, 0.5) // 0.5 tolerance
77+
assertEquals(10.0, currentPosition.longitude, 0.5) // 0.5 tolerance
78+
}
79+
}

0 commit comments

Comments
 (0)