web analytics

รู้จักกับ Navigation Rail Widget ใน Flutter

สวัสดีครับ วันนี้มาลองเล่นหนึ่งในของใหม่ใน Flutter 1.17 ที่ปล่อยออกมาที่ widget มาใหม่ตัวนึง น่าสนใจสำหรับ material design เรียกว่า Navigation Rail โดย Google Team ซึ่งมันก็คือการแสดงเมนูแบบนึงที่เหมาะกับการแสดงผลที่เมนูต้องสลับไปสลับมาระหว่าง Desktop กับ Mobile บล็อกนี้ ผมก็จะลองเล่นว่าเจ้า Navigation rail มันมีอะไรให้ใช้งานบ้างนะ

เริ่มต้น

การใช้งาน Navigation Rail เท่าที่ลองเล่น ก็คล้ายๆกับ widget ตัวอื่นๆ นะ ก็คือ จะมีตัวหลักกับตัวลูก ตัวหลักคือ NavigationRail และก็มีลูกๆ คือเมนูย่อยๆ เรียกว่า NavigationRailDestination เราก็แค่กำหนด icon , label ให้มัน

    return Scaffold(
      appBar: AppBar(
        title: Text("Hello World"),
      ),
      body: NavigationRail(
          selectedIndex: _selectedIndex,
          onDestinationSelected: (int index) {
            setState(() {
              _selectedIndex = index;
            });
          },
          labelType: NavigationRailLabelType.selected,
          destinations: [
            NavigationRailDestination(
              icon: Icon(Icons.favorite_border),
              selectedIcon: Icon(Icons.favorite),
              label: Text('First'),
            ),
            NavigationRailDestination(
              icon: Icon(Icons.bookmark_border),
              selectedIcon: Icon(Icons.book),
              label: Text('Second'),
            ),
            NavigationRailDestination(
              icon: Icon(Icons.star_border),
              selectedIcon: Icon(Icons.star),
              label: Text('Third'),
            ),
          ],
      )
    );

ลองรัน

ลองดู property ต่างๆ ที่สามารถใช้ได้

property ที่น่าจะได้ใช้บ่อยๆ คือ labelType มีให้เลือก 3 แบบ คือ none , selected , all

การแสดงผลก็คือจะตามชื่อเลย

แล้วก็การจัดตำแหน่ง เรียกว่า group alignment มีค่าได้ระหว่าง -1 ถึง 1 โดยค่า 0 คือตรงกลาง

  /// If [groupAlignment] is -1.0, then the items are aligned to the top. If
  /// [groupAlignment] is 0.0, then the items are aligned to the center. If
  /// [groupAlignment] is 1.0, then the items are aligned to the bottom.
  ///
  /// The default is -1.0.

อีกอันที่น่าสนใจ คือ extended โดยมันจะเป็นการขยาย NavigationRail ให้เต็ม parent และแสดง label แต่ว่าเราจะต้องกำหนดให้ labelType เป็น none เท่านั้น โดยสามารถกำหนดความกว้างด้วย minExtendedWidth

        NavigationRail(
          extended: true,
          labelType: NavigationRailLabelType.none,
          ..

ซึ่งเจ้า extended น่าจะเป็น mode ที่เอาไว้ใช้งานร่วมกับ action พวก toggle ต่างๆ เช่น ผมทำปุ่ม menu หากกดก็จะ toggle ค่า extended ของ NavigationRail

  int _selectedIndex = 0;
  bool _extendNavigationRail = false;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        leading: IconButton(icon: Icon(Icons.menu,color: Colors.white),onPressed: (){
          setState(() {
            _extendNavigationRail = !_extendNavigationRail ;
          });
        },),
        title: Text("Hello World"),
      ),
      body: Row(children: <Widget>[
        NavigationRail(
          selectedIndex: _selectedIndex,
          onDestinationSelected: (int index) {
            setState(() {
              _selectedIndex = index;
            });
          },
          extended: _extendNavigationRail ,           
          labelType: NavigationRailLabelType.none,
          ..

นอกจากนี้ก็มี leading , trailing ให้เราสามารถเพิ่ม widget ไปที่หัวและท้ายของ
NavigationRail ด้วย

NavigationRail(
          leading: Text("leading",textAlign: TextAlign.center),
          trailing: Text("trailing",textAlign: TextAlign.center),
          ...

สรุป

บล็อกนี้ก็เป็นการลองเล่นตัว Navigation Rail widget แบบคร่าวๆ ที่มาพร้อมกับ Flutter 1.17 ครับ น่าจะพอเห็นว่ามันทำอะไรได้บ้าง จริงๆเมนูแบบนี้ผมเคยเห็นบ่อยๆใน Windows App UWP เห็นด้วยที่มันเหมาะกับเอามาใช้ร่วมกับ Desktop ที่อนาคตเราน่าจะได้เอามาใช้ใน Flutter Desktop กัน

สำหรับใครที่ยังไม่ได้อ่าน Flutter 1.17 release ของ Flutter Team ลองอ่านได้นะ
https://medium.com/flutter/announcing-flutter-1-17-4182d8af7f8e

และสามารถลองเล่น Navigation Rail ใน Dart Pad ที่ Flutter ทำไว้ให้ได้ในนี้
https://dartpad.dev/b9c6cd345fd1cff643353c1f4902f888