Sunday, May 12, 2019

Mengatasi Masalah "Overflowing Rendering" Pada Layar Input Form Flutter

Error overflowing RenderFlex
Mengatasi Masalah "Overflowing Rendering" atau Keluar Strip Kuning Hitam pada Flutter - Muncul tampilan strip kuning hitam pada tampilan Flutter adalah hal yang cukup menyebalkan. Muncul nya tampilan strip kuning hitam pada layar aplikasi yang kita buat dengan Flutter menandakan suatu error yaitu Overflow Rendering, atau dengan kata lain ruang layar tidak cukup untuk menampilkan widget-widget kita secara keseluruhan, sehingga oleh engine Flutter akan ditampilkan tampilan strip kuning hitam baik secara horizontal maupun vertikal.

Hal ini tentu saja tidak boleh terjadi pada pembuatan aplikasi sesungguhnya, karena merupakan bug yang membuat UI/UX menjadi negatif. Untuk itu kita harus mengantisipasi agar masalah ini tidak terjadi pada aplikasi Flutter kita.

Keluar tampilan strip kuning hitam ini nampaknya membuat frustasi bagi pemula yang baru belajar Flutter, terutama keluar tampilan strip kuning hitam saat keyboard muncul ketika user ingin mengetikan huruf pada input form. Tentunya sobat akan segera mencari solusi jika menemui masalah yang ckup menganggu ini, jika tidak tepat sasaran maka solusi yang sobat ambil akan menambah masalah lain. Misalnya sobat akan merubah layout tampilan layar Flutter, dsb.

Jika sobat mengalami masalah Overflow Rendering pada aplikasi mobile yang sobat buat dengan Flutter, solusinya sangat sederhana yaitu dengan  mebungkus widget utama menggunakan widget SingleChildScrollView.

Berikut saya contohkan, contoh kode Flutter pada kasus form login yang tanpa SingleChildScrollView  dan dengan SingleChildScrollView, untuk kita lihat bedanya nanti.

Contoh Kode Form Login 1 (tanpa SingleChildScrollView)
import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Eduprog',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Eduporg'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);
  final String title;
  @override  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State {
  @override  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Padding(
        padding: EdgeInsets.symmetric(horizontal: 30),
        child: Column(
          children: [
            SizedBox(
              height: 200,
            ),
            Form(
              child: Column(
                children: [
                  TextFormField(
                    decoration: InputDecoration(
                        hintText: "Email",
                        hintStyle: TextStyle(color: Colors.grey),
                        enabledBorder: const UnderlineInputBorder(
                          borderSide: const BorderSide(color: Colors.blue, width: 2.0),
                        )
                    ),
                    keyboardType: TextInputType.emailAddress,
                    style: TextStyle(fontSize: 20),
                  ),
                  SizedBox(
                    height: 15,
                  ),
                  TextFormField(
                    decoration: InputDecoration(
                        hintText: "Password",
                        hintStyle: TextStyle(color: Colors.grey),
                        enabledBorder: const UnderlineInputBorder(
                          borderSide: const BorderSide(color: Colors.blue, width: 2.0),
                        )
                    ),
                    keyboardType: TextInputType.text,
                    obscureText: true,
                    style: TextStyle(fontSize: 20),
                  ),

                ],
              ),
            ),
            SizedBox(
              height: 30,
            ),
            InkWell(
              onTap: (){
                print("Login process");
              },
              child: Container(
                //width: 100.0,                height: 40,
                decoration: new BoxDecoration(
                  color: Colors.deepOrange,
                  border: Border.all(color: Colors.deepOrange, width: 2.0),
                  borderRadius: BorderRadius.circular(10.0),
                ),
                child: Center(child: Text('Login', style: new TextStyle(fontSize: 18.0, color: Colors.white),),),
              ),
            )
          ],
        ),
      )
    );
  }
}
Hasil dari kode diatas adalah sebagai berikut (sebelum dan setelah keyboard muncul)
Form Login 1 (Error Overflow)
Lalu coba kita perbaiki kode di atas dengan membungkus SingleChildScrollView pada widget utamanya dengan scroll direction vertical. Berikut adalah contoh kode perbaikan nya:
import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Eduprog',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Eduporg'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);
  final String title;
  @override  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State {
  @override  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: SingleChildScrollView(
        scrollDirection: Axis.vertical,
        child:Padding(
          padding: EdgeInsets.symmetric(horizontal: 30),
          child: Column(
            children: [
              SizedBox(
                height: 200,
              ),
              Form(
                child: Column(
                  children: [
                    TextFormField(
                      decoration: InputDecoration(
                          hintText: "Email",
                          hintStyle: TextStyle(color: Colors.grey),
                          enabledBorder: const UnderlineInputBorder(
                            borderSide: const BorderSide(color: Colors.blue, width: 2.0),
                          )
                      ),
                      keyboardType: TextInputType.emailAddress,
                      style: TextStyle(fontSize: 20),
                    ),
                    SizedBox(
                      height: 15,
                    ),
                    TextFormField(
                      decoration: InputDecoration(
                          hintText: "Password",
                          hintStyle: TextStyle(color: Colors.grey),
                          enabledBorder: const UnderlineInputBorder(
                            borderSide: const BorderSide(color: Colors.blue, width: 2.0),
                          )
                      ),
                      keyboardType: TextInputType.text,
                      obscureText: true,
                      style: TextStyle(fontSize: 20),
                    ),

                  ],
                ),
              ),
              SizedBox(
                height: 30,
              ),
              InkWell(
                onTap: (){
                  print("Login process");
                },
                child: Container(
                  //width: 100.0,                  height: 40,
                  decoration: new BoxDecoration(
                    color: Colors.deepOrange,
                    border: Border.all(color: Colors.deepOrange, width: 2.0),
                    borderRadius: BorderRadius.circular(10.0),
                  ),
                  child: Center(child: Text('Login', style: new TextStyle(fontSize: 18.0, color: Colors.white),),),
                ),
              )
            ],
          ),
        )
      )
    );
  }
}

Hasil dari kode di atas adalah sebagai berikut (sebelum dan setelah keyboard muncul)
Form Login 2 (Error Overflow Tidak Terjadi)

Cukup simpel kan, mengatasi masalah Overflow Rendering dengan cara di atas? Overflow Rndering juga bisa terjadi pada sudut horizontal, untuk mengatasi masalah tersebut caranya dengan hanya saja properti scroll direction yang digunakan aadalah Axis.horizontal bukan Axis.vertical seperti kasus di atas.

Source Code Lengkap : GITHUB

Mengatasi Error "org-dartlang-debug:synthetic_debug_expression:1:18: Error: Can't find '}' to match '{'"


Mengatasi Error "org-dartlang-debug:synthetic_debug_expression:1:18: Error: Can't find '}' to match '{'" - Dalam membuat aplikasi mobile dengan Flutter (Dart) terkadang kita menjumpai kendala atau masalah-masalah teknis yang tidak terduga. Salah satu contoh nya adalah error dengan keterangan "org-dartlang-debug:synthetic_debug_expression:1:18: Error: Can't find '}' to match '{'".

Secara umum cara mengatasi error pada Flutter (Dart) adalah dengan memperhatikan petunjuk error (tanda merah) pada kode editor yang pada kasus ini adalah dengan editor Android Studio. Baris-baris yang error akan ditunjukan dengan tanda merah beserta keterangan error yang perlu diperbaiki, seperti gambar dibawah ini:
Error Pada Flutter
Akan tetapi, seperti pengalaman yang saya alami sebelumnya ada hal-hal teknis yang tak terduga, dimana secara kode tidak menunjukan error namun ketika kode akan dijalankan atau dikompilasi akan menunjukan error tertentu, salah satu kasus yang saya alami adalah error dengan keterangan "org-dartlang-debug:synthetic_debug_expression:1:18: Error: Can't find '}' to match '{'".

Untuk mengatasi error dimana secara kode editor tidak menunjuk baris-baris yang error, bisa jadi disebabkan oleh cache kompiler Flutter yang belum bersih. Untuk itu, sobat jangan ambil pusing lakukan langkah dibawah ini untuk membersihkan cache kompiler yang tidak sejalan (sesuai) dengan kode editor nya:
Menu "Flutter Clean"
Pilih menu Tools -> Flutter -> Flutter Clean, sampai proses tersebut selesai Lalu coba build ulang / jalankan ulang projek Flutter sobat. Semoga masalah di atas segera teratasi. Perlu sobat ketahui, jenis error yang timbul mungkin masih banyak jenis lainya, pada prinsipnya jika kode sobat merasa sudah benar namun kompiler menyatakan error maka teknik tersebut patut dicoba.

Saturday, May 11, 2019

Daftar Widget Yang Wajib Dipelajari untuk Membuat Layout dan Tampilan di Flutter


Daftar Widget Penting pada Flutter untuk Membuat Layout Tampilan (Part-1) - Sobat eduprog, jika sebelumnya kita sudah membahas dasar-dasar dalam membuat tampilan pada Flutter dengan StatelessWidget dan StatefulWidget kali ini saya akan lanjutkan dengan berbagai macam widget yang secara umum wajib sobat pelajari untuk membuat layout dan tampilan yang menarik pada framework Flutter.

Sebelumnya perlu sobat ketahui bahwa, awal kali kemunculan Flutter telah dibekali dengan ratusan widget variatif yang bisa digunakan untuk membuat tampilan. Tentu saja dengan banyaknya jenis widget yang ditawarkan Flutter ini akan membuat bingung pemula yang baru saja berkenalan dengan Flutter. Seiring dengan poularitas Flutter yang semakin meningkat hari demi hari, tentu saja akan meningkatkan jumlah widget bawaan pada Flutter.

Untuk itu, sobat eduprog harus benar-benar selektif pada saat awal-awal belajar Flutter, sehingga mampu mengimplementasikan pembuatan tampilan / interface lebih cepat dengan menguasai widget-widget yang sifatnya sangat dasar untuk membuat sebuah layout dan tampilan yang menarik.
Pada prinsipnya membuat tampilan aplikasi mobile itu lebih sederhana, karena untuk viewport / ruang layar yang ukuranya kecil. Akan tetapi tampilan yang kita buat nantinya harus bersifat responsive dan dibekali dengan animasi-animasi untuk membuat tampilan apliaksi yang lebih interaktif.

Perlu sobat tanamkan di kepala bahwa konsep sebuah layout yang paling dasar adalah membuat suatu table, dimana tabel tentu saja terdiri dari kolom dan baris. Karena sebelum kita membuat detail tampilan pada layar, kita perlu menentukan layout utama yang paling umum adalah berupa tabel (baris dan kolom).

Untuk menghemat waktu, berikut adalah daftar widget-widget penting untuk membuat layout dan tampilan yang perlu sobat pelajari di awal-awal sobat belajar Flutter:

1. Container 

Adalah widget paling umum untuk menaruh widget lainya, atau sebagai kontainer widget lain.  Kalau dibayangkan dalam HTML, Container ini bisa diibaratkan suatu div

Contoh Kode:
Container( margin: const EdgeInsets.all(10.0), color: Colors.amber[600], width: 48.0, height: 48.0, )

2. Text

Widget Text adalah widget yang akan paling sering anda gunakan dalam membuat tampilan pada Flutter, karena widget ini berfungsi untuk menampilkan teks/caption pada widget lainya. Widget Teks ini menampilkan serangkaian teks dengan gaya tunggal (single style).

Contoh Kode:
Text( 'I Love Eduprog', textAlign: TextAlign.center, overflow: TextOverflow.ellipsis, style: TextStyle(fontWeight: FontWeight.bold), )

3. RichText

Widget RichText adalah widget Text dengan fitur-fitur tambahan yaitu dapat menampung beragam gaya (multiple style). Dengan widget ini sobat bisa membuat tulisan warna-warni atau berbagam ukuran dengan widget ini. Walaupun sobat juga bisa menggunakan banyak widget Text dalam satu blok untuk melakukan hal yang sama dengan widget RichText, namun tentu saja akan membuat kode sobat lebih sulit dibaca jika menggunakan banyak widget Text.

