HyunJun 기술 블로그

Navigation Pattern, Navigation Rail, Navigation Drawer 본문

Flutter

Navigation Pattern, Navigation Rail, Navigation Drawer

공부 좋아 2023. 7. 17. 09:20
728x90
반응형

1. Navigation Rail

Navigation Rail은 Flutter에서 사용자 인터페이스(UI)를 구성하는 하나의 내비게이션 패턴이다. 주로 앱의 사이드 바(Side Bar)나 드로어(Drawer)에 위치하며, 수직 방향으로 여러 개의 목적지(destination)를 나열하여 사용자가 쉽게 화면을 전환하고 다양한 기능에 접근할 수 있도록 도와준다. 각 목적지는 아이콘과 레이블로 표시되며, 사용자가 터치하면 해당 목적지로 이동하거나 해당 기능을 수행할 수 있다. Navigation Rail은 주로 머티리얼 디자인 스타일의 앱에서 사용되며, iOS 스타일의 앱에서는 CupertinoNavigationRail이 사용될 수 있다.

 

Navigation Rail을 오른쪽에 두고 싶은 경우 단순히 Row 레이아웃을 잡아주면 된다.

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _selectedIndex = 0;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Navigation Rail Example'),
      ),
      body: Row(
        children: [
          // Navigation Rail
          NavigationRail(
            backgroundColor: Color.fromRGBO(241, 239, 239, 1.0),
            selectedIndex: _selectedIndex,
            onDestinationSelected: (int index) {
              setState(() {
                _selectedIndex = index;
              });
            },
            labelType: NavigationRailLabelType.selected,
            destinations: [
              NavigationRailDestination(
                icon: Icon(Icons.home),
                selectedIcon: Icon(Icons.home_filled),
                label: Text('Home'),
              ),
              NavigationRailDestination(
                icon: Icon(Icons.search),
                selectedIcon: Icon(Icons.search),
                label: Text('Search'),
              ),
              NavigationRailDestination(
                icon: Icon(Icons.favorite),
                selectedIcon: Icon(Icons.favorite),
                label: Text('Favorites'),
              ),
            ],
          ),
          // Main content for each destination can be shown here.
          // For simplicity, let's show just a placeholder text.
          Expanded(
            child: Center(
              child: _buildSelectedScreen(_selectedIndex),
            ),
          ),
        ],
      ),
    );
  }

  Widget _buildSelectedScreen(int selectedIndex) {
    switch (selectedIndex) {
      case 0:
        return HomeScreen();
      case 1:
        return SearchScreen();
      case 2:
        return FavoritesScreen();
      default:
        return Container();
    }
  }
}

class HomeScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      child: Center(
        child: Text('Home Screen', style: TextStyle(fontSize: 24)),
      ),
    );
  }
}

class SearchScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      child: Center(
        child: Text('Search Screen', style: TextStyle(fontSize: 24)),
      ),
    );
  }
}

class FavoritesScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      child: Center(
        child: Text('Favorites Screen', style: TextStyle(fontSize: 24)),
      ),
    );
  }
}

2. Navigation Drawer

내비게이션 드로어(Drawer)는 화면 위를 덮는 형태의 화면을 의미한다. 일반적으로 앱의 메인 화면 위에 슬라이드 업되어 나타나며, 사용자가 드로어를 보고 선택할 수 있다. 사용자가 왼쪽에서 오른쪽으로 스와이프 하거나 특정 버튼을 눌러 드로어를 호출하면, 드로어가 메인 화면 위로 나타난다. 드로어가 화면 위를 덮는 형태로 나타남으로써, 메인 화면의 일부가 가려지면서 드로어 내의 메뉴나 기능에 접근할 수 있게 된다. 사용자는 원하는 항목을 선택한 후 드로어를 다시 닫아서 메인 화면으로 돌아갈 수 있다. 이러한 내비게이션 패턴은 효율적이고 사용자 친화적인 경험을 제공하기 위해 많이 사용된다.

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _selectedIndex = 0;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Navigation Drawer Example'),
      ),
      drawer: Drawer(
        child: ListView(
          padding: EdgeInsets.zero,
          children: [
            DrawerHeader(
              decoration: BoxDecoration(
                color: Colors.blue,
              ),
              child: Text(
                'Drawer Header',
                style: TextStyle(
                  color: Colors.white,
                  fontSize: 24,
                ),
              ),
            ),
            ListTile(
              leading: Icon(Icons.home),
              title: Text('Home'),
              onTap: () {
                _selectDrawerItem(0);
              },
            ),
            ListTile(
              leading: Icon(Icons.search),
              title: Text('Search'),
              onTap: () {
                _selectDrawerItem(1);
              },
            ),
            ListTile(
              leading: Icon(Icons.favorite),
              title: Text('Favorites'),
              onTap: () {
                _selectDrawerItem(2);
              },
            ),
          ],
        ),
      ),
      body: Center(
        child: _buildSelectedScreen(_selectedIndex),
      ),
    );
  }

  void _selectDrawerItem(int index) {
    setState(() {
      _selectedIndex = index;
      Navigator.pop(context); // 드로어를 닫습니다.
    });
  }

  Widget _buildSelectedScreen(int selectedIndex) {
    switch (selectedIndex) {
      case 0:
        return HomeScreen();
      case 1:
        return SearchScreen();
      case 2:
        return FavoritesScreen();
      default:
        return Container();
    }
  }
}

class HomeScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(

      child: Center(
        child: Text('Home Screen', style: TextStyle(fontSize: 24)),
      ),
    );
  }
}

class SearchScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(

      child: Center(
        child: Text('Search Screen', style: TextStyle(fontSize: 24)),
      ),
    );
  }
}

class FavoritesScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(

      child: Center(
        child: Text('Favorites Screen', style: TextStyle(fontSize: 24)),
      ),
    );
  }
}

728x90
반응형
Comments