Flutter’da Animasyonlar: Fizik Tabanlı Animasyonlar

Mirkan
Flutter İzmir
Published in
3 min readFeb 4, 2020

--

Photo by jcomp

Yerçekimi Animasyonu

Gravity Animation Dart Pad

Bu örnek aslında serinin bir önceki yazısındaki AnimatedPositioned örneğimize benziyor. Stack ve Positioned widget’ları var ve cisimlerin Stack içindeki konumunu değiştiriyoruz. Bunun için de Positioned widget’ının top parametresine animasyonun değerini veriyoruz.

Yukarıdan aşağıya düşen 2 kare için 2 farklı AnimationController ve 2 farklı GravitySimulation var. Yerçekimi simülasyonu yaratırken ivme(acceleration), başlangıç ve bitiş noktaları(starting point, end point) ve başlangıç hızı(starting velocity)’na ihtiyacımız var. 4 değer de double cinsinde. AnimationController sonrasında bu simülasyonu kullanarak yerçekimi animasyonunu sağlayacak. Örnekte verdiğim iki GravitySimulation arasında sadece acceleration farklı, yani ivmelenmeleri farklı olacak ve ivmesi büyük olan daha hızlı düşecek. AnimationController’a upperBound parametresi ile üst sınır belirtiyorum. Arayüzün de güncellenmesi için bir listener ekliyorum ve her değişiklik ile setState’i çağırıyorum. Kodun geri kalanı ise bildiğimiz Stack widget’ı. Stack widget’ının içinde Positioned widgetlarının içine koyduğum Container widgetları mevcut. Kolaylık olması için bu Container widgetlarına bu bağlamda cisimlerimiz diyelim.

Tekrar edersek, olay bu cisimlerin Stack widget’ındaki konumunu değiştirmekten ibaret, bunun için de Positioned widget’ların top parametresi animasyonun o andaki değerine eşit. Böylece AnimationController, verdiğimiz yerçekimi simülasyonu ile 0.0'dan 500.0'a değerler üretirken, bu değer bu cisimlerin Stack içinde yukarıdan kaç piksel aşağıda olduğunu belirliyor .(top = firstController.value)

class GravityAnimationExample extends StatefulWidget {
@override
_GravityAnimationExampleState createState() =>
_GravityAnimationExampleState();
}
class _GravityAnimationExampleState extends State<GravityAnimationExample>
with TickerProviderStateMixin {
AnimationController firstController;
AnimationController secondController;
GravitySimulation firstSimulation;
GravitySimulation secondSimulation;@override
void initState() {
super.initState();
firstSimulation = GravitySimulation(
100.0, // acceleration
0.0, // starting point
500.0, // end point
0.0, // starting velocity
);
secondSimulation = GravitySimulation(
200.0, // acceleration
0.0, // starting point
500.0, // end point
0.0, // starting velocity
);
firstController = AnimationController(vsync: this, upperBound: 500)
..addListener(() {
setState(() {});
});
secondController = AnimationController(vsync: this, upperBound: 500)
..addListener(() {
setState(() {});
});
firstController.animateWith(firstSimulation);
secondController.animateWith(secondSimulation);
}
@override
Widget build(BuildContext context) {
return Stack(
children: <Widget>[
Positioned(
left: 50,
top: firstController.value,
height: 50,
width: 50,
child: Container(
color: Colors.orange,
),
),
Positioned(
right: 50,
top: secondController.value,
height: 50,
width: 50,
child: Container(
color: Colors.green,
),
),
Align(
alignment: Alignment.center,
child: FloatingActionButton(
child: Icon(Icons.play_arrow),
onPressed: () {
firstController.animateWith(firstSimulation);
secondController.animateWith(secondSimulation);
},
),
)
],

);
}
@override
void dispose() {
firstController.dispose();
secondController.dispose();
super.dispose();
}
}

Yaylanma Animasyonu

Spring Animation Dart Pad

Yerçekimi örneğinin aynısı, bir simülasyon yaratıp AnimationController’a veriyoruz(animateWith methodu). Sonrasında AnimationController’ın ürettiği değerleri Positioned widget’ın top parametresine verip, renkli karelerin(Container widget’ı) dikeydeki konumlarını değiştirmiş oluyoruz.

SpringSimulation için SpringDescription’a ihtiyacımız var. SpringDescription’a kütle(mass), sertlik(stiffness) ve sönümleme(damping) veriyoruz(Bu değerleri ve ilişkileri için bir fizik kitabına başvurabilirsiniz, benim de iddialı olduğum bir alan değil).
Sonrasında bu SpringDescription ve başlangıç, bitiş ve ivme değerleri ile SpringSimulation yaratıyoruz.

class SpringAnimationExample extends StatefulWidget {
@override
_SpringAnimationExampleState createState() => _SpringAnimationExampleState();
}

class _SpringAnimationExampleState extends State<SpringAnimationExample>
with TickerProviderStateMixin {
AnimationController _firstController;
SpringSimulation _firstSimulation;​
var _firstSpring;

AnimationController _secondController;
SpringSimulation _secondSimulation;
var _secondSpring;
@override
void initState() {
_firstSpring = SpringDescription(mass: 1, stiffness: 300, damping: 1);
_firstSimulation = SpringSimulation(_firstSpring, 0, 200, 10);
_firstController = AnimationController(
vsync: this,
upperBound: 500,
)..addListener(() {
setState(() {});
});

_firstController.animateWith(_firstSimulation);

_secondSpring = SpringDescription(mass: 1, stiffness: 100, damping: 1);
_secondSimulation = SpringSimulation(_secondSpring, 0, 200, 10);
_secondController = AnimationController(
vsync: this,
upperBound: 500,
)..addListener(() {
setState(() {});
});

_secondController.animateWith(_secondSimulation);
super.initState();
}

@override
Widget build(BuildContext context) {
return Stack(
children: <Widget>[
Positioned(
left: 50,
top: _firstController.value,
height: 50,
width: 50,
child: Container(
color: Colors.deepPurpleAccent,
),
),
Positioned(
right: 50,
top: _secondController.value,
height: 50,
width: 50,
child: Container(
color: Colors.blue[900],
),
),
Align(
alignment: Alignment.center,
child: FloatingActionButton(
child: Icon(Icons.play_arrow),
onPressed: () {
_firstController.animateWith(_firstSimulation);
_secondController.animateWith(_secondSimulation);
},
),
)
],
);
}

@override
void dispose() {
_firstController.dispose();
_secondController.dispose();
super.dispose();
}
}

Sorularınızı Twitter @mirkancal ve LinkedIn üzerinden yazabilirsiniz, sağlıcakla kalın.

Diğer yazılarıma da göz atabilirsiniz.
Flutter’da Animasyonlar: Implicit Animation Widgets
Flutter’da Temiz Routing
Flutter Web uygulamasını Peanut ile Github Pages’e Dağıtma
Flutter Uygulama Mimarisi: BLoC
Flutter’da SVG Kullanımı
Flutter’da Pusher Kullanımı

--

--