-
-
Notifications
You must be signed in to change notification settings - Fork 1k
[General] Update button's animation duration props #4046
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: @jpiasecki/refactor-button
Are you sure you want to change the base?
Changes from all commits
8bceb77
16805c8
c571692
af7ea63
2d09358
0522f2f
f564653
fdcc8cc
2142a8c
eafff80
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -15,6 +15,7 @@ import android.graphics.drawable.RippleDrawable | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import android.graphics.drawable.ShapeDrawable | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import android.graphics.drawable.shapes.RectShape | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import android.os.Build | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import android.os.SystemClock | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import android.util.TypedValue | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import android.view.KeyEvent | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import android.view.MotionEvent | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -266,9 +267,14 @@ class RNGestureHandlerButtonViewManager : | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| view.isSoundEffectsEnabled = !touchSoundDisabled | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @ReactProp(name = "animationDuration") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| override fun setAnimationDuration(view: ButtonViewGroup, animationDuration: Int) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| view.animationDuration = animationDuration | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @ReactProp(name = "pressAndHoldAnimationDuration") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| override fun setPressAndHoldAnimationDuration(view: ButtonViewGroup, pressAndHoldAnimationDuration: Int) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| view.pressAndHoldAnimationDuration = pressAndHoldAnimationDuration | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @ReactProp(name = "tapAnimationDuration") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| override fun setTapAnimationDuration(view: ButtonViewGroup, tapAnimationDuration: Int) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| view.tapAnimationDuration = tapAnimationDuration | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @ReactProp(name = "defaultOpacity") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -346,7 +352,9 @@ class RNGestureHandlerButtonViewManager : | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| var useBorderlessDrawable = false | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| var exclusive = true | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| var animationDuration: Int = 100 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| var tapAnimationDuration: Int = 100 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| var pressAndHoldAnimationDuration: Int = -1 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| get() = if (field < 0) tapAnimationDuration else field | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| var activeOpacity: Float = 1.0f | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| var defaultOpacity: Float = 1.0f | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| var activeScale: Float = 1.0f | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -369,6 +377,8 @@ class RNGestureHandlerButtonViewManager : | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private var receivedKeyEvent = false | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private var currentAnimator: AnimatorSet? = null | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private var underlayDrawable: PaintDrawable? = null | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private var pressInTimestamp = 0L | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private var pendingPressOut: Runnable? = null | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
378
to
382
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // When non-null the ripple is drawn in dispatchDraw (above background, below children). | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // When null the ripple lives on the foreground drawable instead. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -487,7 +497,7 @@ class RNGestureHandlerButtonViewManager : | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| underlayDrawable?.alpha = (defaultUnderlayOpacity * 255).toInt() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private fun animateTo(opacity: Float, scale: Float, underlayOpacity: Float) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private fun animateTo(opacity: Float, scale: Float, underlayOpacity: Float, durationMs: Long) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| val hasOpacity = activeOpacity != 1.0f || defaultOpacity != 1.0f | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| val hasScale = activeScale != 1.0f || defaultScale != 1.0f | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| val hasUnderlay = activeUnderlayOpacity != defaultUnderlayOpacity && underlayDrawable != null | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -509,18 +519,41 @@ class RNGestureHandlerButtonViewManager : | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| currentAnimator = AnimatorSet().apply { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| playTogether(animators) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| duration = animationDuration.toLong() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| duration = durationMs | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| interpolator = LinearOutSlowInInterpolator() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| start() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private fun animatePressIn() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| animateTo(activeOpacity, activeScale, activeUnderlayOpacity) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pendingPressOut?.let { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| handler.removeCallbacks(it) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pendingPressOut = null | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pressInTimestamp = SystemClock.uptimeMillis() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| animateTo(activeOpacity, activeScale, activeUnderlayOpacity, pressAndHoldAnimationDuration.toLong()) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private fun animatePressOut() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| animateTo(defaultOpacity, defaultScale, defaultUnderlayOpacity) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pendingPressOut?.let { handler.removeCallbacks(it) } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| val elapsed = SystemClock.uptimeMillis() - pressInTimestamp | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (elapsed >= pressAndHoldAnimationDuration) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| animateTo(defaultOpacity, defaultScale, defaultUnderlayOpacity, pressAndHoldAnimationDuration.toLong()) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // elapsed * 2 to ensure there is at least half of the tapAnimationDuration left for the animation to play | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } else if (elapsed * 2 >= tapAnimationDuration) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| animateTo(defaultOpacity, defaultScale, defaultUnderlayOpacity, elapsed) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| val remaining = tapAnimationDuration - elapsed | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| animateTo(activeOpacity, activeScale, activeUnderlayOpacity, remaining) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| val runnable = Runnable { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pendingPressOut = null | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| animateTo(defaultOpacity, defaultScale, defaultUnderlayOpacity, tapAnimationDuration.toLong()) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+540
to
+552
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (elapsed >= pressAndHoldAnimationDuration) { | |
| animateTo(defaultOpacity, defaultScale, defaultUnderlayOpacity, pressAndHoldAnimationDuration.toLong()) | |
| // elapsed * 2 to ensure there is at least half of the tapAnimationDuration left for the animation to play | |
| } else if (elapsed * 2 >= tapAnimationDuration) { | |
| animateTo(defaultOpacity, defaultScale, defaultUnderlayOpacity, elapsed) | |
| } else { | |
| val remaining = tapAnimationDuration - elapsed | |
| animateTo(activeOpacity, activeScale, activeUnderlayOpacity, remaining) | |
| val runnable = Runnable { | |
| pendingPressOut = null | |
| animateTo(defaultOpacity, defaultScale, defaultUnderlayOpacity, tapAnimationDuration.toLong()) | |
| val pressAndHoldMs = pressAndHoldAnimationDuration.toLong() | |
| val tapMs = tapAnimationDuration.toLong() | |
| if (elapsed >= pressAndHoldMs) { | |
| animateTo(defaultOpacity, defaultScale, defaultUnderlayOpacity, pressAndHoldMs) | |
| // elapsed * 2 to ensure there is at least half of the tapAnimationDuration left for the animation to play | |
| } else if (elapsed * 2 >= tapMs) { | |
| animateTo(defaultOpacity, defaultScale, defaultUnderlayOpacity, elapsed) | |
| } else { | |
| val remaining = tapMs - elapsed | |
| animateTo(activeOpacity, activeScale, activeUnderlayOpacity, remaining) | |
| val runnable = Runnable { | |
| pendingPressOut = null | |
| animateTo(defaultOpacity, defaultScale, defaultUnderlayOpacity, tapMs) |
Copilot
AI
Apr 1, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
val remaining = tapAnimationDuration - elapsed mixes Int and Long (won’t compile), and handler.postDelayed(runnable, remaining) expects a non-negative Long delay. After converting tapAnimationDuration to Long, ensure remaining is computed as Long and clamped to >= 0 before calling postDelayed.
Uh oh!
There was an error while loading. Please reload this page.