【2通り紹介】Flutterでサイドバーを作成する方法

Flutter
 

はじめに

最近Flutterを学んでいます。

今日はFlutterでサイドバーを作ってみました。

公式にて一つのサイドバーを紹介していますが、少し変わり種のサイドバーも紹介しようと思います。

サイドバー2選

1つ目

1つ目はよくあるサイドバーの紹介です。

以下の動画をご覧ください。

左上のMenuボタンを押下することで左側からサイドバーが出現します。

ソースはこちらから

import 'package:flutter/material.dart';

void main() {
  runApp(const MenuTestPage());
}

class MenuTestPage extends StatelessWidget {
  const MenuTestPage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Drawer Test Page'),
      ),
      body: Center(
        child: Text('Hey!'),
      ),
      drawer: Drawer(
        child: ListView(
          children: [
            DrawerHeader(
              decoration: BoxDecoration(color: Colors.lightBlue),
              child: Text('Test App'),
            ),
            ListTile(
              title: Text('item1'),
              onTap: () {},
            ),
            ListTile(
              title: Text('item2'),
              onTap: () {},
            ),
          ],
        ),
      ),
    );
  }
}

使用しているWidgetまとめ

Drawer

サイドバーを出現させるためのWidget。

ListViewと組み合わせてサイドバーのメニューを表示させるのが一般的な使い方みたい。

ListView

スクロールウィジェットである。

スクロール方向に無限数だけ表示させることができるみたい。

2つ目

2つ目はちょっとイカしたUIのサイドバーです。

こちらは左上のMenuボタンを押下することでアニメーションのように左からスーッとサイドバーが出現してきます。

import 'package:flutter/material.dart';

class MenuDashboardPage extends StatefulWidget {
  const MenuDashboardPage({Key? key}) : super(key: key);

  @override
  State<MenuDashboardPage> createState() => _MenuDashboardPageState();
}

class _MenuDashboardPageState extends State<MenuDashboardPage> {
  bool isCollapsed = true;
  double screenWidth = 0, screenHeight = 0;
  final Duration duration = const Duration(milliseconds: 300);

  @override
  Widget build(BuildContext context) {
    Size size = MediaQuery.of(context).size;
    screenHeight = size.height;
    screenWidth = size.width;
    return Scaffold(
      backgroundColor: Colors.blueGrey[600],
      body: Stack(
        children: <Widget>[
          menu(),
          dashboard(context),
        ],
      ),
    );
  }

  Widget dashboard(context) {
    return AnimatedPositioned(
      duration: duration,
      top: isCollapsed ? 0 : 0.2 * screenHeight,
      bottom: isCollapsed ? 0 : 0.05 * screenWidth,
      left: isCollapsed ? 0 : 0.6 * screenWidth,
      right: isCollapsed ? 0 : -0.4 * screenWidth,
      child: Material(
        animationDuration: duration,
        borderRadius: BorderRadius.all(Radius.circular(40)),
        elevation: 8,
        color: Colors.blueGrey[600],
        child: Container(
          padding: EdgeInsets.only(left: 16, right: 16, top: 48),
          child: Column(
            children: <Widget>[
              Row(
                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                mainAxisSize: MainAxisSize.max,
                children: [
                  InkWell(
                    onTap: () {
                      setState(() {
                        isCollapsed = !isCollapsed;
                      });
                    },
                    child: Icon(
                      Icons.menu,
                      color: Colors.white,
                    ),
                  ),
                  Text(
                    'My Cards',
                    style: TextStyle(
                      color: Colors.white,
                      fontSize: 24,
                    ),
                  ),
                  Icon(
                    Icons.settings,
                    color: Colors.white,
                  ),
                ],
              ),
              SizedBox(
                height: 50,
              ),
              Container(
                height: 200,
                child: PageView(
                  controller: PageController(viewportFraction: 0.8),
                  scrollDirection: Axis.horizontal,
                  pageSnapping: true,
                  children: [
                    Container(
                      margin: EdgeInsets.symmetric(
                        horizontal: 8,
                      ),
                      color: Colors.redAccent,
                      width: 100,
                    ),
                    Container(
                      margin: EdgeInsets.symmetric(
                        horizontal: 8,
                      ),
                      color: Colors.blueAccent,
                      width: 100,
                    ),
                    Container(
                      margin: EdgeInsets.symmetric(
                        horizontal: 8,
                      ),
                      color: Colors.greenAccent,
                      width: 100,
                    ),
                  ],
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }

  Widget menu() {
    return Padding(
      padding: const EdgeInsets.only(left: 16.0),
      child: Align(
        alignment: Alignment.centerLeft,
        child: Column(
          mainAxisAlignment: MainAxisAlignment.spaceAround,
          mainAxisSize: MainAxisSize.min,
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Text(
              'Dashboard',
              style: TextStyle(color: Colors.white, fontSize: 22),
            ),
            SizedBox(
              height: 10.0,
            ),
            Text(
              'Messages',
              style: TextStyle(color: Colors.white, fontSize: 22),
            ),
            SizedBox(
              height: 10.0,
            ),
            Text(
              'Utility Bills',
              style: TextStyle(color: Colors.white, fontSize: 22),
            ),
            SizedBox(
              height: 10.0,
            ),
            Text(
              'Funds Transfer',
              style: TextStyle(color: Colors.white, fontSize: 22),
            ),
            SizedBox(
              height: 10.0,
            ),
            Text(
              'Branches',
              style: TextStyle(color: Colors.white, fontSize: 22),
            ),
          ],
        ),
      ),
    );
  }
}

使用しているWidgetまとめ

AnimatedPositioned

指定した子コンポーネントのポジションを移動させる。(top, bottom, left, rightで指定が可能)

Stackとの組み合わせで使用する必要がある。

InkWell

このウィジェットでラップしたウィジェットをいい感じのボタンに変更するイメージ。

onTapなどでイベントの設定もすることが可能

コメント

タイトルとURLをコピーしました