Mengenal Widget Flutter #8: Membuat Carousel Slide Show Dengan List View & Page View

Mengenal Widget Flutter #8: Membuat Carousel Slide Show Dengan List View & Page View

Pendahuluan

Carousel atau sebuah Slide Show memang menarik selalu menarik apabila terdapat pada sebuah layout, karena selain fungsinya minimalis tapi bisa menyampaikan banyak informasi karena adanya objek yang saling bergantian untuk ditampilkan. Fitur ini biasanya banyak digunakan untuk menampilkan informasi penting ataupun promosi agar segera dilihat oleh pengguna aplikasi.

Berbeda halnya jika anda adalah seorang web developer, maka tidak asing lagi dengan carousel milik Bootstrap dimana class-nya bisa langsung digunakan tanpa perlu membuatnya secara manual. Flutter sendiri memiliki banyak package atau library untuk mewujudkan hal tersebut, akan tetapi pada artikel kali ini kita akan belajar membuat Carouse Slide Show dengan List View dan Page View secara manual.

Adapun hasil yang akan dicapai akan terlihat seperti video berikut.

Baca Juga: Mengenal Widget Flutter #7: Membuat UI Profile Instagram

Install Flutter & Kerangka Dasar Layout

Sebelum memulai mengerjakan project yang diinginkan, maka install Flutter terlebih dahulu dengan command.

flutter create dw_carousel

Buka file Flutter yang baru saja di-install, kemudian modifikasi file lib/main.dart menjadi

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Home(),
    );
  }
}


class Home extends StatefulWidget {
  @override
  _HomeState createState() => _HomeState();
}

class _HomeState extends State<Home> {
  
