Updated on 2026-08-14
This commit is contained in:
parent
128faaec8d
commit
31e0591ef0
20 changed files with 1242 additions and 20 deletions
|
|
@ -1,6 +1,7 @@
|
|||
package com.tangem.core.ui.ds.button
|
||||
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.compose.runtime.Stable
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
|
||||
/**
|
||||
|
|
@ -19,6 +20,7 @@ import com.tangem.core.ui.extensions.TextReference
|
|||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
@Stable
|
||||
data class TangemButtonUM(
|
||||
val text: TextReference? = null,
|
||||
val descriptionText: TextReference? = null,
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ package com.tangem.core.ui.ds.topbar
|
|||
|
||||
import android.content.res.Configuration
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.animation.*
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.material3.Icon
|
||||
|
|
@ -55,6 +55,7 @@ fun TangemTopBar(
|
|||
modifier = modifier,
|
||||
content = {
|
||||
Column(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
verticalArrangement = Arrangement.spacedBy(TangemTheme.dimens2.x0_5),
|
||||
) {
|
||||
|
|
@ -95,11 +96,17 @@ private fun TangemTopBarTitle(title: TextReference?, @DrawableRes titleIconRes:
|
|||
AnimatedVisibility(
|
||||
visible = title != null,
|
||||
label = "Title Visibility",
|
||||
enter = slideInVertically(initialOffsetY = { it / 2 }) + fadeIn(),
|
||||
exit = slideOutVertically(targetOffsetY = { it / 2 }) + fadeOut(),
|
||||
) {
|
||||
val wrappedTitle = remember(this) { requireNotNull(title) }
|
||||
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.spacedBy(TangemTheme.dimens2.x1),
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
horizontalArrangement = Arrangement.spacedBy(
|
||||
space = TangemTheme.dimens2.x1,
|
||||
alignment = Alignment.CenterHorizontally,
|
||||
),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
AnimatedVisibility(
|
||||
|
|
|
|||
|
|
@ -0,0 +1,126 @@
|
|||
package com.tangem.core.ui.ds.topbar.collapsing
|
||||
|
||||
import android.content.res.Configuration
|
||||
import androidx.compose.animation.core.AnimationSpec
|
||||
import androidx.compose.animation.core.DecayAnimationSpec
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.Stable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
|
||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||
import androidx.compose.ui.layout.Layout
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.tangem.core.ui.ds.topbar.collapsing.entity.TangemCollapsingAppBarState
|
||||
import com.tangem.core.ui.res.TangemThemePreviewRedesign
|
||||
import kotlin.math.max
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
|
||||
@Composable
|
||||
fun TangemCollapsingTopBar(
|
||||
state: TangemCollapsingAppBarState,
|
||||
collapsingPart: @Composable () -> Unit,
|
||||
body: @Composable () -> Unit,
|
||||
) {
|
||||
Layout(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
content = {
|
||||
collapsingPart()
|
||||
body()
|
||||
},
|
||||
) { measurables, constraints ->
|
||||
|
||||
val collapsingConstraints = constraints.copy(
|
||||
minWidth = 0,
|
||||
minHeight = 0,
|
||||
)
|
||||
val collapsingPlaceable = measurables[0].measure(collapsingConstraints)
|
||||
|
||||
val bodyConstraints = constraints.copy(
|
||||
minWidth = 0,
|
||||
minHeight = 0,
|
||||
maxHeight = (constraints.maxHeight - collapsingConstraints.minHeight).coerceAtLeast(0),
|
||||
)
|
||||
val bodyPlaceable = measurables[1].measure(bodyConstraints)
|
||||
|
||||
val minHeight = 0.dp.roundToPx()
|
||||
val maxHeight = collapsingPlaceable.height + minHeight
|
||||
|
||||
val offset = state.heightOffset.roundToInt().coerceAtLeast(-maxHeight)
|
||||
|
||||
val width = max(
|
||||
collapsingPlaceable.width,
|
||||
bodyPlaceable.width,
|
||||
).coerceIn(constraints.minWidth, constraints.maxWidth)
|
||||
val height = max(
|
||||
collapsingPlaceable.height,
|
||||
bodyPlaceable.height,
|
||||
).coerceIn(constraints.minHeight, constraints.maxHeight)
|
||||
|
||||
layout(width = width, height = height) {
|
||||
bodyPlaceable.placeRelative(0, collapsingPlaceable.height + offset)
|
||||
collapsingPlaceable.placeRelative(0, offset)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A scroll behavior for a collapsing top app bar that collapses when scrolling up and expands when scrolling down.
|
||||
*
|
||||
* @property state The state of the collapsing app bar.
|
||||
* @property snapAnimationSpec The animation spec used for snapping the app bar to its collapsed or
|
||||
* expanded state after a fling. If null, no snapping will occur.
|
||||
* @property flingAnimationSpec The decay animation spec used for fling gestures.
|
||||
* If null, fling gestures will not be handled.
|
||||
* @property nestedScrollConnection Nested scroll connection
|
||||
*/
|
||||
@Stable
|
||||
data class TangemCollapsingAppBarBehavior(
|
||||
val state: TangemCollapsingAppBarState,
|
||||
val snapAnimationSpec: AnimationSpec<Float>?,
|
||||
val flingAnimationSpec: DecayAnimationSpec<Float>?,
|
||||
val nestedScrollConnection: NestedScrollConnection,
|
||||
)
|
||||
|
||||
// region Preview
|
||||
@Composable
|
||||
@Preview(showBackground = true, widthDp = 360)
|
||||
@Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
private fun TangemCollapsingTopBar_Preview() {
|
||||
TangemThemePreviewRedesign {
|
||||
val collapsingHeight = 200.dp
|
||||
val behavior = rememberTangemExitUntilCollapsedScrollBehavior(
|
||||
expandedHeight = collapsingHeight,
|
||||
)
|
||||
TangemCollapsingTopBar(
|
||||
state = behavior.state,
|
||||
collapsingPart = {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.height(collapsingHeight)
|
||||
.background(Color.Red),
|
||||
)
|
||||
},
|
||||
body = {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.background(Color.Blue)
|
||||
.nestedScroll(behavior.nestedScrollConnection)
|
||||
.verticalScroll(rememberScrollState()),
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
// endregion
|
||||
|
|
@ -0,0 +1,211 @@
|
|||
package com.tangem.core.ui.ds.topbar.collapsing
|
||||
|
||||
import androidx.compose.animation.core.*
|
||||
import androidx.compose.animation.rememberSplineBasedDecay
|
||||
import androidx.compose.foundation.gestures.Orientation
|
||||
import androidx.compose.foundation.gestures.draggable
|
||||
import androidx.compose.foundation.gestures.rememberDraggableState
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.geometry.Offset
|
||||
import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
|
||||
import androidx.compose.ui.input.nestedscroll.NestedScrollSource
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.Velocity
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.tangem.core.ui.ds.topbar.collapsing.entity.TangemCollapsingAppBarState
|
||||
import com.tangem.core.ui.ds.topbar.collapsing.entity.TopBapScrollDirection
|
||||
import com.tangem.core.ui.ds.topbar.collapsing.entity.rememberTangemCollapsingAppBarState
|
||||
import com.tangem.core.ui.utils.toPx
|
||||
import kotlin.math.abs
|
||||
import kotlin.math.absoluteValue
|
||||
|
||||
/**
|
||||
* A scroll behavior for a collapsing top app bar that collapses when scrolling up and expands when scrolling down.
|
||||
* When the user stops scrolling, the app bar will settle to either fully collapsed or fully expanded state
|
||||
* based on the current collapsed fraction and scroll direction.
|
||||
*
|
||||
* @param expandedHeight The height of the app bar when it is fully expanded.
|
||||
* @param partialCollapsedHeight The height of the app bar when it is partially collapsed.
|
||||
* @param snapAnimationSpec The animation spec for snapping the app bar to the collapsed or expanded state when the
|
||||
* user stops scrolling. If null, no snapping will occur.
|
||||
* @param flingAnimationSpec The decay animation spec for the fling behavior when the user flings the app bar.
|
||||
* If null, no fling behavior will occur.
|
||||
*/
|
||||
@Composable
|
||||
fun rememberTangemExitUntilCollapsedScrollBehavior(
|
||||
expandedHeight: Dp = -Int.MAX_VALUE.dp,
|
||||
partialCollapsedHeight: Dp = expandedHeight,
|
||||
snapAnimationSpec: AnimationSpec<Float>? = spring(),
|
||||
flingAnimationSpec: DecayAnimationSpec<Float>? = rememberSplineBasedDecay(),
|
||||
): TangemCollapsingAppBarBehavior {
|
||||
val topBarState = rememberTangemCollapsingAppBarState(
|
||||
heightOffsetLimit = -expandedHeight.toPx(),
|
||||
partialHeightLimit = partialCollapsedHeight.toPx(),
|
||||
)
|
||||
return exitUntilCollapsedScrollBehavior(
|
||||
state = topBarState,
|
||||
snapAnimationSpec = snapAnimationSpec,
|
||||
flingAnimationSpec = flingAnimationSpec,
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* A scroll behavior for a collapsing top app bar that collapses when scrolling up and expands when scrolling down.
|
||||
* When the user stops scrolling, the app bar will settle to either fully collapsed or fully expanded state
|
||||
* based on the current collapsed fraction and scroll direction.
|
||||
*
|
||||
* @param state The state of the collapsing app bar, which controls the height offset and scroll behavior.
|
||||
* @param snapAnimationSpec The animation spec for snapping the app bar to the collapsed or expanded state when the
|
||||
* user stops scrolling. If null, no snapping will occur.
|
||||
* @param flingAnimationSpec The decay animation spec for the fling behavior when the user flings the app bar.
|
||||
* If null, no fling behavior will occur.
|
||||
*/
|
||||
@Composable
|
||||
private fun exitUntilCollapsedScrollBehavior(
|
||||
state: TangemCollapsingAppBarState = rememberTangemCollapsingAppBarState(),
|
||||
snapAnimationSpec: AnimationSpec<Float>? = spring(),
|
||||
flingAnimationSpec: DecayAnimationSpec<Float>? = rememberSplineBasedDecay(),
|
||||
): TangemCollapsingAppBarBehavior {
|
||||
val nestedScrollConnection = remember(state) {
|
||||
object : NestedScrollConnection {
|
||||
override fun onPreScroll(available: Offset, source: NestedScrollSource): Offset {
|
||||
val dy = available.y
|
||||
|
||||
val consume = if (dy < 0) {
|
||||
state.direction = TopBapScrollDirection.Collapsing
|
||||
state.dispatchRawDelta(dy)
|
||||
} else {
|
||||
0f
|
||||
}
|
||||
|
||||
return Offset(0f, consume)
|
||||
}
|
||||
|
||||
override fun onPostScroll(consumed: Offset, available: Offset, source: NestedScrollSource): Offset {
|
||||
val dy = available.y
|
||||
|
||||
val consume = if (dy > 0) {
|
||||
state.direction = TopBapScrollDirection.Expanding
|
||||
state.dispatchRawDelta(dy)
|
||||
} else {
|
||||
state.direction = TopBapScrollDirection.Collapsing
|
||||
0f
|
||||
}
|
||||
|
||||
return Offset(0f, consume)
|
||||
}
|
||||
|
||||
override suspend fun onPostFling(consumed: Velocity, available: Velocity): Velocity {
|
||||
val superConsumed = super.onPostFling(consumed, available)
|
||||
return superConsumed + settleAppBar(
|
||||
state = state,
|
||||
velocity = available.y,
|
||||
flingAnimationSpec = flingAnimationSpec,
|
||||
snapAnimationSpec = snapAnimationSpec,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return remember(state, nestedScrollConnection, snapAnimationSpec, flingAnimationSpec) {
|
||||
TangemCollapsingAppBarBehavior(
|
||||
state = state,
|
||||
snapAnimationSpec = snapAnimationSpec,
|
||||
flingAnimationSpec = flingAnimationSpec,
|
||||
nestedScrollConnection = nestedScrollConnection,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun Modifier.snapToExitUntilCollapsed(behavior: TangemCollapsingAppBarBehavior): Modifier {
|
||||
return draggable(
|
||||
orientation = Orientation.Vertical,
|
||||
state = rememberDraggableState { delta ->
|
||||
behavior.state.heightOffset += delta
|
||||
},
|
||||
onDragStopped = { velocity ->
|
||||
settleAppBar(
|
||||
state = behavior.state,
|
||||
velocity = velocity,
|
||||
flingAnimationSpec = behavior.flingAnimationSpec,
|
||||
snapAnimationSpec = behavior.snapAnimationSpec,
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Settles the app bar to either fully collapsed or fully expanded state
|
||||
* based on the current collapsed fraction and scroll direction.
|
||||
*/
|
||||
@Suppress("MagicNumber", "CyclomaticComplexMethod")
|
||||
private suspend fun settleAppBar(
|
||||
state: TangemCollapsingAppBarState,
|
||||
velocity: Float,
|
||||
flingAnimationSpec: DecayAnimationSpec<Float>?,
|
||||
snapAnimationSpec: AnimationSpec<Float>?,
|
||||
snapCollapseThreshold: Float = 0.3f,
|
||||
snapExpandThreshold: Float = 0.7f,
|
||||
): Velocity {
|
||||
val partialLimit = state.heightOffsetLimit + state.partialHeightLimit
|
||||
var remainingVelocity = velocity
|
||||
|
||||
// Check if the app bar is completely collapsed/expanded. If so, no need to settle the app bar,
|
||||
// and just return Zero Velocity.
|
||||
// Note that we don't check for 0f due to float precision with the collapsedFraction
|
||||
// calculation.
|
||||
if (state.collapsedFraction < 0.01f || state.collapsedFraction == 1f) {
|
||||
return Velocity.Zero
|
||||
}
|
||||
|
||||
// Fling
|
||||
if (flingAnimationSpec != null && velocity.absoluteValue > 1f) {
|
||||
var lastValue = 0f
|
||||
AnimationState(
|
||||
initialValue = 0f,
|
||||
initialVelocity = velocity,
|
||||
).animateDecay(flingAnimationSpec) {
|
||||
val delta = value - lastValue
|
||||
val initialHeightOffset = state.heightOffset
|
||||
|
||||
val availableDelta = partialLimit - initialHeightOffset
|
||||
|
||||
state.heightOffset = if (delta < 0f && initialHeightOffset > partialLimit) {
|
||||
(initialHeightOffset + delta).coerceAtLeast(partialLimit)
|
||||
} else {
|
||||
initialHeightOffset + delta
|
||||
}
|
||||
|
||||
val consumed = abs(initialHeightOffset - state.heightOffset)
|
||||
lastValue = value
|
||||
remainingVelocity = this.velocity
|
||||
// avoid rounding errors and stop if anything is unconsumed
|
||||
if (abs(maxOf(delta, availableDelta) - consumed) > 0.5f) this.cancelAnimation()
|
||||
}
|
||||
}
|
||||
// Snap
|
||||
if (snapAnimationSpec != null && state.heightOffset > partialLimit && state.heightOffset < 0f) {
|
||||
AnimationState(initialValue = state.heightOffset).animateTo(
|
||||
when (state.direction) {
|
||||
TopBapScrollDirection.Collapsing -> if (state.collapsedFraction > snapCollapseThreshold) {
|
||||
partialLimit
|
||||
} else {
|
||||
0f
|
||||
}
|
||||
TopBapScrollDirection.Expanding -> if (state.collapsedFraction < snapExpandThreshold) {
|
||||
0f
|
||||
} else {
|
||||
partialLimit
|
||||
}
|
||||
TopBapScrollDirection.Idle -> 0f
|
||||
},
|
||||
animationSpec = snapAnimationSpec,
|
||||
) {
|
||||
state.heightOffset = value
|
||||
}
|
||||
}
|
||||
return Velocity(0f, remainingVelocity)
|
||||
}
|
||||
|
|
@ -0,0 +1,142 @@
|
|||
package com.tangem.core.ui.ds.topbar.collapsing.entity
|
||||
|
||||
import androidx.compose.animation.core.AnimationState
|
||||
import androidx.compose.animation.core.animateTo
|
||||
import androidx.compose.animation.core.tween
|
||||
import androidx.compose.foundation.MutatePriority
|
||||
import androidx.compose.foundation.gestures.ScrollScope
|
||||
import androidx.compose.foundation.gestures.ScrollableState
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.Stable
|
||||
import androidx.compose.runtime.mutableFloatStateOf
|
||||
import androidx.compose.runtime.saveable.Saver
|
||||
import androidx.compose.runtime.saveable.listSaver
|
||||
import androidx.compose.runtime.saveable.rememberSaveable
|
||||
import com.tangem.core.ui.ds.topbar.collapsing.entity.TangemCollapsingAppBarState.Companion.Saver
|
||||
import kotlin.math.absoluteValue
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
|
||||
/**
|
||||
* State of the collapsing top app bar.
|
||||
* It contains the current height offset, the limits for collapsing and expanding, and the scroll direction.
|
||||
*
|
||||
* @property initialHeightOffset The initial height offset of the app bar. Default is 0f.
|
||||
* @property heightOffsetLimit The height offset limit for full collapse.
|
||||
* @property partialHeightLimit The height offset limit for partial collapse. Default is the same as [heightOffsetLimit]
|
||||
*/
|
||||
@Stable
|
||||
class TangemCollapsingAppBarState(
|
||||
val initialHeightOffset: Float = 0f,
|
||||
val heightOffsetLimit: Float = 0f,
|
||||
val partialHeightLimit: Float = heightOffsetLimit,
|
||||
) : ScrollableState {
|
||||
|
||||
private val _heightOffset = mutableFloatStateOf(initialHeightOffset)
|
||||
private var deferredConsumption: Float = 0f
|
||||
|
||||
/**
|
||||
* The current height offset of the app bar.
|
||||
* This value is updated as the user scrolls, and is constrained between [heightOffsetLimit] and 0f.
|
||||
*/
|
||||
var heightOffset: Float
|
||||
get() = _heightOffset.floatValue
|
||||
set(newOffset) {
|
||||
_heightOffset.floatValue =
|
||||
newOffset.coerceIn(minimumValue = heightOffsetLimit, maximumValue = 0f)
|
||||
}
|
||||
|
||||
/**
|
||||
* The fraction of the app bar that is collapsed, calculated as the ratio of [heightOffset] to [heightOffsetLimit].
|
||||
*/
|
||||
val collapsedFraction: Float
|
||||
get() =
|
||||
if (heightOffsetLimit != 0f) {
|
||||
heightOffset / heightOffsetLimit
|
||||
} else {
|
||||
0f
|
||||
}
|
||||
|
||||
/**
|
||||
* The current scroll direction of the app bar, which can be Collapsing, Expanding, or Idle.
|
||||
*/
|
||||
var direction: TopBapScrollDirection = TopBapScrollDirection.Idle
|
||||
|
||||
private val scrollableState = ScrollableState { value ->
|
||||
val consume = if (value < 0) {
|
||||
max(heightOffsetLimit - heightOffset, value)
|
||||
} else {
|
||||
min(0f - heightOffset, value)
|
||||
}
|
||||
|
||||
val current = consume + deferredConsumption
|
||||
val currentInt = current.toInt()
|
||||
|
||||
if (current.absoluteValue > 0) {
|
||||
heightOffset += currentInt
|
||||
deferredConsumption = current - currentInt
|
||||
}
|
||||
|
||||
consume
|
||||
}
|
||||
|
||||
override val isScrollInProgress: Boolean
|
||||
get() = scrollableState.isScrollInProgress
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
suspend fun collapse() {
|
||||
AnimationState(initialValue = heightOffset).animateTo(
|
||||
targetValue = heightOffsetLimit + partialHeightLimit,
|
||||
animationSpec = tween(),
|
||||
) {
|
||||
heightOffset = value
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun scroll(scrollPriority: MutatePriority, block: suspend ScrollScope.() -> Unit) =
|
||||
scrollableState.scroll(scrollPriority, block)
|
||||
|
||||
override fun dispatchRawDelta(delta: Float) = scrollableState.dispatchRawDelta(delta)
|
||||
|
||||
companion object {
|
||||
/** The default [Saver] implementation for [TangemCollapsingAppBarState]. */
|
||||
val Saver: Saver<TangemCollapsingAppBarState, *> =
|
||||
listSaver(
|
||||
save = { state -> listOf(state.heightOffsetLimit, state.heightOffset, state.partialHeightLimit) },
|
||||
restore = { state ->
|
||||
TangemCollapsingAppBarState(
|
||||
heightOffsetLimit = state[0],
|
||||
partialHeightLimit = state[2],
|
||||
initialHeightOffset = state[1],
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remembers and saves the state of the collapsing top app bar across recompositions and configuration changes.
|
||||
*/
|
||||
@Composable
|
||||
fun rememberTangemCollapsingAppBarState(
|
||||
heightOffsetLimit: Float = -Float.MAX_VALUE,
|
||||
partialHeightLimit: Float = -Float.MAX_VALUE,
|
||||
initialHeightOffset: Float = 0f,
|
||||
): TangemCollapsingAppBarState {
|
||||
return rememberSaveable(saver = Saver) {
|
||||
TangemCollapsingAppBarState(
|
||||
initialHeightOffset = initialHeightOffset,
|
||||
partialHeightLimit = partialHeightLimit,
|
||||
heightOffsetLimit = heightOffsetLimit,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The scroll direction of the top app bar, which can be Collapsing, Expanding, or Idle.
|
||||
*/
|
||||
enum class TopBapScrollDirection {
|
||||
Collapsing, Expanding, Idle
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue