Gesture- og spring-animationer
Naturlig, fysikbaseret bevægelse.
Gesture- og spring-animationer er en gratis Android Academy-lektion på CoddyKit. Dette er lektion 4 af 4. Du kan læse alle 3 lektioner i dette læringsspor gratis i deres fulde længde — derefter låser CoddyKit PRO alle lektioner op samt praktiske øvelser med en indbygget kodeeditor og en AI-underviser døgnet rundt. Den er en del af læringsforløbet i Android Academy, og dine fremskridt synkroniseres på tværs af nettet og CoddyKit-appen. Android Academy-kurset indeholder 4 lektioner i alt.
Interaktiv, fysisk bevægelse
De mest tilfredsstillende animationer reagerer på brugerens finger og føles som virkelige objekter med fremdrift og hop. For at bygge dem kombinerer du gestus med fysikbaseret animation.
Denne lektion dækker Animatable, fjedre, kastehenfald og kobling til trækgestus for en naturlig, interaktiv brugergrænseflade.
Animatable: Styring på lavt niveau
Mens animate*AsState reagerer på tilstand, giver Animatable dig imperativ kontrol. Du gemmer en sådan i remember og driver den fra en coroutine med kald som animateTo eller snapTo.
Det er grundlaget for bevægelse styret af gestus.
@Composable
fun BounceOnClick() {
val scale = remember { Animatable(1f) }
val scope = rememberCoroutineScope()
Box(
Modifier
.graphicsLayer { scaleX = scale.value; scaleY = scale.value }
.clickable {
scope.launch {
scale.animateTo(1.3f, spring())
scale.animateTo(1f, spring())
}
}
)
}Fjedre: dampingRatio og stiffness
En spring-specifikation defineres af to værdier:
- dampingRatio – hvor meget den hopper. En lavere værdi giver flere hop;
1f(kritisk dæmpet) overskyder ikke. - stiffness – hvor hurtigt den bevæger sig. En højere værdi når hurtigere frem til målet.
Compose tilbyder konstanter som Spring.DampingRatioMediumBouncy og Spring.StiffnessLow, så du sjældent behøver rå tal.
val spec = spring<Float>(
dampingRatio = Spring.DampingRatioLowBouncy,
stiffness = Spring.StiffnessMedium
)
// later, inside a coroutine:
// offset.animateTo(targetValue = 0f, animationSpec = spec)Registrering af trækbevægelser
For at gøre bevægelse interaktiv læser du berøringsinput. Modifier.pointerInput med detectDragGestures rapporterer trækforskydninger, mens brugeren bevæger fingeren.
Du akkumulerer disse forskydninger i en offset og anvender den på den composable.
@Composable
fun Draggable() {
var offsetX by remember { mutableStateOf(0f) }
Box(
Modifier
.offset { IntOffset(offsetX.roundToInt(), 0) }
.size(80.dp)
.background(Color.Red)
.pointerInput(Unit) {
detectDragGestures { change, drag ->
change.consume()
offsetX += drag.x
}
}
)
}Spring tilbage med en fjeder
Kombinér træk med Animatable for at skabe en effekt, hvor elementet "springer tilbage". Mens du trækker, bruger du snapTo til øjeblikkeligt at sætte elementet ved fingerens position. Når fingeren slippes, bruger du animateTo(0f) med en fjeder, så elementet hopper tilbage på plads.
@Composable
fun SnapBack() {
val offsetX = remember { Animatable(0f) }
val scope = rememberCoroutineScope()
Box(
Modifier
.offset { IntOffset(offsetX.value.roundToInt(), 0) }
.size(80.dp)
.background(Color.Blue)
.pointerInput(Unit) {
detectDragGestures(
onDrag = { change, drag ->
change.consume()
scope.launch { offsetX.snapTo(offsetX.value + drag.x) }
},
onDragEnd = {
scope.launch { offsetX.animateTo(0f, spring()) }
}
)
}
)
}Slyngning med hastighed
Ved en ægte slyngning fortsætter elementet med at bevæge sig, efter fingeren løftes. Spor hastigheden med en VelocityTracker, og giv den derefter til animateDecay, så elementet glider naturligt til standsning ved hjælp af en friktionsbaseret DecayAnimationSpec.
val decay = rememberSplineBasedDecay<Float>()
// on drag end, with measured velocity:
// scope.launch {
// offsetX.animateDecay(
// initialVelocity = velocity,
// animationSpec = decay
// )
// }Swipe for at afvise med ankre
Ved swipebevægelser med faste hvilepositioner, f.eks. swipe for at afvise, springer anchoredDraggable til de definerede ankre. Du erklærer tilstandene og deres positioner i pixels, og Compose håndterer fjederen mellem dem.
enum class DragValue { Start, End }
val state = remember {
AnchoredDraggableState(
initialValue = DragValue.Start,
anchors = DraggableAnchors {
DragValue.Start at 0f
DragValue.End at 300f
}
)
}Uendelige og gentagne animationer
Til kontinuerlig bevægelse, f.eks. en pulserende prik eller en indlæsningsglans, skal du bruge rememberInfiniteTransition sammen med infiniteRepeatable. Angiv RepeatMode som Reverse for at køre frem og tilbage eller som Restart for at gentage fra begyndelsen.
@Composable
fun Pulse() {
val transition = rememberInfiniteTransition(label = "pulse")
val scale by transition.animateFloat(
initialValue = 1f,
targetValue = 1.2f,
animationSpec = infiniteRepeatable(
animation = tween(700),
repeatMode = RepeatMode.Reverse
),
label = "scale"
)
Box(Modifier.graphicsLayer { scaleX = scale; scaleY = scale })
}Kombination af gestus og fjeder
Det klassiske interaktive mønster: træk for at flytte, og slip for at få elementet til at falde på plads. Spor hastigheden under trækket, og brug derefter enten animateDecay til en slyngning eller en spring mod et anker, afhængigt af afstanden eller hastigheden.
Det er præcis sådan, bundpaneler, karruseller og kort, der kan afvises, føles så naturlige.
// pattern:
// 1) onDrag -> animatable.snapTo(current + delta)
// 2) onDragEnd -> if (fast) animatable.animateDecay(velocity, decay)
// else animatable.animateTo(nearestAnchor, spring())Fjederens stabilisering i ren Kotlin
For at mærke, hvordan en fjeder stabiliserer sig, får du her en minimal løkke i ren Kotlin. Den anvender en gendannende kraft mod målet og dæmper hastigheden for hvert trin – det er den samme idé, som Compose kører for hver frame.
fun main() {
var pos = 0f
var vel = 0f
val target = 200f
val stiffness = 0.2f
val damping = 0.75f
repeat(8) { step ->
vel = (vel + (target - pos) * stiffness) * damping
pos += vel
println("step $step pos=${"%.1f".format(pos)}")
}
}Tryk, hold, og brug flere gestus
Træk er ikke den eneste gestus. pointerInput tilbyder også detectTapGestures til tryk, dobbelttryk og lange tryk samt detectTransformGestures til knib for at zoome og rotation.
Her udløser et langt tryk en fjederbaseret skalering, hvor registrering af gestus kombineres med en Animatable.
@Composable
fun LongPressScale() {
val scale = remember { Animatable(1f) }
val scope = rememberCoroutineScope()
Box(
Modifier
.graphicsLayer { scaleX = scale.value; scaleY = scale.value }
.pointerInput(Unit) {
detectTapGestures(
onLongPress = {
scope.launch { scale.animateTo(1.4f, spring()) }
},
onPress = {
tryAwaitRelease()
scope.launch { scale.animateTo(1f, spring()) }
}
)
}
)
}Hurtig kontrol
Du bygger et kort, der kan trækkes, og som skal hoppe tilbage til sin oprindelige position, når det slippes. Hvilken kombination er det idiomatiske valg i Compose?
Opsummering: gestus og fjedre
Du kan nu bygge naturlig, interaktiv bevægelse:
Animatablegiver imperativ, coroutine-drevet kontrol viaanimateTo/snapTo.springjusteres meddampingRatio(hop) ogstiffness(hastighed).pointerInput+detectDragGesturesomdanner berøring til bevægelse;animateDecaytilføjer slyngning.anchoredDraggablespringer til faste positioner ved swipeinteraktioner.rememberInfiniteTransitiondriver gentagne effekter som pulser og glanseffekter.
Det afslutter animationer i Jetpack Compose. Du kan nu animere værdier, synlighed, indhold og gestus med sikkerhed.
Lær Kotlin med en AI-underviser — gratis
Skriv og kør rigtig kode i din browser, få øjeblikkelig hjælp fra en AI-underviser døgnet rundt, og fortsæt, hvor du slap, på web eller i appen.
- Kurser
- 36
- Lektioner
- 152
Ofte stillede spørgsmål
Er lektionen “Gesture- og spring-animationer” gratis?
Ja — alle 3 lektioner i læringssporet Android Academy, inklusive “Gesture- og spring-animationer”, kan læses gratis i deres fulde længde her på webstedet. Derefter låser CoddyKit PRO alle lektioner op samt interaktive øvelser med en indbygget kodeeditor og en AI-underviser døgnet rundt. Android Academy-kurset indeholder 4 lektioner i alt.
Hvad lærer jeg i “Gesture- og spring-animationer”?
Naturlig, fysikbaseret bevægelse. Du øver dig i Android Academy med praktisk kode, som du kører direkte i browseren, og en AI-vejleder døgnet rundt besvarer dine spørgsmål, mens du arbejder dig gennem lektionen.
Skal jeg have erfaring for at begynde på Android Academy?
Der kræves ingen tidligere erfaring. Android Academy på CoddyKit er tilrettelagt for både begyndere og øvede, så du kan starte her eller fra begyndelsen og lære i dit eget tempo. Dette er lektion 4 af 4.
Hvor lang tid tager lektionen “Gesture- og spring-animationer”?
De fleste CoddyKit-lektioner tager cirka 5–10 minutter. Hver lektion er kort og interaktiv, så du gør løbende fremskridt og kan fortsætte, hvor du slap – på både web og app.
Kan jeg skrive og køre kode i denne Android Academy-lektion?
Ja. Alle Android Academy-lektioner har en indbygget kodeeditor, så du kan skrive og køre rigtig kode direkte i din browser og få øjeblikkelig feedback fra AI – uden lokal opsætning.
Alle lektioner i dette kursus
- Hvorfor animationer er vigtige
- Grundlæggende animate*AsState
- AnimatedVisibility og transitions
- Gesture- og spring-animationer