  //KOMENTAR-INISIASI-VARIABLE
  
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: Column(
          children: <Widget>[
            Flexible(
              flex: 1,
              child: Container(
                margin: const EdgeInsets.all(20),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: <Widget>[
                    //KOMENTAR-1 PROFILE AREA
                    //KOMENTAR-2 DESCRIPTION
                    //KOMENTAR-3 LISTVIEW CAROUSEL
                    //KOMENTAR-4 INFORMATION
                  ],
                ),
              ),
            ),
            Flexible(
              flex: 1,
              child: Container(
                color: Colors.white,
                child: Column(
                  children: <Widget>[
                    //KOMENTAR-5 ACTUALLY CATEGORY TAB
                    Divider(),
                    //KOMENTAR-6 CAROUSEL PAGE VIEW
                  ],
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }

  //KOMENTAR-PARTIAL-WIDGET
}

Note: Kode di atas sudah dilengkapi dengan komentar sebagai penanda untuk kemudian nantinya akan di-replace dengan code lainnya sesuai dengan fungsinya masing-masing. Jadi apabila selama penulisan selanjutnya disebutkan kode komentar di atas, maka replace dengan code yang baru.

Adapun penjelasan mengenai Flexible, Container dan lain sebagainya bisa ditemukan pada artikel seri Mengenal widget flutter sebelumnya.

Bagian pertama yang akan kita selesaikan adalah KOMENTAR-1 untuk profile area, tambahkan code berikut untuk menampilkan profile yang terdiri dari gambar, nama, company/organisasi, dan tombol menu pada pojok paling kanan.

//KOMENTAR-1
profileArea(),

Kok code-nya cuman sebaris? Yap, karena selengkapnya kita pisahkan ke dalam fungsi tersediri agar lebih memudahkan untuk mengelolanya. Tambahkan block code di bawah ini pada area KOMENTAR-PARTIAL-WIDGET.

profileArea() {
  //KITA MENGGUNAKAN ROW KARENA TERDIRI DARI 3 BAGIAN SECARA HORIZONTAL
  //GAMBAR - NAME/COMPANY - MENU
  return Row(
    children: <Widget>[
      //GAMBAR UNTUK PROFILENYA KITA SET SEBUAH CONTAINER DENGAN UKURAN 50
      Container(
        width: 50,
        height: 50,
        margin: EdgeInsets.only(right: 10),
        //DAN GAMBARNYA DIBUNGKUS DGN CLIPRRECT
        child: ClipRRect(
          //DENGAN BORDER RADIUS SETENGAH DARI UKURAN CONTAINER AGAR MEMBENTUK LINGKARAN
          borderRadius: BorderRadius.circular(25),
          //GAMBARNYA DI-LOAD DARI INTERNET, DALAM HAL INI LOGO DAENGWEB
          child: Image.network(
            'https://daengweb.id/front/d-blog/img/favicon.png',
            fit: BoxFit.cover, //AGAR MEMENUHI SELURUH AREA CONTAINER
          ),
        ),
      ),
      //PADA BAGIAN KEDUA BERISI NAMA DAN COMPANY/ORGANIZATION
      //KARENA BERTUMPUK SECARA VERTICAL, MAKA KITA MASUKKAN KEDALAM COLUMN
      Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: <Widget>[
          Text(
            'Anugrah Sandi',
            style: TextStyle(fontWeight: FontWeight.bold, fontSize: 16),
          ),
          Text('Daengweb.id')
        ],
      ),
      //DIANTAR ICON DAN IMAGE/NAME KITA GUNAKAN SPACE DGN FLEX 2 AGAR MENU ICON TERSEBUT BERADA PADA POSISI PALING KANAN
      Spacer(
        flex: 2,
      ),
      Icon(
        Icons.menu,
        size: 50,
      )
    ],
  );
}

Kemudian bagian lainnya adalah deskripsi dari profile user, replace KOMENTAR-2 dengan baris code berikut.

//KOMENTAR-2
Padding(
  padding: const EdgeInsets.only(top: 15.0),
  child: Text(
    'Discover',
    style: TextStyle(
      fontSize: 20,
      fontWeight: FontWeight.bold,
    ),
  ),
),
Text(
  'Live with no excuses and travel with no regrets, Oscar Wild',
  style: TextStyle(
    fontSize: 15,
    fontStyle: FontStyle.italic,
  ),
),

Note: Tidak ada yang perlu dijelaskan karena hanya sebuah teks.

Membuat Carousel Dengan List View

Cara paling mudah membuat carousel adalah dengan menggunakan widget yang sudah pernah dikelakan sebelumnya, yakni List View. Widget ini memiliki sebuah attribute untuk menentukan arah scroll-nya baik secara vertical maupun horizontal. Adapun bagian yang akan dikerjakan dengan menggunakan List View ini adalah carousel untuk favorite places.

Replace code untuk KOMENTAR-3 dengan block code di bawah ini

//KOMENTAR-3

//HANYA SEBUAH TEKS UNTUK LABEL
Padding(
  padding: EdgeInsets.only(top: 10, bottom: 10),
  child: Text(
    'Favorite Places',
    style: TextStyle(
        fontWeight: FontWeight.bold, fontSize: 20),
  ),
),
Container(
  //KETIKA MENGGUNAKAN LIST VIEW DI DALAM COLUMN, MAKA WRAP DIA DENGAN EXPANDED UNTUK MENGHINDARI ERROR
  child: Expanded(
    //KITA MENGGUNAKAN SEPARATED UNTUK MEMBUAT SEPARATOR ANTAR CAROUSEL
    child: ListView.separated(
      physics: PageScrollPhysics(),
      //ADAPUN SEPARATORNYA MENGGUNAKAN DIVIDER DENGAN INDENT 3
      //INDENT AKAN MEMBUAT JARAK SESUAI VALUE YANG DIMILIKINYA
      separatorBuilder: (context, index) => Divider(
        indent: 3,
      ),
      scrollDirection: Axis.horizontal, //ATUR ARAH SCROLLNYA SECARA HORIZONTAL
      itemCount: _favoriteImage.length, //ADAPUN JUMLAH ITEMNYA TERGANTUNG BERAPA BANYAK DATA YANG ADA DI VARIABLE _favoriteImage
      //BUILDERNYA AKAN MEMUAT SEBUAH FUNGSI BARU YANG BERISI WIDGET UNTUK MENAMPILKAN CONTENT
      itemBuilder: (context, index) => favoritePlace(index),
    ),
  ),
),

Note: Content-nya dipisahkan pada fungsi baru agar tidak menumpuk di dalam satu block code.

Tambahkan code berikut setelah fungsi profileArea()

favoritePlace(index) {
  //PER-CONTENT SLIDENYA KITA TENTUKAN UKURANNYA DENGAN SIZEDBOX
  return SizedBox(
    height: 80, //DIMANA TINGGINYA 80
    width: 250, //DAN LEBARNYA 250
    child: Container(
      //KEMUDIAN SET MARGIN DAN PADDINGNYA AGAR TIDAK MERAPAT PADA OBJEK LAINNYA
      margin: EdgeInsets.only(right: 10),
      padding: EdgeInsets.only(left: 10, top: 10, bottom: 10),
      //KEMUDIAN CONTAINER INI KITA BUAT GARIS BORDER DISEKELILINGNYA
      decoration: BoxDecoration(
          //DENGAN KETEBALAN 0.3 DAN WARNA GREY
          border: Border.all(width: 0.3, color: Colors.grey),
          //DAN KEEMPAT SISINYA DIBUAT MELENGKUNG
          borderRadius: BorderRadius.circular(10)),
      //ADAPUN CONTENTNYA TERDIRI DARI 2 BAGIAN, YAKNI GAMBAR DAN INFORMASI
      child: Row(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: <Widget>[
          //BAGIAN GAMBARNYA SEPERTI BIASA MENGGUNAKAN CONTAINER DENGAN IMAGE YANG MENUTUPINYA
          Container(
            height: 60,
            width: 60,
            decoration: BoxDecoration(
              borderRadius: BorderRadius.circular(10),
              image: DecorationImage(
                //IMAGENYA KITA AMBIL DARI VARIABLE _FAVORITEIMAGE DENGAN INDEX SESUAI DENGAN LOOPING DARI LIST VIEW
                image: AssetImage(
                  _favoriteImage[index]['image'],
                ),
                //SET BAGIAN INI AKAN IMAGE MENUTUPI SEPENUHNYA
                fit: BoxFit.cover,
              ),
            ),
          ),
          //BAGIAN KEDUA ADALAH INFORMASI YANG TERDIRI DARI 3 BAGIAN
          //NAMA TEMPAT, CATEGORY DAN JAM KERJA
          Padding(
            padding: const EdgeInsets.only(left: 8),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: <Widget>[
                Text(
                  _favoriteImage[index]['name'],
                  style: TextStyle(fontWeight: FontWeight.bold),
                ),
                Text(
                  _favoriteImage[index]['cat'],
                  style: TextStyle(fontSize: 12, color: Colors.grey),
                ),
                Text(
                  _favoriteImage[index]['open'],
                  style: TextStyle(fontSize: 12, color: Colors.grey),
                ),
              ],
            ),
          )
        ],
      ),
    ),
  );
}

Terus variable untuk data image-nya bagaimana? Masih ingat dengan code KOMENTAR-INISIASI-VARIABLE? Masukkan code berikut ini di dalamnya

final _favoriteImage = {
{
  'name': 'Bantimurung',
  'image': 'images/bantimurung.jpg',
  'cat': 'Air Terjun',
  'open': '09.00-17.00 WITA'
},
{
  'name': 'Pantai Bira',
  'image': 'images/bira.jpg',
  'cat': 'Wisata Bahari',
  'open': '06.00-21.00 WITA'
},
{
  'name': 'Malino',
  'image': 'images/malino.jpg',
  'cat': 'Wisata Alam',
  'open': '09.00-17.00 WITA'
},
{
  'name': 'Pantai Losari',
  'image': 'images/pantai-losari.jpg',
  'cat': 'Landmark',
  'open': '06.00-17.00 WITA'
},
{
  'name': 'Tana Toraja',
  'image': 'images/toraja.jpg',
  'cat': 'Wisata Budaya',
  'open': '9.00-17.00 WITA'
},
}.toList();

Tugas terakhir adalah me-register ke-5 image tersebut karena sifatnya adalah local file. Download seluruh file-nya di repository artikel ini dan simpan di dalam folder images di root directory (red: jika folder images belum ada, silahkan buat foldernya).

register local image flutter

Modifikasi file pubspec.yaml menjadi.

assets:
   - images/bantimurung.jpg
   - images/bira.jpg
   - images/malino.jpg
   - images/pantai-losari.jpg
   - images/toraja.jpg

Sebagai penutup dari section ini adalah menampilkan kotak informasi, replace code KOMENTAR-4 dengan code berikut.

//KOMENTAR-4
Container(
  margin: const EdgeInsets.only(top: 10),
  padding: const EdgeInsets.all(8),
  decoration: BoxDecoration(
    border: Border.all(width: 0.5, color: Colors.grey),
    borderRadius: BorderRadius.circular(20),
  ),
  child: Column(
    children: <Widget>[
      Row(
        children: <Widget>[
          Padding(
            padding: const EdgeInsets.only(right: 8.0),
            child: Icon(
              Icons.info_outline,
              color: Colors.red,
            ),
          ),
          Text(
            'Informasi',
            style: TextStyle(
                fontWeight: FontWeight.bold, fontSize: 20),
          )
        ],
      ),
      Divider(),
      Padding(
        padding: const EdgeInsets.only(
            top: 8.0, left: 8, bottom: 5),
        child: Text(
          'Jangan membuang sampah sekecil apapun selama berada dilokasi pariwisata, cagar budaya dan cagar alam adalah miliki bersama, maka lestarikanlah.',
          style: TextStyle(color: Colors.grey),
        ),
      )
    ],
  ),
)

Note: Penjelasan dari code di atas hanya mengulang kegiatan sebelumnya yakni membuat sebuah kotak dengan border berwarna grey dan setiap sudutnya dibuat melengkung. Adapun content-nya adalah teks informasi yang ingin disampaikan.

Membuat Carousel Dengan Page View

Teknik lainnya dalam membuat carousel atau image slide show dengan Flutter adalah menggunakan widget PageView. Widget tersebut belum pernah dibahas sebelumnya maka akan menjadi materi baru dalam artikel ini.

Sebelum membuat carousel-nya, maka bagian pertama adalah menampilkan 3 buah teks untuk kategori dimana seharusnya adalah tab tapi karena saya tidak punya ide untuk content pada tab berikutnya maka kita buat hanya dalam bentuk teks biasa saja.

Replace KOMENTAR-5 dengan code berikut

//KOMENTAR-5
Padding(
  padding: const EdgeInsets.only(top: 10, bottom: 10),
  child: Row(
    mainAxisAlignment: MainAxisAlignment.spaceEvenly,
    children: <Widget>[
      Row(
        children: <Widget>[
          Text('Wisata Alam', style: TextStyle(fontWeight: FontWeight.bold, fontSize: 14),),
          Icon(Icons.check_circle, color: Colors.red,)
        ],
      ),
      Text('Wisata Budaya', style: TextStyle(fontWeight: FontWeight.bold, fontSize: 14),),
      Text('Wisata Kuliner', style: TextStyle(fontWeight: FontWeight.bold, fontSize: 14),),
    ],
  ),
),

Note: Hanya menampilkan teks biasa jadi tidak perlu penjelasan.

Tiba saatnya untuk membuat carousel di Flutter menggunakan PageView, replace KOMENTAR-6

//KOMENTAR-6
Expanded(
  //MENGGUNAKAN BUILDER
  child: PageView.builder(
    //DIMANA CONTROLLERNYA DIAMBIL DARI VARIABLE _PAGECONTROLLER YANG AKAN DIBUAT NANTI
    controller: _pageController,
    //KETIKA PAGENYA BERGANTI ATAU CAROUSELNYA DIGESER
    onPageChanged: (value) {
      setState(() {
       //MAKA CURRENT SLIDE DIUBAH VALUENYA
        _currentSlide = value;
      });
    },
    //ITEM BUILDERNYA MEMUAT FUNGSI BARU BERNAMA slideShow DENGAN MENGIRIMKAN INDEX LOOPING DARI PAGEVIEW
    itemBuilder: (BuildContext context, int index) =>
        slideShow(index),
    //JUMLAH SLIDENYA KITA SET 3 SAJA
    itemCount: 3,
  ),
),

Kemudian tambahkan code di bawah ini setelah fungsi favoritePlace()

slideShow(int index) {
  //CONTENTNYA ADALAH SEBUAH CONTAINER
  return Container(
    //YANG SUDAH DI-SET MARGIN DISEKELILINGNYA
    margin: EdgeInsets.all(10),
    //DENGAN DECORATION BERISI IMAGE YANG MEMENUHI CONTAINER
    decoration: BoxDecoration(
      image: DecorationImage(
        image: AssetImage(
          _images[index], //ADAPUN IMAGENYA DIAMBIL DARI VARIABLE _images BERDASARKAN INDEX LOOPING
        ),
        fit: BoxFit.cover, //SET COVER AGAR MENUTUPI SELURUH SPACE CONTAINER
      ),
      borderRadius: BorderRadius.circular(20), //BUAT MELENGKUNG SETIAP SUDUTNYA
    ),
  );
}

Bagian terakhir adalah mendefinisikan variable berikut ini untuk kebutuhan gambar, pengaturan controller dari PageView.

PageController _pageController; //INISIASI VARIABLE _PAGECONTROLLER
int _currentSlide = 1; //INISIASI DEFAULT VALUE DARI CURRENT SLIDE
final _images = ['images/56.jpg', 'images/60.jpg', 'images/71.jpg'];

@override
void initState() {
  _pageController = PageController(
    initialPage: _currentSlide, //SLIDE YANG AKAN DISOROT BERDASARKAN VALUE DARI CURRENT SLIDE
    keepPage: false,
    viewportFraction: 0.5, //SEDANGKAN INI ADALAH UKURAN UNTUKS SETIAP CONTENT SLIDE
  );
  super.initState();
}

Download ketiga gambar yang ada di dalam variable images di repository daengweb dan simpan di dalam folder yang sama seperti sebelumnya, yakni images. Kemudian modifikasi file pubspec.yaml menjadi

assets:
   - images/56.jpg
   - images/60.jpg
   - images/71.jpg
   - images/bantimurung.jpg
   - images/bira.jpg
   - images/malino.jpg
   - images/pantai-losari.jpg
   - images/toraja.jpg

Adapun hasil akhir yang akan diperoleh terlihat seperti berikut

membuat carousel flutter

Baca Juga: Mengenal Widget Flutter #6: Grid View, ClipRRect & ClipPath, Hero Animation

Kesimpulan

Membuat carousel atau slide show di Flutter tidaklah sesulit yang dibayangkan, kita bisa memanfaatkan widget yang familiar seperti List View atau menggunakan widget yang berbeda seperti Page View. Sepanjang artikel ini kita banyak mengulang penggunaan widget yang telah lampau dan juga belajar menggunakan sebuah widget baru.

Semakin banyak case dalam belajar bahasa pemrograman akan semakin mudah dalam memahami bagaimana caranya bekerja

Adapun dokumentasi code dari artikel ini bisa dilihat di Github.

Category:
Share:

Comments