SnackBar เป็น widget ที่เราสามารถใช้สำหรับแสดง popup ข้อความ
แบบย่อหรือการแจ้งเตือนถึงการกระทำบางอย่างๆ ที่เพิ่งเกิดขึ้น หรือเพื่อตัดสินใจ
จะแสดงขึ้นตรงขอบด้านล่างของหน้าจอแอพ ก่อนลงไปในรายละเอียด ต้องขอ
แจ้งก่อนว่า เราจะใช้เนื้อหาต่อเนื่องจากบทความตอนที่แล้ว
การใช้งาน BottomNavigationBar ใน Flutter เบื้องต้น http://niik.in/961
https://www.ninenik.com/content.php?arti_id=961 via @ninenik
โดยจะใช้ในส่วนของหน้า home สำหรับทดสอบประกอบการทำงานและการใช้งาน
การใช้งาน SnackBar Widget
รูปแบบการใช้งาน snackbar เช่น สมมติมีรายการที่แสดงบนหน้าจอ แล้วเราทำการ
เลือกรายการนั้นและลบออก เราอาจจะต้องการแจ้งว่าทำการลบรายการนั้นแล้ว หรืออาจจะ
แจ้งข้อความว่าลบรายการนั้นไปแล้วและมีปุ่มให้ทำคำสั่ง ยกเลิก การลบขึ้นมาพร้อมข้อความ
แจ้งก็ได้ เพื่อเป็นทางเลือกให้ผู้ใช้ตัดสินใจอีกครั้ง
ในส่วนของ snackbar นอกจากจะแสดงเป็นข้อความแล้ว ยังสามารถใส่ widget อื่นๆ เพิ่ม
ลงไปได้ แต่ต้องคำนึงถึงพื้นที่การใช้งาน เพราะจะเป็นขอบเขตจำกัดเท่านั้น
เราจะทดสอบแสดงข้อความใน snackbar ด้วยรูปแบบอย่างง่ายดังนี้คือ เราจะสร้างปุ่มในหน้า
home แล้วเมื่อคลิกปุ่ม ก็ให้แสดง ข้อความใน snackbar
class _HomeState extends State<Home> { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Home'), ), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ Text('Home Screen'), ElevatedButton( onPressed: () { // เมื่อกดที่ปุ่ม // กำหนดรูปแบบการใช้งาน snackbar final snackBar = SnackBar( content: const Text('Yay! A SnackBar!'), // แสดงข้อความ action: SnackBarAction( label: 'Undo', onPressed: () { // ทำคำสั่งถ้ากดที่ข้อความใน action }, ), ); // แสดงข้อความ snackbar โดยเรียกใช้งานผ่าน ScaffoldMessenger ScaffoldMessenger.of(context).showSnackBar(snackBar); }, child: const Text('Show SnackBar'), ), ], ) ), ); } }
ผลลัพธ์
เราสร้างตัวแปรชื่อ snackBar เป็น final ขึ้นมาแล้วเรียกใช้งาน SnackBar widget กำหนดรูปแบบตาม
ต้องการ ในตัวอย่างกำหนดแค่ข้อความ และส่วนของ action เสมือนเป็นปุ่มข้อความ ให้ผู้ใช้เลือกที่จะกด
เพื่อทำคำสั่งเพิ่มเติม หลังจากนั้น ก็เรียกใช้งาน snackBar ผ่าน ScaffoldMessenger ซึ่งเป็นส่วนหนึ่งของ
Scaffold widget
จะเห็นว่ารูปแบบการใช้งาน ง่ายๆ ไม่ยุ่งยากซับซ้อน
ลองมาปรับรูปแบบการแสดงส่วนของ snackbar เพิ่มเติม ดังนี้
// กำหนดรูปแบบการใช้งาน snackbar final snackBar2 = SnackBar( content: Row( // แสดงข้อมูลอื่นๆ นอกจากข้อความอย่างเดียว children: [ Icon(Icons.info_rounded,color: Colors.yellow,), // ใส่ไอคอน SizedBox(width: 10), // เพิ่มกล่องช่องว่าง Expanded( child: Text('ทำรายการเรียบร้อยแล้ว!'), ), ], ), action: SnackBarAction( label: 'ดูเพิ่มเติม', onPressed: () { // ทำคำสั่งถ้ากดที่ข้อความใน action }, ), );
ผลลัพธ์
เนื่องจากว่าเรามีการใช้งาน BottomNavigationBar จึงเห็นว่าตัว SnackBar จะอยู่ด้านบนต่อขึ้นมาอีกที
ดูตัวอย่างการกำหนดค่าเพิ่มเติม
// กำหนดรูปแบบการใช้งาน snackbar final snackBar3 = SnackBar( content: Row( // แสดงข้อมูลอื่นๆ นอกจากข้อความอย่างเดียว children: [ Icon(Icons.info_rounded,color: Colors.yellow,), // ใส่ไอคอน SizedBox(width: 10), // เพิ่มกล่องช่องว่าง Expanded( child: Text('ทำรายการเรียบร้อยแล้ว!'), ), ], ), duration: const Duration(milliseconds: 3000), // กำหนดเวลาแสดง 3 วินาที width: 300.0, // กำหนดความกว้่าง padding: const EdgeInsets.symmetric( horizontal: 8.0, ), behavior: SnackBarBehavior.floating, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(10.0), ), action: SnackBarAction( label: 'ดูเพิ่มเติม', onPressed: () { // ทำคำสั่งถ้ากดที่ข้อความใน action }, ), );
ผลลัพธ์
ดูการกำหนดคุณสมบัติอื่นๆ เพิ่มเติมได้ที่ SnackBar Widget
เราสามารถแยกออกมาเป็นฟังก์ชั่นเพื่อให้เรียกใช้งานได้สะดวก และรองรับการส่งค่าตามต้องการ
ดูตัวอย่างตามโค้ดด้านล่าง
class _HomeState extends State<Home> { // สร้าง ScaffoldMessengerState key ให้สามารถเรียกใช้งาน ใน widget ที่กำหนดได้ final GlobalKey<ScaffoldMessengerState> scaffoldMessengerKey = GlobalKey<ScaffoldMessengerState>(); @override Widget build(BuildContext context) { return ScaffoldMessenger( key: scaffoldMessengerKey, // อ้างอิงค่า key ที่กำหนด child: Scaffold( appBar: AppBar( title: Text('Home'), ), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ Text('Home Screen'), ElevatedButton( onPressed: (){ showSnack('Hi'); // เรียกใช้งานฟังก์ชั่น }, child: const Text('Show SnackBar'), ), ], ) ), ), ); } // ฟังกชั่นสำหรับใช้งาน SnackBar void showSnack(String title) { // กำหนดรูปแบบการใช้งาน snackbar final snackBar = SnackBar( content: Row( // แสดงข้อมูลอื่นๆ นอกจากข้อความอย่างเดียว children: [ Icon(Icons.info_rounded,color: Colors.yellow,), // ใส่ไอคอน SizedBox(width: 10), // เพิ่มกล่องช่องว่าง Expanded( child: Text(title), // รับค่าข้อความจาก parameter มาแสดง ), ], ), duration: const Duration(milliseconds: 3000), // กำหนดเวลาแสดง 3 วินาที width: 300.0, // กำหนดความกว้่าง padding: const EdgeInsets.symmetric( horizontal: 8.0, ), behavior: SnackBarBehavior.floating, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(10.0), ), action: SnackBarAction( label: 'ดูเพิ่มเติม', onPressed: () { // ทำคำสั่งถ้ากดที่ข้อความใน action }, ), ); scaffoldMessengerKey.currentState!.showSnackBar(snackBar); } }
ผลลัพธ์
เราสามารถกำหนดไห้ SnackBar แสดงจนกว่ากดที่ปุ่มข้อความใน action โดยกำหนดรูปแบบ
ของเวลาใน duration เป็นดังนี้
duration: const Duration(days: 365), // duration: const Duration(milliseconds: 1500), // กำหนดเวลาแสดง 1.5 วินาที // duration: const Duration(seconds: 3), // กำหนดเวลาแสดง 3 วินาที
ปกติถ้าไม่กำหนด หรือกำหนดเป็นหน่วยมิลลิวินาที ตัว SnackBar ก็จะแสดงชั่วขณะ หรือตามที่กำหนด
เท่านั้น แต่หากเรากำหนดเป็นค่า days: 365 ก็เหมือนเป็นการบอกว่า เปิดค้างไว้ตลอด จนกว่าจะกดที่ปุ่มข้อ
ความใน action ตัว SnackBar ถึงจะหายไป การกำหนดในลักษณะนี้ก็เพื่อเป็นการยืนยันว่าผู้ใช้ได้เห็นข้อความ
นี้และทำการใดๆ ต่อไปตามที่กำหนด หรือเป็นการให้ผู้ใช้โต้ตอบกับ SnackBar นั่นเอง แทนที่จะหายไปอัตโนมัติ
การแสดง SnackBar จะแสดงตามลำดับการเรียกใช้งาน สมมติเรากดซ้ำที่ปุ่มเรียกใช้งาน 3 ครั้ง ตัว SnackBar
ก็จะแสดง ซ้ำ 3 ครั้งแต่ละครั้งก็จะใช้เวลา 3 วินาที ตามที่กำหนด
เราสามารถกำหนดให้ ทุกการเรียกใช้งาน SnackBar สามารถแสดงต่อเนื่องทันที โดยไม่ต้องรอจนครบตาม
เวลาที่กำหนด โดยใช้คำสั่ง removeCurrentSnackBar() ก่อนแล้วค่อยเรียกใช้คำสั่ง showSnackBar()
ตัวอย่างการใช้งานกับ ScaffoldMessenger ก็จะเป็นประมาณนี้
ScaffoldMessenger.of(context) ..removeCurrentSnackBar() // ปิดตัวที่แสดงอยู่ก่อนทันที ..showSnackBar(snackBar); // แล้วค่อยแสดงตัวใหม่
หรือกรณีใช้กับในฟังก์ชั่น ตัวอย่างด้านบน ก็จะเป็น
scaffoldMessengerKey.currentState! ..removeCurrentSnackBar() ..showSnackBar(snackBar);
เราสามารถใช้คำสั่ง hideCurrentSnackBar() แทนได้ แต่จะให้ความรู้สึกเหมือนมี animation มากกว่า
กรณีใช้เป็น removeCurrentSnackBar()
ดูการกำหนดคุณสมบัติอื่นๆ เพิ่มเติมได้ที่ SnackBar Widget