การใช้ Flutter ของ Google เพื่อการพัฒนามือถือข้ามแพลตฟอร์มอย่างแท้จริง
เผยแพร่แล้ว: 2022-03-10Flutter เป็นเฟรมเวิร์กการพัฒนาอุปกรณ์พกพาแบบโอเพนซอร์สแบบข้ามแพลตฟอร์มจาก Google อนุญาตให้สร้างแอปพลิเคชันประสิทธิภาพสูงและสวยงามสำหรับ iOS และ Android จากฐานรหัสเดียว นอกจากนี้ยังเป็นแพลตฟอร์มการพัฒนาระบบปฏิบัติการ Fuchsia ที่กำลังจะมีขึ้นของ Google นอกจากนี้ มันยังได้รับการออกแบบทางสถาปัตยกรรมในลักษณะที่สามารถนำไปใช้กับแพลตฟอร์มอื่น ๆ ได้ผ่านตัวฝังเครื่องยนต์ Flutter แบบกำหนดเอง
ทำไม Flutter ถูกสร้างขึ้นและทำไมคุณควรใช้มัน
ชุดเครื่องมือข้ามแพลตฟอร์มได้ใช้วิธีใดวิธีหนึ่งจากสองแนวทางในอดีต:
- พวกเขารวมมุมมองเว็บในแอปเนทีฟและสร้างแอปพลิเคชันราวกับว่าเป็นเว็บไซต์
- พวกเขารวมการควบคุมแพลตฟอร์มดั้งเดิมและให้สิ่งที่เป็นนามธรรมข้ามแพลตฟอร์มเหนือพวกเขา
Flutter ใช้แนวทางที่แตกต่างออกไปเพื่อพยายามทำให้การพัฒนาอุปกรณ์พกพาดีขึ้น มันมีเฟรมเวิร์กที่นักพัฒนาแอพพลิเคชั่นทำงานด้วย และเอ็นจิ้นที่มีรันไทม์แบบพกพาสำหรับโฮสต์แอพพลิเคชั่น เฟรมเวิร์กสร้างขึ้นจากไลบรารีกราฟิกของ Skia โดยมอบวิดเจ็ตที่แสดงผลจริง แทนที่จะเป็นเพียงตัวห่อหุ้มในการควบคุมแบบเนทีฟ
แนวทางนี้ให้ความยืดหยุ่นในการสร้างแอปพลิเคชันข้ามแพลตฟอร์มในลักษณะที่กำหนดเองอย่างสมบูรณ์ เช่นเดียวกับตัวเลือก Web Wrapper แต่ในขณะเดียวกันก็ให้ประสิทธิภาพที่ราบรื่น ในขณะเดียวกัน ไลบรารีวิดเจ็ตที่เพียบพร้อมซึ่งมาพร้อมกับ Flutter พร้อมด้วยวิดเจ็ตโอเพนซอร์ซจำนวนมาก ทำให้เป็นแพลตฟอร์มที่มีฟีเจอร์มากมายให้ใช้งาน พูดง่ายๆ ก็คือ Flutter เป็นสิ่งที่ใกล้เคียงที่สุดที่นักพัฒนามือถือมีสำหรับการพัฒนาข้ามแพลตฟอร์มโดยแทบไม่ต้องประนีประนอมเลย
โผ
แอปพลิเคชั่น Flutter เขียนด้วยภาษา Dart ซึ่งเป็นภาษาโปรแกรมที่พัฒนาโดย Google Dart เป็นภาษาเชิงวัตถุที่รองรับทั้งการคอมไพล์ล่วงหน้าและแบบทันท่วงที ทำให้เหมาะสำหรับการสร้างแอปพลิเคชันดั้งเดิม ในขณะที่ให้เวิร์กโฟลว์การพัฒนาที่มีประสิทธิภาพด้วยการรีโหลดด่วนของ Flutter Flutter เพิ่งย้ายไป Dart เวอร์ชัน 2.0 เช่นกัน
ภาษา Dart มีคุณสมบัติมากมายที่เห็นในภาษาอื่น ๆ รวมถึงการรวบรวมขยะ, async-await, การพิมพ์ที่รัดกุม, ข้อมูลทั่วไปรวมถึงไลบรารีมาตรฐานที่หลากหลาย
Dart นำเสนอฟีเจอร์ที่คู่ควรกับนักพัฒนาที่มาจากภาษาต่างๆ เช่น C#, JavaScript, F#, Swift และ Java นอกจากนี้ Dart สามารถคอมไพล์เป็น Javascript เมื่อใช้ร่วมกับ Flutter จะทำให้สามารถแชร์โค้ดผ่านแพลตฟอร์มเว็บและมือถือได้
เส้นเวลาทางประวัติศาสตร์ของเหตุการณ์
- เมษายน 2015
Flutter (เดิมชื่อรหัสว่า Sky) แสดงที่ Dart Developer Summit - พฤศจิกายน 2015
สกายเปลี่ยนชื่อเป็น Flutter - กุมภาพันธ์ 2018
Flutter beta 1 ประกาศในงาน Mobile World Congress 2018 - เมษายน 2018
Flutter beta 2 ประกาศแล้ว - พฤษภาคม 2018
Flutter beta 3 ประกาศที่ Google I/O Google ประกาศ Flutter พร้อมสำหรับแอพการผลิต
เปรียบเทียบกับแพลตฟอร์มการพัฒนาอื่นๆ
Apple/Android Native
แอปพลิเคชันดั้งเดิมมีแรงเสียดทานน้อยที่สุดในการนำคุณสมบัติใหม่มาใช้ พวกเขามักจะมีประสบการณ์ของผู้ใช้ที่สอดคล้องกับแพลตฟอร์มที่กำหนดมากขึ้นเนื่องจากแอปพลิเคชันถูกสร้างขึ้นโดยใช้การควบคุมจากผู้ขายแพลตฟอร์มเอง (Apple หรือ Google) และมักจะปฏิบัติตามแนวทางการออกแบบที่กำหนดโดยผู้ขายเหล่านี้ ในกรณีส่วนใหญ่ แอปพลิเคชันแบบเนทีฟจะทำงานได้ดีกว่าแอปพลิเคชันที่สร้างด้วยข้อเสนอข้ามแพลตฟอร์ม แม้ว่าความแตกต่างจะเล็กน้อยมากในหลายกรณี ทั้งนี้ขึ้นอยู่กับเทคโนโลยีข้ามแพลตฟอร์มพื้นฐาน
ข้อได้เปรียบที่สำคัญอย่างหนึ่งของแอปพลิเคชันเนทีฟคือสามารถใช้เทคโนโลยีใหม่ล่าสุดที่ Apple และ Google สร้างในรุ่นเบต้าได้ทันทีหากต้องการ โดยไม่ต้องรอให้มีการผสานรวมกับบุคคลที่สาม ข้อเสียเปรียบหลักในการสร้างแอปพลิเคชันแบบเนทีฟคือการขาดการใช้โค้ดซ้ำในแพลตฟอร์มต่างๆ ซึ่งอาจทำให้การพัฒนามีราคาแพงหากกำหนดเป้าหมายไปที่ iOS และ Android
React Native
React Native อนุญาตให้สร้างแอปพลิเคชันดั้งเดิมโดยใช้ JavaScript การควบคุมจริงที่แอปพลิเคชันใช้คือการควบคุมแพลตฟอร์มแบบเนทีฟ ดังนั้นผู้ใช้ปลายทางจึงสัมผัสได้ถึงแอปที่มาพร้อมเครื่อง สำหรับแอพที่ต้องการการปรับแต่งนอกเหนือจากสิ่งที่เป็นนามธรรมของ React Native ยังคงจำเป็นต้องพัฒนาเนทีฟ ในกรณีที่จำนวนการปรับแต่งที่จำเป็นมาก ประโยชน์ของการทำงานภายในเลเยอร์นามธรรมของ React Native จะลดลงจนถึงจุดที่ในบางกรณีการพัฒนาแอปโดยกำเนิดจะมีประโยชน์มากกว่า
ซามาริน
เมื่อพูดถึง Xamarin มีสองแนวทางที่จำเป็นต้องได้รับการประเมิน สำหรับแนวทางข้ามแพลตฟอร์มมากที่สุดคือ Xamarin.Forms แม้ว่าเทคโนโลยีจะแตกต่างจาก React Native มาก แต่ในเชิงแนวคิดก็มีแนวทางที่คล้ายคลึงกันในการทำให้การควบคุมแบบเนทีฟเป็นนามธรรม ในทำนองเดียวกันก็มีข้อเสียที่คล้ายกันเกี่ยวกับการปรับแต่ง
ประการที่สอง มีคำ Xamarin-classic หลายคำ วิธีนี้ใช้ผลิตภัณฑ์ iOS และ Android ของ Xamarin อย่างอิสระเพื่อสร้างคุณลักษณะเฉพาะแพลตฟอร์ม เช่นเดียวกับเมื่อใช้เนทีฟของ Apple/Android โดยตรง โดยใช้ C# หรือ F# ในกรณี Xamarin เท่านั้น ประโยชน์ของ Xamarin ก็คือสามารถแชร์โค้ดเฉพาะที่ไม่ใช่แพลตฟอร์ม สิ่งต่างๆ เช่น เครือข่าย การเข้าถึงข้อมูล บริการเว็บ ฯลฯ ได้
ต่างจากทางเลือกอื่น Flutter พยายามมอบโซลูชันข้ามแพลตฟอร์มที่สมบูรณ์ยิ่งขึ้นให้กับนักพัฒนา โดยใช้โค้ดซ้ำ ประสิทธิภาพสูง ส่วนต่อประสานผู้ใช้ที่ลื่นไหล และเครื่องมือที่ยอดเยี่ยม
ภาพรวมของแอพ Flutter
การสร้างแอพ
หลังจากติดตั้ง Flutter แล้ว การสร้างแอปด้วย Flutter นั้นง่ายพอๆ กับการเปิดบรรทัดคำสั่งและป้อน flutter create [app_name]
การเลือกคำสั่ง “Flutter: New Project” ใน VS Code หรือเลือก “Start a new Flutter Project” ใน Android สตูดิโอหรือ IntelliJ.
ไม่ว่าคุณจะเลือกใช้ IDE หรือบรรทัดคำสั่งพร้อมกับตัวแก้ไขที่คุณต้องการ เทมเพลตแอปพลิเคชัน Flutter ใหม่จะเป็นจุดเริ่มต้นที่ดีสำหรับแอปพลิเคชัน
แอปพลิเคชั่นนำแพ็คเกจ flutter
/ material.dart
มาเพื่อนำเสนอโครงพื้นฐานสำหรับแอพ เช่น แถบชื่อเรื่อง ไอคอนวัสดุ และธีม นอกจากนี้ยังตั้งค่าวิดเจ็ตแบบเก็บสถานะเพื่อสาธิตวิธีอัปเดตอินเทอร์เฟซผู้ใช้เมื่อสถานะของแอปพลิเคชันเปลี่ยนแปลง

ตัวเลือกเครื่องมือ
Flutter ให้ความยืดหยุ่นอย่างเหลือเชื่อเกี่ยวกับเครื่องมือ แอปพลิเคชันสามารถพัฒนาได้อย่างง่ายดายจากบรรทัดคำสั่งพร้อมกับตัวแก้ไขใดๆ เนื่องจากสามารถพัฒนาจาก IDE ที่รองรับ เช่น VS Code, Android Studio หรือ IntelliJ แนวทางในการดำเนินการขึ้นอยู่กับความชอบของนักพัฒนาเป็นหลัก
Android Studio นำเสนอคุณสมบัติส่วนใหญ่ เช่น Flutter Inspector เพื่อวิเคราะห์วิดเจ็ตของแอปพลิเคชันที่ทำงานอยู่และติดตามประสิทธิภาพของแอปพลิเคชัน นอกจากนี้ยังมีการปรับโครงสร้างหลายอย่างที่สะดวกเมื่อพัฒนาลำดับชั้นของวิดเจ็ต
VS Code มอบประสบการณ์การพัฒนาที่เบากว่า โดยมีแนวโน้มที่จะเริ่มต้นได้เร็วกว่า Android Studio/IntelliJ IDE แต่ละตัวมีตัวช่วยแก้ไขในตัว เช่น การเติมโค้ดให้สมบูรณ์ ทำให้สามารถสำรวจ API ต่างๆ ได้ เช่นเดียวกับการสนับสนุนการดีบักที่ดี
บรรทัดคำสั่งยังได้รับการสนับสนุนเป็นอย่างดีผ่านคำสั่ง flutter
ซึ่งทำให้ง่ายต่อการสร้าง อัปเดต และเปิดแอปพลิเคชันโดยไม่ต้องพึ่งพาเครื่องมืออื่นใดนอกเหนือจากตัวแก้ไข

