Gest- och fjäderanimationer
Naturlig, fysikbaserad rörelse.
Gest- och fjäderanimationer är en gratis lektion i Android Academy på CoddyKit. Detta är lektion 4 av 4. Du kan läsa vilka 3 lektioner som helst i den här lärvägen kostnadsfritt i sin helhet – därefter låser CoddyKit PRO upp alla lektioner, plus praktisk övning med en inbyggd kodredigerare och en AI-lärare dygnet runt. Den ingår i lärvägen för Android Academy, och Era framsteg synkroniseras mellan webben och CoddyKit-appen. Kursen i Android Academy innehåller totalt 4 lektioner.
Interaktiv, fysisk rörelse
De mest tillfredsställande animationerna reagerar på användarens finger och känns som riktiga objekt, med rörelsemängd och studs. För att bygga sådana kombinerar ni gester med fysikbaserad animation.
Den här lektionen behandlar Animatable, fjädrar, fling-avklingning och hur de kopplas till draggester för ett naturligt och interaktivt användargränssnitt.
Animatable: kontroll på låg nivå
Medan animate*AsState reagerar på tillstånd ger Animatable er imperativ kontroll. Ni sparar ett sådant objekt i remember och styr det från en coroutine med anrop som animateTo eller snapTo.
Detta är grunden för geststyrd rörelse.
@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())
}
}
)
}Fjädrar: dampingRatio och stiffness
En spring-specifikation definieras av två värden:
- dampingRatio – hur studsande den är. Lägre värden ger mer studs;
1f(kritiskt dämpad) överskjuter inte målet. - stiffness – hur snabb den är. Högre värden når målet snabbare.
Compose tillhandahåller konstanter som Spring.DampingRatioMediumBouncy och Spring.StiffnessLow, så ni behöver sällan använda råa tal.
val spec = spring<Float>(
dampingRatio = Spring.DampingRatioLowBouncy,
stiffness = Spring.StiffnessMedium
)
// later, inside a coroutine:
// offset.animateTo(targetValue = 0f, animationSpec = spec)Identifiera dragningar
För att göra rörelser interaktiva läser du av beröringsinmatning. Modifier.pointerInput med detectDragGestures rapporterar förflyttningen när användaren rör fingret.
Du ackumulerar förflyttningarna i en offset och tillämpar den på composable-funktionen.
@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
}
}
)
}Fjädrande återgång
Kombinera dragning med Animatable för en effekt där elementet "snäpper tillbaka". Under dragningen använder du snapTo för att omedelbart flytta elementet till fingrets position. När fingret släpps använder du animateTo(0f) med en fjäder, så att elementet studsar tillbaka till sin ursprungliga position.
@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()) }
}
)
}
)
}Slunga med hastighet
En riktig slungning fortsätter efter att fingret lyfts. Spåra hastigheten med en VelocityTracker och skicka den sedan till animateDecay, så att elementet glider till ett naturligt stopp med hjälp av en friktionsbaserad DecayAnimationSpec.
val decay = rememberSplineBasedDecay<Float>()
// on drag end, with measured velocity:
// scope.launch {
// offsetX.animateDecay(
// initialVelocity = velocity,
// animationSpec = decay
// )
// }Svep för att stänga med ankare
För svepgester med fasta vilopositioner, som svep för att stänga, snäpper anchoredDraggable till definierade ankare. Du deklarerar tillstånd och deras positioner i pixlar, så hanterar Compose fjäderrörelsen mellan dem.
enum class DragValue { Start, End }
val state = remember {
AnchoredDraggableState(
initialValue = DragValue.Start,
anchors = DraggableAnchors {
DragValue.Start at 0f
DragValue.End at 300f
}
)
}Oändliga och upprepade animationer
För kontinuerliga rörelser, som en pulserande punkt eller en laddningsanimation, använder du rememberInfiniteTransition med infiniteRepeatable. Ange RepeatMode som Reverse för att växla fram och tillbaka, eller Restart för att börja om från början i varje loop.
@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 })
}Kombinera gest och fjäder
Det typiska interaktiva mönstret är att dra för att flytta och släppa för att låta elementet lägga sig på plats. Spåra hastigheten under dragningen och använd sedan antingen animateDecay för att slunga elementet eller en spring för att lägga det mot ett ankare, beroende på avstånd eller hastighet.
Det är precis så här bottom sheets, karuseller och kort som kan stängas får sin naturliga känsla.
// pattern:
// 1) onDrag -> animatable.snapTo(current + delta)
// 2) onDragEnd -> if (fast) animatable.animateDecay(velocity, decay)
// else animatable.animateTo(nearestAnchor, spring())Fjädrande positionering i ren Kotlin
För att känna hur en fjäder lägger sig på plats finns här en minimal loop i ren Kotlin. Den tillämpar en återställande kraft mot målet och dämpar hastigheten vid varje steg, enligt samma princip som Compose använder för varje bildruta.
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)}")
}
}Tryck, håll ned och flera gester
Dragning är inte den enda gesten. pointerInput erbjuder även detectTapGestures för tryck, dubbeltryck och långtryck, samt detectTransformGestures för nypzoomning och rotation.
Här utlöser ett långtryck en fjädrande skalning, där gestidentifiering kombineras 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()) }
}
)
}
)
}Snabbtest
Du bygger ett dragbart kort som ska studsa tillbaka till sin ursprungliga position när det släpps. Vilken kombination är det idiomatiska valet i Compose?
Sammanfattning: gester och fjädrar
Nu kan du skapa naturliga, interaktiva rörelser:
Animatableger imperativ, koroutinstyrd kontroll viaanimateTo/snapTo.springjusteras meddampingRatio(studsighet) ochstiffness(hastighet).pointerInput+detectDragGesturesomvandlar beröring till rörelse;animateDecaylägger till slungning.anchoredDraggablesnäpper till fasta positioner för svepinteraktioner.rememberInfiniteTransitiondriver loopande effekter som pulseringar och skimrande laddningsanimationer.
Det avslutar avsnittet om animationer i Jetpack Compose. Nu kan du med säkerhet animera värden, synlighet, innehåll och gester.
Lär dig Kotlin med en AI-lärare – gratis
Skriv och kör riktig kod i webbläsaren, få omedelbar hjälp av en AI-lärare dygnet runt och fortsätt där du slutade – på webben eller i appen.
- Kurser
- 36
- Lektioner
- 152
Vanliga frågor
Är lektionen ”Gest- och fjäderanimationer” gratis?
Ja – du kan läsa vilka 3 lektioner som helst i lärvägen Android Academy, inklusive ”Gest- och fjäderanimationer”, kostnadsfritt i sin helhet här på webben. Därefter låser CoddyKit PRO upp alla lektioner, plus interaktiv övning med en inbyggd kodredigerare och en AI-lärare dygnet runt. Kursen i Android Academy innehåller totalt 4 lektioner.
Vad lär jag mig i ”Gest- och fjäderanimationer”?
Naturlig, fysikbaserad rörelse. Ni övar på Android Academy med praktisk kod som körs direkt i webbläsaren, medan en AI-handledare som är tillgänglig dygnet runt svarar på Era frågor under lektionen.
Behöver jag någon erfarenhet för att börja lära mig Android Academy?
Du behöver inga förkunskaper. Utbildningen i Android Academy på CoddyKit är upplagd för allt från nybörjare till avancerade elever, så att du kan börja här eller från början och gå fram i din egen takt. Detta är lektion 4 av 4.
Hur lång tid tar lektionen ”Gest- och fjäderanimationer”?
De flesta CoddyKit-lektioner tar cirka 5–10 minuter. Varje lektion är kort och interaktiv, så att du gör stadiga framsteg och kan fortsätta precis där du slutade – på webben eller i appen.
Kan jag skriva och köra kod i den här Android Academy-lektionen?
Ja. Varje Android Academy-lektion innehåller en inbyggd kodredigerare, så att du kan skriva och köra riktig kod direkt i webbläsaren och få omedelbar AI-feedback – utan lokal installation.
Alla lektioner i den här kursen
- Varför animationer spelar roll
- Grunderna i animate*AsState
- AnimatedVisibility och övergångar
- Gest- och fjäderanimationer