Contoh Kode:
RichText( text: TextSpan( text: 'Hello ', style: DefaultTextStyle.of(context).style, children: [ TextSpan(text: 'bold', style: TextStyle(fontWeight: FontWeight.bold)), TextSpan(text: ' world!'), ], ), )

4. MaterialButton

Salah satu widget untuk membuat tombol pada Flutter, Ukuran tombol akan membesar atau menyesuaikan widget induknya. Selain MaterialButton ada beberapa widget lainya untuk membuat tombol yang bisa menjadi alternatif / pertimbangan anda antara lain adalah FlatButton, OutlineButton, atau RaisedButton.

5. Center

Center adalah widget yang sering digunakan untuk memposisikan suatu objek ke tengah baik secara vertikal maupun horizontal. Dengan widget ini anda bisa membuat suatu posisi objek secara otomatis ke posisi tengah dan relatif terhadap induknya.

Contoh Kode:
Center( child: Container( margin: const EdgeInsets.all(10.0), color: Colors.amber[600], width: 48.0, height: 48.0, ), )

6. Icon

Widget untuk menampilkan ikon (glyph) dengan kelas IconData yang telah ditentukan, yang bisa diambil melalui kelas Icons.

Contoh Kode:
Icon( Icons.add, color: Colors.pink, size: 30.0, )

7. Image

Widget untuk menampilkan suatu gambar, gambar yang ditampilkan bisa berasal dari berbagai sumber. Baik dari asset (yang didaftarkan), file, ataupun dari network.

8. Row

Widget untuk menampilkan komponen / widget anaknya dalam bentuk horizontal (baris). Widget Row ini sangat penting sekali, karena akan sering sobat gunakan untuk membuat satu tampilan dengan sifat horizontal.

Contoh Kode:
Row( children: [ Expanded( child: Text('Deliver features faster', textAlign: TextAlign.center), ), Expanded( child: Text('Craft beautiful UIs', textAlign: TextAlign.center), ), Expanded( child: FittedBox( fit: BoxFit.contain, // otherwise the logo will be tiny child: const FlutterLogo(), ), ), ], )

9. Column

Widget untuk menampilkan komponen / widget anaknya dalam bentuk vertikal (kolom). Widget Column ini sangat penting sekali, karena akan sering sobat gunakan untuk membuat satu tampilan dengan sifat vertikal.

Contoh Kode:
Column( children: [ Text('Deliver features faster'), Text('Craft beautiful UIs'), Expanded( child: FittedBox( fit: BoxFit.contain, // otherwise the logo will be tiny child: const FlutterLogo(), ), ), ], )

10. Expanded

Widget untuk mengisi sisa ruang yang ada pada widget Row / Column, widget ini bisa menggunakan ukuran skala dengan mengatur niali properti flex nya. Widget ini sering dipakai untuk membuat tampilan yang responsive, karena bisa menggunakan ukuran scalar ataupun untuk mengisi sisa ruang (fleksibel).

Contoh Kode:
Center( child: Row( children: [ Expanded( flex: 2, child: Container( color: Colors.red, height: 100, ), ), Container( color: Colors.blue, height: 100, width: 50, ), Expanded( flex: 1, child: Container( color: Colors.red, height: 100, ), ), ], ), ), );

11. Stack

Salah satu widget penting lainya adalah Stack, Widget ini memposisikan anak-anaknya relatif terhadap tepi kotaknya. Widget ini berguna jika sobat ingin membuat tampilan tumpang tindih dengan cara yang sederhana, misalnya suatu tampilan memiliki beberapa teks dan gambar yang saling bertumpukan.

Contoh Kode:
Stack( children: [ Container( width: 100, height: 100, color: Colors.red, ), Container( width: 90, height: 90, color: Colors.green, ), Container( width: 80, height: 80, color: Colors.blue, ), ], )

Nah, demikian lah sobat eduprog daftar widget-widget penting untuk membuat tampilan dasar atau layout dasar pada Flutter. Tentu saja masih banyak widget lainya, namun saya sarankan agar sobat untuk menguasai ke-11 widget di atas terlebih dahulu lebih detail. Karena masing-masing widget diatas memiliki berbagai macam properti yang tidak kita bahas disini.