ขั้นตอนวิธีสร้าง App โดยใช้ Flutter ( Flutter Tutorial Part 1 )

ใน tutorial นี้ เราจะมาสอนการสร้างแอพพลิเคชั่นโดยใช้ Flutter แบบ Step by step แอพที่สร้างขึ้นจะเป็นแบบ open source อยู่ที่ Aviacommerce platform, tutorial นี้โฟกัสไปที่ แอพพลิเคชั่นเพื่อที่จะนำเสนอ concepts ที่สำคัญของ flutter framework

Tutorial นี้เป็นแค่ส่วนแรกของ Tutorial ทั้งหมดเท่านั้น :-

  1. วิธีการสร้าง App โดยใช้ Flutter
  2. วิธีการทำ layout ใน App โดยใช้ Flutter (ยังไม่มา)
  3. วิธีจัดการ data ใน flutter (ยังไม่มา)
  4. วิธีการ listing ใน Flutter (ยังไม่มา)

Blog นี้จะอธิบายเกี่ยวกับวิธีการสร้าง layouts แนะนำแบบ step by step หากคุณต้องการดู code ทั้งหมดเลย โปรเจ็คทั้งหมดมี code อยู่ใน Github ถ้าอยากลองดูคุณก็สามารถไปดูก่อนได้เลย

ทีมของเรา () พยายามหาเกี่ยวกับ framework ที่สามารถพัฒนา software ในแบบใหม่ๆได้อยู่ตลอดเวลา เราได้ติดตามกิจกรรมหรือข่าวสารที่เกี่ยวกับ flutter ตั้งแต่ตัว Beta รุ่นแรกออก

ในที่สุด google ก็เปิดตัว Flutter 1.0, เป็นเครื่องมือ UI ตัวแรกที่มีความเสถียร เป็น Experiences ใหม่ๆในการใช้สร้างพวก native app สำหรับ iphone หรือว่า android จาก codebase เดียว

Flutter มีขั้นตอนการติดตั้งหลายขั้นตอนเพื่อให้เข้ากับสภาพคอมของเรา ให้ทำตาม คู่มือการติดตั้ง นี้ไปก่อน จากนั้นให้ดูต่อ

เมื่อติดตั้งเสร็จแล้ว ให้ลองสร้าง test project ผู้เขียนแนะนำให้ใช้ Android studio เพราะมันมี IDE ที่ครบเครื่องสำหรับ Flutter  Android studio จะต้องมี editor plugin ในการเขียน Dart ก่อน

เปิด Android studio ขึ้นมา คุณจะเห็น option ในการสร้างโปรเจค flutter ใหม่

ให้เลือก Flutter Application เมื่อหน้าต่าง configurations ขึ้นมา

ตั้งชื่อให้โปรเจคแรกของคุณ หรือจะตั้งชื่อว่า timer ตามผู้เขียนก็ได้

ขั้นตอนนี้ หน้าต่างจะขึ้นมาให้คุณใส่ชื่อ package

หลังจากนั้น Flutter SDK จะสร้าง Directory ทั้งหมดที่ต้องใช้ในแอพพลิเคชั่น สิ่งที่คุณทำทั้งหมดจะอยู่ใน Folder ที่ชื่อว่า lib และเราจะเริ่มเขียนในไฟล์ชื่อว่า main.dart


ใน Flutter ให้จำไว้ว่าทุกอย่างล้วนเป็น widget ไม่ว่าจะเป็น รูปภาพ ไอคอน หรือว่า text แม้กระทั่ง layouts อย่างเช่น แถว columns และ grid ที่ใช้ จัดเรียง widgets อื่นๆ ก็คือ widgets ในตัวมันเอง

ข้อดีคือ Flutter SDK สร้าง widget ที่สามรถแก้ไขได้โดยตรงกับ code ของแอพในตัวมันเองได้เลย เพื่อให้ง่ายขึ้น ให้ลบออกและแก้ไขให้เป็น Hello world

ไฟล์ main.dart ของคุณจะขึ้นเป็นแบบนี้

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Welcome to Flutter',
      home: Scaffold(
        appBar: AppBar(
          title: Text('Welcome to Flutter'),
        ),
        body: Center(
          child: Text('Hello World'),
        ),
      ),
    );
  }
}
เปิด emulator ใน Android ขึ้นมา จากนั้นจะมี widget ขึ้นมาเป็นข้อความทักทายว่า “Hello world”
จะสังเกตได้ว่า widget ที่ขึ้นมี code อยู่ตรงนี้ เราจะลองเปลี่ยน body ของตัวMaterialApp เพื่อแก้ไข Interface ตามที่เราอยากได้ และนี่ก็คือ code ในตอนแรก
body: Center(
  child: Text('Hello World'),
)

องค์ประกอบของ layout (widgets) สามารถแบ่งออกเป็น 2 ประเภท ขึ้นอยู่กับว่ามันสามารถจัดเก็บ widget ได้ตัวเดียวหรือ เก็บเป็น Array ของ widget ได้   ContainerPadding จะเป็นประเภทแรก ส่วน RowColumn จะเป็นเภทที่ 2 ตามลำดับ

