diff --git a/api/current.txt b/api/current.txt index 5b79660e..3378d6fe 100644 --- a/api/current.txt +++ b/api/current.txt @@ -12,6 +12,17 @@ package androidx.core.animation { method public static android.animation.Animator.AnimatorListener doOnStart(android.animation.Animator, kotlin.jvm.functions.Function1 action); } + public final class ViewPropertyAnimatorKt { + ctor public ViewPropertyAnimatorKt(); + method public static android.animation.Animator.AnimatorListener doOnCancel(android.view.ViewPropertyAnimator, kotlin.jvm.functions.Function1 action); + method public static android.animation.Animator.AnimatorListener doOnEnd(android.view.ViewPropertyAnimator, kotlin.jvm.functions.Function1 action); + method public static android.animation.Animator.AnimatorListener doOnRepeat(android.view.ViewPropertyAnimator, kotlin.jvm.functions.Function1 action); + method public static android.animation.Animator.AnimatorListener doOnStart(android.view.ViewPropertyAnimator, kotlin.jvm.functions.Function1 action); + method public static android.animation.ValueAnimator.AnimatorUpdateListener doOnUpdate(android.view.ViewPropertyAnimator, kotlin.jvm.functions.Function1 action); + method public static android.animation.Animator.AnimatorListener setListener(android.view.ViewPropertyAnimator, kotlin.jvm.functions.Function1? onEnd = "null", kotlin.jvm.functions.Function1? onStart = "null", kotlin.jvm.functions.Function1? onCancel = "null", kotlin.jvm.functions.Function1? onRepeat = "null"); + method public static android.animation.ValueAnimator.AnimatorUpdateListener setUpdateListener(android.view.ViewPropertyAnimator, kotlin.jvm.functions.Function1? onUpdate = "null"); + } + } package androidx.core.content { diff --git a/src/androidTest/java/androidx/core/animation/ViewPropertyAnimatorTest.kt b/src/androidTest/java/androidx/core/animation/ViewPropertyAnimatorTest.kt new file mode 100644 index 00000000..496779fd --- /dev/null +++ b/src/androidTest/java/androidx/core/animation/ViewPropertyAnimatorTest.kt @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package androidx.core.animation + +import android.support.test.InstrumentationRegistry +import android.support.test.annotation.UiThreadTest +import android.support.test.filters.SdkSuppress +import android.support.test.runner.AndroidJUnit4 +import android.view.View +import android.view.ViewPropertyAnimator +import org.junit.Assert +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class ViewPropertyAnimatorTest { + private val context = InstrumentationRegistry.getContext() + private val view = View(context) + + private lateinit var animator: ViewPropertyAnimator + + @Before + fun before() { + view.alpha = 0f + animator = view.animate().alpha(1f).setDuration(0) + } + + @UiThreadTest + @Test fun testDoOnStart() { + var called = false + animator.doOnStart { + called = true + } + + animator.start() + Assert.assertTrue(called) + } + + @UiThreadTest + @Test fun testDoOnEnd() { + var called = false + animator.doOnEnd { + called = true + } + + animator.start() + animator.cancel() + Assert.assertTrue(called) + } + + @UiThreadTest + @Test fun testDoOnCancel() { + var cancelCalled = false + animator.doOnCancel { + cancelCalled = true + } + + animator.start() + animator.cancel() + Assert.assertTrue(cancelCalled) + } + + @UiThreadTest + @SdkSuppress(minSdkVersion = 19) + @Test fun testDoOnUpdate() { + var called = false + animator.doOnUpdate { + called = true + } + + animator.start() + Assert.assertTrue(called) + } +} \ No newline at end of file diff --git a/src/main/java/androidx/core/animation/ViewPropertyAnimator.kt b/src/main/java/androidx/core/animation/ViewPropertyAnimator.kt new file mode 100644 index 00000000..f921e7da --- /dev/null +++ b/src/main/java/androidx/core/animation/ViewPropertyAnimator.kt @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package androidx.core.animation + +import android.animation.Animator +import android.animation.ValueAnimator +import android.view.ViewPropertyAnimator +import androidx.annotation.RequiresApi + +/** + * Add an action which will be invoked when the animation has ended. + * + * @return the [Animator.AnimatorListener] added to the Animator + * @see Animator.end + */ +fun ViewPropertyAnimator.doOnEnd(action: (animator: Animator) -> Unit) = + setListener(onEnd = action) + +/** + * Add an action which will be invoked when the animation has started. + * + * @return the [Animator.AnimatorListener] added to the Animator + * @see Animator.start + */ +fun ViewPropertyAnimator.doOnStart(action: (animator: Animator) -> Unit) = + setListener(onStart = action) + +/** + * Add an action which will be invoked when the animation has been cancelled. + * + * @return the [Animator.AnimatorListener] added to the Animator + * @see Animator.cancel + */ +fun ViewPropertyAnimator.doOnCancel(action: (animator: Animator) -> Unit) = + setListener(onCancel = action) + +/** + * Add an action which will be invoked when the animation has repeated. + * @return the [Animator.AnimatorListener] added to the Animator + */ +fun ViewPropertyAnimator.doOnRepeat(action: (animator: Animator) -> Unit) = + setListener(onRepeat = action) + +/** + * Add an action which will be invoked when the animation has been updated. + * + * @return the [ValueAnimator.AnimatorUpdateListener] added to the Animator + * @see Animator.pause + */ +@RequiresApi(19) +fun ViewPropertyAnimator.doOnUpdate(action: (animator: ValueAnimator?) -> Unit) = + setUpdateListener(onUpdate = action) + +/** + * Add a listener to this Animator using the provided actions. + */ +fun ViewPropertyAnimator.setListener( + onEnd: ((animator: Animator) -> Unit)? = null, + onStart: ((animator: Animator) -> Unit)? = null, + onCancel: ((animator: Animator) -> Unit)? = null, + onRepeat: ((animator: Animator) -> Unit)? = null +): Animator.AnimatorListener { + val listener = object : Animator.AnimatorListener { + override fun onAnimationRepeat(animator: Animator) { + onRepeat?.invoke(animator) + } + + override fun onAnimationEnd(animator: Animator) { + onEnd?.invoke(animator) + } + + override fun onAnimationCancel(animator: Animator) { + onCancel?.invoke(animator) + } + + override fun onAnimationStart(animator: Animator) { + onStart?.invoke(animator) + } + } + setListener(listener) + return listener +} + +/** + * Add an update listener to this Animator using the provided actions. + */ +@RequiresApi(19) +fun ViewPropertyAnimator.setUpdateListener( + onUpdate: ((animator: ValueAnimator?) -> Unit)? = null +): ValueAnimator.AnimatorUpdateListener { + val listener = ValueAnimator.AnimatorUpdateListener { + onUpdate?.invoke(it) + } + setUpdateListener(listener) + return listener +}