Flutter 101: membuat splashscreen sederhana


Setelah mengatur agar komputer kamu sudah bisa bermain flutter dan membaca beberapa tutorialnya, saatnya mulai ngoding. Di tulisan kali ini mari belajar membuat aplikasi yang menampilkan splashscreen.

Kenapa bukan hello world? Karena defaultnya, saat kita membuat proyek flutter, otomatis akan dibuatkan semacam template aplikasi counter. Jadi kalau sekadar hello world mah lewat :D. Sebelum lupa, disclaimer dulu, tidak semua kode yang ditulis di sini murni hasil pemikiran saya. Kebanyakan hasil googling, dan beberapa sumber lupa disimpan :D.

Oh iya di tulisan ini saya memakai Idea dari Jetbrains sebagai IDE. Sebenarnya untuk ngoding flutter kita bisa menggunakan IDE ‘ringan’ seperti Visual Studio Code ataupun langsung di Android Studio. Tapi entah kenapa saya lebih senang ngoding di Idea. Mungkin karena pakai versi ultimate yang lisensinya memanfaatkan email kampus :D).

Untuk langkah awal pembuatan proyek mungkin bisa dilewat ya. Diasumsikan kita sudah membuat proyek, namanya splashscreen dan sudah ada berkas main.dart. Di berkas main.dart sudah dibuatkan kelas MyHomePage beserta kelas state-nya. Silakan kalau mau dihapus dan menyisakan kelas MyApp saja, Kalau saya sih biasanya tidak dihapus.

Sekarang mari membuat berkas baru, namanya splashsatu.dart, lalu buat kelas SplashSatu yang extend ke StatefulWidget.

class SplashSatu extends StatefulWidget {

  @override
  State<StatefulWidget> createState() => _SplashState();
}

Di atas bisa dilihat kita akan menimpa fungsi createState() oleh _SplashState() yang belum kita bikin. Mari bikin kerangkanya dulu.

class _SplashState extends State<SplashSatu> with TickerProviderStateMixin {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: new Center(
        child: new Text('anu');
      ),
    );
  }
}

Kalau kita build sekarang, niscaya di ponsel atau emulator tidak akan muncul kata anu. Kenapa? Karena kita belum memanggil kelas SplashSatu di main.dart. Karena itu mari ubah di kelas MyApp:

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Flutter Demo',
      theme: new ThemeData(
      home: new SplashSatu(), //yang ini yang diubah
    );
  }
}

Silakan build ulang (kalau hot reload tidak ada pengaruh), niscaya harusnya sekarang ada perubahan. Kalau sudah berubah, selamat, langkah pertama membuat kelas baru berhasil. Mari lanjut.

Di splashscreen pertama ini (rencananya mau dibuat tiga macam), saya ingin menampilkan tulisan countdown sebanyak x detik, dan setelah hitungan mundur mencapai 0 akan dilempar ke kelas lain. Karena itulah kita membutuhkan kelas TickerProviderStateMixin karena nanti akan berhubungan dengan animasi.

Di kelas _SplashState buat variabel controller animasi dan waktu mundur, lalu kita timpa fungsi initState() yang pertama dieksekusi dengan mendefinisikan controller tersebut. Setelah didefinisikan, jalankan animasinya (bisa forward, reverse, atau stop kalau ingin berhenti).

AnimationController controller;
static const int seconds = 15;

@override
void initState() {
// TODO: implement initState
super.initState();
controller = new AnimationController(
  vsync: this,
  duration: new Duration(seconds: seconds),
);

controller.forward();

}

Untuk menampilkan hitungan mundurnya, kita buat kelas Countdown yang meng-extend dari kelas AnimatedWidget. Nantinya widget hasil kelas ini akan dipasang di body punya _SplashState. Ini bukan kodingan saya, jadi saya juga tak begitu paham :D.

class Countdown extends AnimatedWidget {
  Countdown({ Key key, this.animation }) : super(key: key, listenable: animation);
  Animation<int> animation;