นี่ก็คือลักษณะ layout ของ row ที่มี 3 children ในรูปแบบของข้อความ

body: Center(
  child: Row(
    mainAxisAlignment: MainAxisAlignment.center,
    children: <Widget>[
      Text('0'),
      Text('0'),
      Text('0'),
    ],
  ),
),

ก่อนที่เราจะไปจัดองค์ประกอบความสวยงามของ widget เราควรที่จะสร้าง widget ใหม่ขึ้นมาก่อนเพื่อที่เราจะได้ดูตามไปด้วย และเพื่อความสะดวกสบาย

แทนที่ Children ทั้งสามด้วย widget ที่เรากำหนดไว้เอง ไฟลน์ main.dart จะมีหน้าตาประมาณนี้

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Welcome to Flutter',
      home: Scaffold(
        appBar: AppBar(
          title: Text('Timer'),
        ),
        body: Center(
          child: Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              CustomTextContainer(),
              CustomTextContainer(),
              CustomTextContainer(),
            ],
          ),
        ),
      ),
    );
  }
}

class CustomTextContainer extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Text('00');
  }
}

ตอนนี้สีของ timer ดูจืดชืดนิดหน่อย พูดตรงๆเลยคือผู้เขียนก็ไม่ได้เก่งในด้าน UI มาก ขั้นตอนต่อไป pack รวม widget ไว้ใน container และตกแต่ง container ด้วยสี Background พร้อมกับจัดระยะการเว้นช่องว่างเพื่อให้องค์ประกอบออกมาดี

class CustomTextContainer extends StatelessWidget {
  CustomTextContainer({this.label, this.value});

  final String label;
  final String value;

  @override
  Widget build(BuildContext context) {
    return Container(
      margin: EdgeInsets.symmetric(horizontal: 5),
      padding: EdgeInsets.all(20),
      decoration: new BoxDecoration(
        borderRadius: new BorderRadius.circular(10),
        color: Colors.black87,
      ),
      child: Column(
        mainAxisSize: MainAxisSize.min,
        children: <Widget>[
          Text(
            '$value',
            style: TextStyle(
              color: Colors.white,
              fontSize: 54,
              fontWeight: FontWeight.bold,
            ),
          ),
          Text(
            '$label',
            style: TextStyle(
              color: Colors.white70,
            ),
          )
        ],
      ),
    );
  }
}

ให้ใส่ปุ่มจับเวลาที่ด้านล่าง widget ด้วย codeจะมีหน้าตาประมาณนี้

และนี่ก็เป็นส่วนที่สำคัญที่สุดของแอพ ในส่วนของ “State”  State จะเก็บค่าปัจจุบันของตัวจับเวลาและไม่ว่าตัวจับเวลาจะทำงาน (กำลังรัน) หรือว่าไม่ทำงาน ผู้เขียนใช้  TimerState class เพราะมันสามารถจัดการดูในเรื่องของ State ได้ แล้วยังช่วยในเรื่องของการทำ widget tree ให้ง่ายขึ้นอีกด้วย

class Timer extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return new TimerState();
  }
}

class TimerState extends State<Timer> {
  int secondsPassed = 0;
  bool isActive = false;

  @override
  Widget build(BuildContext context) {
    // Return Widget Tree
  }
}

การเขียนปุ่ม start และ stop ให้ทำงานได้ในปุ่มเดียว

RaisedButton(
  child: Text(isActive ? 'STOP' : 'START'),
  onPressed: () {
    setState(() {
      isActive = !isActive;
    });
  },
)

Dart มาพร้อมกับโมดูลสุดหรูสำหรับการทำงานแบบ async เราสามารถใช้ timer class เพื่อช่วยเพิ่มตัววินาทีเข้ามา TimerAppState ที่แก้ไขแล้วมีคำอธิบายอยู่ด้านล่าง จะสังเกตได้ว่าเราได้ทำการปรับปรุง Timer class ไปเป็น TimerApp เพื่อเลี่ยงความยุ่งยากในTimer class

class TimerAppState extends State<TimerApp> {
  static const duration = const Duration(seconds:1);

  int secondsPassed = 0;
  bool isActive = false;

  Timer timer;

  void handleTick() {
    if (isActive) {
      setState(() {
        secondsPassed = secondsPassed + 1;
      });
    }
  }

  @override
  void initState() {
    timer = Timer.periodic(duration, (Timer t) {
      handleTick();
    });
    super.initState();
  }

  @override
  Widget build(BuildContext context) {

    int seconds = secondsPassed % 60;
    int minutes = secondsPassed ~/ 60;
    int hours = secondsPassed ~/ (60*60);

    return MaterialApp(...)
  }
}

ตอนนี้แอพก็ทำงนได้อย่างสมบูรณ์แล้ว code main.dart ที่เขียนเสร็จแล้วจะอยู่ที่นี่ ผู้เขียนหวังว่า Tutorial นี้จะช่วยให้คุณเข้าใจพื้นฐานของการใช้ Flutter framework ได้

บทความแปลจากเว็บไซต์: medium

รวบรวม Course Online Flutter น่าสนใจ