Skip to content

Commit

Permalink
offset collapsing animation implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
RareScrap committed Nov 7, 2021
1 parent ab42e1b commit ca373fe
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 11 deletions.
43 changes: 43 additions & 0 deletions lib/src/main/java/me/onebone/toolbar/CollapsingToolbar.kt
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import androidx.compose.foundation.gestures.FlingBehavior
import androidx.compose.foundation.gestures.ScrollScope
import androidx.compose.foundation.gestures.ScrollableState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.Stable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
Expand Down Expand Up @@ -136,6 +137,7 @@ class CollapsingToolbarState(
)
fun feedScroll(value: Float): Float = dispatchRawDelta(value)

// TODO: A strange jump in snap speed is often observed
@ExperimentalToolbarApi
suspend fun expand(duration: Int = CollapsingToolbarDefaults.EXPAND_DURATION) {
val anim = AnimationState(height.toFloat())
Expand All @@ -149,6 +151,7 @@ class CollapsingToolbarState(
}
}

// TODO: A strange jump in snap speed is often observed
@ExperimentalToolbarApi
suspend fun collapse(duration: Int = CollapsingToolbarDefaults.COLLAPSE_DURATION) {
val anim = AnimationState(height.toFloat())
Expand All @@ -162,6 +165,46 @@ class CollapsingToolbarState(
}
}

@ExperimentalToolbarApi
suspend fun expandOffset(snapStrategy: SnapStrategy, offsetY: MutableState<Int>) {
val anim = AnimationState(offsetY.value.toFloat())

anim.animateTo(0f, tween(snapStrategy.expandDuration)) {
offsetY.value = value.toInt()
}
}

@ExperimentalToolbarApi
suspend fun collapseOffset(snapStrategy: SnapStrategy, offsetY: MutableState<Int>) {
val anim = AnimationState(offsetY.value.toFloat())

anim.animateTo(-minHeight.toFloat(), tween(snapStrategy.collapseDuration)) {
offsetY.value = value.toInt()
}
}

// TODO: Is there a better solution rather OptIn ExperimentalToolbarApi?
@OptIn(ExperimentalToolbarApi::class)
internal suspend fun processSnap(strategy: SnapStrategy) {
if (progress > strategy.edge) {
expand(strategy.expandDuration)
} else {
collapse(strategy.collapseDuration)
}
}

// TODO: Is there a better solution rather OptIn ExperimentalToolbarApi?
@OptIn(ExperimentalToolbarApi::class)
internal suspend fun processOffsetSnap(snapStrategy: SnapStrategy, offsetY: MutableState<Int>) {
val offsetProgress =
1f - ((offsetY.value / (minHeight / 100f)) / 100f).absoluteValue
if (offsetProgress > snapStrategy.edge) {
expandOffset(snapStrategy, offsetY)
} else {
collapseOffset(snapStrategy, offsetY)
}
}

/**
* @return Remaining velocity after fling
*/
Expand Down
13 changes: 13 additions & 0 deletions lib/src/main/java/me/onebone/toolbar/ScrollStrategy.kt
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,19 @@ internal class EnterAlwaysCollapsedNestedScrollConnection(
dy
}

// TODO: Cancel expand/collapse animation inside onPreScroll
snapStrategy?.let {
val isToolbarChangingOffset = offsetY.value != 0//toolbarState.progress == 0f
if (isToolbarChangingOffset) {
// When the toolbar is hiding, it does it through changing the offset and does not
// change its height, so we must process not the snap of the toolbar, but the
// snap of its offset.
toolbarState.processOffsetSnap(it, offsetY)
} else {
toolbarState.processSnap(it)
}
}

return available.copy(y = available.y - left)
}
}
Expand Down
12 changes: 1 addition & 11 deletions lib/src/main/java/me/onebone/toolbar/SnapStrategy.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,4 @@ class SnapStrategy(
@FloatRange(from = 0.0, to = 1.0) val edge: Float = CollapsingToolbarDefaults.EDGE,
val expandDuration: Int = CollapsingToolbarDefaults.EXPAND_DURATION,
val collapseDuration: Int = CollapsingToolbarDefaults.COLLAPSE_DURATION
)

// TODO: Is there a better solution rather OptIn ExperimentalToolbarApi?
@OptIn(ExperimentalToolbarApi::class)
internal suspend fun CollapsingToolbarState.processSnap(strategy: SnapStrategy) {
if (progress > strategy.edge) {
expand(strategy.expandDuration)
} else {
collapse(strategy.collapseDuration)
}
}
)

0 comments on commit ca373fe

Please sign in to comment.