  @override
  build(BuildContext context){
    count = animation.value.toInt();
    print("count: $count");
    return new Text(
      count.toString(),
      style: new TextStyle(fontSize: 24.0),
    );
  }
}

Setelah itu, mari buat widget berdasarkan kelas tersebut di _SplashState. Ganti child: new Text('anu') dengan Container ini:

...
child: new Container(
  padding: EdgeInsets.all(16.0),
  child: new Column(
    mainAxisAlignment: MainAxisAlignment.center,
    crossAxisAlignment: CrossAxisAlignment.center,
    children: <Widget>[
      new Text("Countdown: ", style: TextStyle(fontSize: 30.0),),
      new Countdown(
        animation: new StepTween(
          begin: seconds,
          end: 0,
        ).animate(controller),
      )
    ],
  ),
),
...

Kalau kita jalankan aplikasinya, maka akan muncul hitungan mundur dari 15 sampai 0 setelah itu berhenti. Agar perilakunya seperti splashscreen aslinya, kita buat dulu berkas baru namanya utama.dart. Anggap saja berkas ini sebagai menu utama aplikasi kita yang akan kena lemparan dari splashsatu.dart.

import 'package:flutter/material.dart';

class Utama extends StatelessWidget{
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: new Center(
        child: new Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            const Text("Ini menu utama")
          ],
        ),
      ),
    );
  }
}

Kembali ke splashsatu.dart. Masih di _SplashState, buat fungsi baru, yang tugasnya melempar ‘activity’ splashscreen (entah di flutter namanya apa) ke menu utama, lalu panggil di initState().

  gotoUtama() async {
    var _duration = new Duration(seconds: seconds);
    return new Timer(_duration, changePage);
  }

  void changePage(){
    Navigator.push(context, MaterialPageRoute(builder: (context)=> _utamaPage.Utama()));
  }

Fungsi gotoUtama seharusnya bukan begitu, ini cuma akal-akalan saja menunggu selama seconds detik, di mana kalau sudah terpenuhi, Timer akan memanggil fungsi sebenarnya, changePage() yang bertugas memindahkan halaman.

Sebenarnya ada cara lain, misalnya men-trigger setState() agar nantinya si changePage() dieksekusi. Tapi ya namanya juga belajar :D. Jadi, kelas _SplashState lengkapnya seperti ini:

class _SplashState extends State<SplashSatu> with TickerProviderStateMixin {
  AnimationController controller;
  static const int seconds = 15;
  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    controller = new AnimationController(
      vsync: this,
      duration: new Duration(seconds: seconds),
    );

    controller.forward();
    gotoUtama();

  }

  gotoUtama() async {
    var _duration = new Duration(seconds: seconds);
    return new Timer(_duration, changePage);
  }

  void changePage(){
    Navigator.push(context, MaterialPageRoute(builder: (context)=> _utamaPage.Utama()));
  }

  @override
  Widget build(BuildContext context) {

    return Scaffold(
      body: new Center(
        child: new Container(
          padding: EdgeInsets.all(16.0),
          child: new Column(
            mainAxisAlignment: MainAxisAlignment.center,
            crossAxisAlignment: CrossAxisAlignment.center,
            children: <Widget>[
              new Text("Countdown: ", style: TextStyle(fontSize: 30.0),),
              new Countdown(
                animation: new StepTween(
                  begin: seconds,
                  end: 0,
                ).animate(controller),
              )
            ],
          ),
        ),
      ),
    );

  }

  @override
  void dispose() {
    // TODO: implement dispose
    controller.dispose();
    super.dispose();

  }
}

Kalau dijalankan, seharusnya sekarang muncul hitungan mundur sebanyak 15 detik, lalu setelah habis akan dilempar ke menu utama.

Ya sudah, untuk sementara sekian dulu. Nanti kalau sempat kita lanjut ke bagian kedua. Semoga bukan awal wacana.


One response to “Flutter 101: membuat splashscreen sederhana”

Ada komentar?

This site uses Akismet to reduce spam. Learn how your comment data is processed.