กำลังโหลดใหม่
โดยไม่คำนึงถึงการใช้เครื่องมือ Flutter ยังคงรองรับการโหลดซ้ำของแอปพลิเคชันได้อย่างดีเยี่ยม ซึ่งช่วยให้แก้ไขแอปพลิเคชันที่ทำงานอยู่ได้ในหลายกรณี โดยจะคงสถานะไว้โดยไม่ต้องหยุดแอป สร้างใหม่ และปรับใช้ใหม่
การรีโหลดแบบด่วนช่วยเพิ่มประสิทธิภาพการพัฒนาอย่างมากโดยอนุญาตให้ทำซ้ำได้เร็วขึ้น มันทำให้แพลตฟอร์มนี้มีความสุขที่ได้ร่วมงานด้วย
การทดสอบ
Flutter มียูทิลิตี้ WidgetTester
เพื่อโต้ตอบกับวิดเจ็ตจากการทดสอบ เทมเพลตแอปพลิเคชันใหม่มีตัวอย่างการทดสอบเพื่อสาธิตวิธีใช้งานเมื่อสร้างการทดสอบดังที่แสดงด้านล่าง:
// Test included with the new Flutter application template import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:myapp/main.dart'; void main() { testWidgets('Counter increments smoke test', (WidgetTester tester) async { // Build our app and trigger a frame. await tester.pumpWidget(new MyApp()); // Verify that our counter starts at 0. expect(find.text('0'), findsOneWidget); expect(find.text('1'), findsNothing); // Tap the '+' icon and trigger a frame. await tester.tap(find.byIcon(Icons.add)); await tester.pump(); // Verify that our counter has incremented. expect(find.text('0'), findsNothing); expect(find.text('1'), findsOneWidget); }); }
การใช้แพ็คเกจและปลั๊กอิน
Flutter เพิ่งเริ่มต้น แต่มีระบบนิเวศสำหรับนักพัฒนาที่สมบูรณ์อยู่แล้ว: มีแพ็คเกจและปลั๊กอินมากมายสำหรับนักพัฒนาอยู่แล้ว
ในการเพิ่มแพ็คเกจหรือปลั๊กอิน เพียงรวมการพึ่งพาในไฟล์ pubspec.yaml ที่ไดเรกทอรีรากของแอปพลิเคชัน จากนั้นเรียกใช้ flutter packages get
จากบรรทัดคำสั่งหรือผ่าน IDE และเครื่องมือของ Flutter จะนำการพึ่งพาที่จำเป็นทั้งหมดมา
ตัวอย่างเช่น ในการใช้ปลั๊กอินตัวเลือกรูปภาพยอดนิยมสำหรับ Flutter pubspec.yaml ต้องการเพียงแสดงรายการเป็นการพึ่งพาดังนี้:
dependencies: image_picker: "^0.4.1"
จากนั้นการรัน flutter packages get
นำเสนอทุกสิ่งที่คุณต้องการเพื่อใช้งาน หลังจากนั้นก็สามารถนำเข้าและใช้ใน Dart ได้:
import 'package:image_picker/image_picker.dart';
วิดเจ็ต
ทุกอย่างใน Flutter เป็นเครื่องมือ ซึ่งรวมถึงองค์ประกอบอินเทอร์เฟซผู้ใช้ เช่น ListView
, TextBox
และ Image
ตลอดจนส่วนอื่นๆ ของเฟรมเวิร์ก รวมถึงเลย์เอาต์ แอนิเมชัน การจดจำท่าทางสัมผัส และธีม เป็นต้น
ด้วยการมีทุกอย่างเป็นวิดเจ็ต แอปพลิเคชันทั้งหมดซึ่งบังเอิญเป็นวิดเจ็ตสามารถแสดงภายในลำดับชั้นของวิดเจ็ตได้ การมีสถาปัตยกรรมที่ทุกอย่างเป็นวิดเจ็ตทำให้ชัดเจนว่าแอตทริบิวต์และพฤติกรรมบางอย่างที่ใช้กับส่วนหนึ่งของแอปมาจากไหน ซึ่งแตกต่างจากเฟรมเวิร์กของแอปพลิเคชันอื่นๆ ส่วนใหญ่ ซึ่งเชื่อมโยงคุณสมบัติและลักษณะการทำงานไม่สอดคล้องกัน บางครั้งก็แนบมาจากส่วนประกอบอื่นๆ ในลำดับชั้น และในบางครั้งบนตัวควบคุมเอง
ตัวอย่างวิดเจ็ต UI อย่างง่าย
จุดเริ่มต้นของแอปพลิเคชัน Flutter คือหน้าที่หลัก ในการวางวิดเจ็ตสำหรับองค์ประกอบส่วนต่อประสานผู้ใช้บนหน้าจอ ใน main()
ให้เรียก runApp()
และส่งวิดเจ็ตที่จะทำหน้าที่เป็นรูทของลำดับชั้นวิดเจ็ต
import 'package:flutter/material.dart'; void main() { runApp( Container(color: Colors.lightBlue) ); }
ส่งผลให้วิดเจ็ต Container
สีฟ้าอ่อนเต็มหน้าจอ:

วิดเจ็ตไร้สัญชาติกับวิดเจ็ตแบบเก็บสถานะ
วิดเจ็ตมีสองแบบ: ไร้สัญชาติและแบบเก็บสถานะ วิดเจ็ตไร้สัญชาติจะไม่เปลี่ยนเนื้อหาหลังจากที่สร้างและเริ่มต้นแล้ว ในขณะที่วิดเจ็ตแบบเก็บสถานะจะรักษาสถานะบางอย่างที่สามารถเปลี่ยนแปลงได้ขณะเรียกใช้แอปพลิเคชัน เช่น เพื่อตอบสนองต่อการโต้ตอบของผู้ใช้

ในตัวอย่างนี้ วิดเจ็ต FlatButton
และวิดเจ็ต Text
จะถูกวาดไปที่หน้าจอ วิดเจ็ต Text
เริ่มต้นด้วย String
เริ่มต้นสำหรับสถานะ การกดปุ่มส่งผลให้เกิดการเปลี่ยนแปลงสถานะที่จะทำให้วิดเจ็ต Text
ได้รับการอัปเดต โดยแสดง String
ใหม่
ในการสรุปวิดเจ็ต ให้สร้างคลาสที่มาจาก StatelessWidget
หรือ StatefulWidget
ตัวอย่างเช่น Container
สีฟ้าอ่อนสามารถเขียนได้ดังนี้:
class MyWidget extends StatelessWidget { @override Widget build(BuildContext context) { return Container(color: Colors.lightBlue); } }
Flutter จะเรียกวิธีการสร้างของวิดเจ็ตเมื่อแทรกลงในแผนผังวิดเจ็ตเพื่อให้สามารถแสดงส่วนนี้ของ UI ได้
สำหรับวิดเจ็ต stateful ให้มาจาก StatefulWidget
:
class MyStatefulWidget extends StatefulWidget { MyStatefulWidget(); @override State createState() { return MyWidgetState(); } }
class MyStatefulWidget extends StatefulWidget { MyStatefulWidget(); @override State createState() { return MyWidgetState(); } }
วิดเจ็ต stateful ส่งคืนคลาส State
ที่รับผิดชอบในการสร้างแผนผังวิดเจ็ตสำหรับสถานะที่กำหนด เมื่อสถานะเปลี่ยนแปลง ส่วนที่เกี่ยวข้องของแผนผังวิดเจ็ตจะถูกสร้างขึ้นใหม่
ในโค้ดต่อไปนี้ คลาส State
จะอัปเดต String
เมื่อมีการคลิกปุ่ม:
class MyWidgetState extends State { String text = "some text"; @override Widget build(BuildContext context) { return Container( color: Colors.lightBlue, child: Padding( padding: const EdgeInsets.all(50.0), child: Directionality( textDirection: TextDirection.ltr, child: Column( children: [ FlatButton( child: Text('Set State'), onPressed: () { setState(() { text = "some new text"; }); }, ), Text( text, style: TextStyle(fontSize: 20.0)), ], ) ) ) ); } }
class MyWidgetState extends State { String text = "some text"; @override Widget build(BuildContext context) { return Container( color: Colors.lightBlue, child: Padding( padding: const EdgeInsets.all(50.0), child: Directionality( textDirection: TextDirection.ltr, child: Column( children: [ FlatButton( child: Text('Set State'), onPressed: () { setState(() { text = "some new text"; }); }, ), Text( text, style: TextStyle(fontSize: 20.0)), ], ) ) ) ); } }
สถานะได้รับการอัพเดตในฟังก์ชันที่ส่งผ่านไปยัง setState()
เมื่อ setState()
ฟังก์ชันนี้สามารถตั้งค่าสถานะภายในใดๆ เช่น สตริงในตัวอย่างนี้ จากนั้นจะเรียกวิธีการ build
โดยอัปเดตแผนผังของวิดเจ็ตแบบเก็บสถานะ

นอกจากนี้ ให้สังเกตการใช้วิดเจ็ต Directionality
เพื่อกำหนดทิศทางของข้อความสำหรับวิดเจ็ตใดๆ ในแผนผังย่อยที่จำเป็นต้องใช้ เช่น วิดเจ็ต Text
ตัวอย่างที่นี่คือการสร้างโค้ดตั้งแต่ต้น ดังนั้นจำเป็นต้องมี Directionality
ที่ใดที่หนึ่งในลำดับชั้นของวิดเจ็ต อย่างไรก็ตาม การใช้วิดเจ็ต MaterialApp
เช่น ด้วยเทมเพลตแอปพลิเคชันเริ่มต้น จะตั้งค่าทิศทางข้อความโดยปริยาย
เค้าโครง
ฟังก์ชัน runApp
จะขยายวิดเจ็ตให้เต็มหน้าจอโดยค่าเริ่มต้น ในการควบคุมเลย์เอาต์วิดเจ็ต Flutter เสนอวิดเจ็ตเลย์เอาต์ที่หลากหลาย มีวิดเจ็ตสำหรับดำเนินการเลย์เอาต์ที่จัดวิดเจ็ตย่อยในแนวตั้งหรือแนวนอน ขยายวิดเจ็ตเพื่อเติมพื้นที่เฉพาะ จำกัดวิดเจ็ตไว้ที่พื้นที่หนึ่ง จัดวางวิดเจ็ตไว้ตรงกลางหน้าจอ และอนุญาตให้วิดเจ็ตซ้อนทับกัน
สองวิดเจ็ตที่ใช้กันทั่วไปคือ Row
และ Column
วิดเจ็ตเหล่านี้ใช้เลย์เอาต์เพื่อแสดงวิดเจ็ตย่อยในแนวนอน (แถว) หรือแนวตั้ง (คอลัมน์)
การใช้วิดเจ็ตเลย์เอาต์เหล่านี้เกี่ยวข้องกับการล้อมรอบรายการวิดเจ็ตย่อย หลัก mainAxisAlignment
จะควบคุมวิธีการจัดวางวิดเจ็ตตามแกนของเค้าโครง ไม่ว่าจะอยู่ตรงกลาง ที่จุดเริ่มต้น สิ้นสุด หรือด้วยตัวเลือกระยะห่างต่างๆ
รหัสต่อไปนี้แสดงวิธีจัดแนววิดเจ็ตย่อยหลายรายการใน Row
หรือ Column
:
class MyStatelessWidget extends StatelessWidget { @override Widget build(BuildContext context) { return Row( //change to Column for vertical layout mainAxisAlignment: MainAxisAlignment.center, children: [ Icon(Icons.android, size: 30.0), Icon(Icons.pets, size: 10.0), Icon(Icons.stars, size: 75.0), Icon(Icons.rowing, size: 25.0), ], ); } }

ตอบสนองต่อการสัมผัส
การโต้ตอบด้วยการแตะจะได้รับการจัดการด้วยท่าทางสัมผัส ซึ่งห่อหุ้มไว้ในคลาส GestureDetector
เนื่องจากเป็นวิดเจ็ตด้วย การเพิ่มการจดจำท่าทางจึงง่ายพอๆ กับการรวมวิดเจ็ตย่อยใน GestureDetector
ตัวอย่างเช่น หากต้องการเพิ่มการจัดการด้วยการแตะลงใน Icon
ให้กำหนดให้เป็นลูกของ GestureDetector
และตั้งค่าตัวจัดการของตัวตรวจจับสำหรับท่าทางสัมผัสที่ต้องการเพื่อจับภาพ
class MyStatelessWidget extends StatelessWidget { @override Widget build(BuildContext context) { return GestureDetector( onTap: () => print('you tapped the star'), onDoubleTap: () => print('you double tapped the star'), onLongPress: () => print('you long pressed the star'), child: Icon(Icons.stars, size: 200.0), ); } }
ในกรณีนี้ เมื่อทำการแตะ แตะสองครั้ง หรือกดค้างบนไอคอน ข้อความที่เกี่ยวข้องจะถูกพิมพ์:
To hot reload your app on the fly, press "r". To restart the app entirely, press "R". An Observatory debugger and profiler on iPhone X is available at: https://127.0.0.1:8100/ For a more detailed help message, press "h". To quit, press "q". flutter: you tapped the star flutter: you double tapped the star flutter: you long pressed the star
นอกจากการแตะแบบธรรมดาแล้ว ยังมีตัวจำแนกลายมืออีกมากมายสำหรับทุกอย่างตั้งแต่การเลื่อนและการปรับขนาด ไปจนถึงการลาก สิ่งเหล่านี้ทำให้ง่ายต่อการสร้างแอปพลิเคชันแบบโต้ตอบ
จิตรกรรม
Flutter ยังมีวิดเจ็ตที่หลากหลายให้ระบายสีด้วย รวมถึงวิดเจ็ตที่ปรับเปลี่ยนความทึบ กำหนดเส้นทางการตัดต่อ และใช้การตกแต่ง มันยังรองรับการวาดภาพแบบกำหนดเองผ่านวิดเจ็ต CustomPaint
และคลาส CustomPainter
และ Canvas
ที่เกี่ยวข้อง
ตัวอย่างหนึ่งของวิดเจ็ตการระบายสีคือ DecoratedBox
ซึ่งสามารถลงสี BoxDecoration
ไปที่หน้าจอได้ ตัวอย่างต่อไปนี้แสดงวิธีใช้สิ่งนี้เพื่อเติมหน้าจอด้วยการเติมไล่ระดับสี:
class MyStatelessWidget extends StatelessWidget { @override Widget build(BuildContext context) { return new DecoratedBox( child: Icon(Icons.stars, size: 200.0), decoration: new BoxDecoration( gradient: LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [Colors.red, Colors.blue, Colors.green], tileMode: TileMode.mirror ), ), ); } }

แอนิเมชั่น
Flutter มีคลาส AnimationController
ที่ควบคุมการเล่นแอนิเมชั่นในช่วงเวลาหนึ่ง รวมถึงการเริ่มและการหยุดแอนิเมชั่น ตลอดจนการเปลี่ยนค่าของแอนิเมชั่น นอกจากนี้ยังมีวิดเจ็ต AnimatedBuilder
ที่อนุญาตให้สร้างแอนิเมชั่นร่วมกับ AnimationController
วิดเจ็ตใดๆ เช่น ดาวที่ตกแต่งที่แสดงไว้ก่อนหน้านี้ สามารถมีคุณสมบัติเป็นภาพเคลื่อนไหวได้ ตัวอย่างเช่น การจัดโครงสร้างโค้ดใหม่เป็น StatefulWidget
เนื่องจากการสร้างภาพเคลื่อนไหวเป็นการเปลี่ยนแปลงสถานะ และส่งผ่าน AnimationController
ไปยังคลาส State
จะอนุญาตให้ใช้ค่าภาพเคลื่อนไหวเมื่อสร้างวิดเจ็ต
class StarWidget extends StatefulWidget { @override State createState() { return StarState(); } } class StarState extends State with SingleTickerProviderStateMixin { AnimationController _ac; final double _starSize = 300.0; @override void initState() { super.initState(); _ac = new AnimationController( duration: Duration(milliseconds: 750), vsync: this, ); _ac.forward(); } @override Widget build(BuildContext context) { return new AnimatedBuilder( animation: _ac, builder: (BuildContext context, Widget child) { return DecoratedBox( child: Icon(Icons.stars, size: _ac.value * _starSize), decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [Colors.red, Colors.blue, Colors.green], tileMode: TileMode.mirror ), ), ); } ); } }
class StarWidget extends StatefulWidget { @override State createState() { return StarState(); } } class StarState extends State with SingleTickerProviderStateMixin { AnimationController _ac; final double _starSize = 300.0; @override void initState() { super.initState(); _ac = new AnimationController( duration: Duration(milliseconds: 750), vsync: this, ); _ac.forward(); } @override Widget build(BuildContext context) { return new AnimatedBuilder( animation: _ac, builder: (BuildContext context, Widget child) { return DecoratedBox( child: Icon(Icons.stars, size: _ac.value * _starSize), decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [Colors.red, Colors.blue, Colors.green], tileMode: TileMode.mirror ), ), ); } ); } }
class StarWidget extends StatefulWidget { @override State createState() { return StarState(); } } class StarState extends State with SingleTickerProviderStateMixin { AnimationController _ac; final double _starSize = 300.0; @override void initState() { super.initState(); _ac = new AnimationController( duration: Duration(milliseconds: 750), vsync: this, ); _ac.forward(); } @override Widget build(BuildContext context) { return new AnimatedBuilder( animation: _ac, builder: (BuildContext context, Widget child) { return DecoratedBox( child: Icon(Icons.stars, size: _ac.value * _starSize), decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [Colors.red, Colors.blue, Colors.green], tileMode: TileMode.mirror ), ), ); } ); } }
ในกรณีนี้ ค่าจะใช้เพื่อเปลี่ยนขนาดของวิดเจ็ต ฟังก์ชันตัว builder
จะถูกเรียกเมื่อใดก็ตามที่ค่าภาพเคลื่อนไหวเปลี่ยนแปลง ทำให้ขนาดของดาวแตกต่างกันมากกว่า 750 มิลลิวินาที ทำให้เกิดมาตราส่วน:

การใช้คุณสมบัติดั้งเดิม
ช่องแพลตฟอร์ม
เพื่อให้สามารถเข้าถึง API แพลตฟอร์มดั้งเดิมบน Android และ iOS แอปพลิเคชัน Flutter สามารถใช้ช่องทางแพลตฟอร์มได้ ซึ่งอนุญาตให้โค้ด Flutter Dart ส่งข้อความไปยังแอปพลิเคชันโฮสต์ iOS หรือ Android ปลั๊กอินโอเพนซอร์ซจำนวนมากที่มีอยู่นั้นสร้างขึ้นโดยใช้การส่งข้อความผ่านช่องทางแพลตฟอร์ม หากต้องการเรียนรู้วิธีทำงานกับช่องทางแพลตฟอร์ม เอกสาร Flutter จะมีเอกสารที่ดีที่สาธิตการเข้าถึง API ของแบตเตอรี่ในตัว
บทสรุป
แม้แต่ในรุ่นเบต้า Flutter ก็นำเสนอโซลูชันที่ยอดเยี่ยมสำหรับการสร้างแอปพลิเคชันข้ามแพลตฟอร์ม ด้วยเครื่องมือที่ยอดเยี่ยมและการโหลดซ้ำแบบร้อน ทำให้ได้รับประสบการณ์การพัฒนาที่น่าพึงพอใจ แพ็คเกจโอเพ่นซอร์สมากมายและเอกสารประกอบที่ยอดเยี่ยมช่วยให้เริ่มต้นได้ง่าย ในอนาคต นักพัฒนา Flutter จะสามารถกำหนดเป้าหมาย Fuchsia นอกเหนือจาก iOS และ Android เมื่อพิจารณาถึงความสามารถในการขยายได้ของสถาปัตยกรรมของเครื่องยนต์ คงไม่แปลกใจเลยที่จะได้เห็น Flutter ลงจอดบนแพลตฟอร์มอื่นๆ ที่หลากหลายเช่นกัน ด้วยชุมชนที่กำลังเติบโต จึงเป็นช่วงเวลาที่ดีที่จะเข้าร่วม
ขั้นตอนถัดไป
- ติดตั้ง Flutter
- ทัวร์ภาษาปาเป้า
- Flutter Codelabs
- หลักสูตร Flutter Udacity
- รหัสที่มาของบทความ