2
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【Flutter】シンプルなheaderとfooterを作成する

Posted at

ProviderパターンでModelを作成してheaderとfooterのあるアプリを作成します
完成形は以下のような形

(gifなのでぼやぼやですが、実際は高画質です)

footer(BottomNavigationBar)を押した場所によって、headerの文字とbodyに表示されるものを変えています。

ファイル構造

今回はmodelを使います。

lib
├── header.dart
├── main.dart
├── models
│   └── bottom_navigation_model.dart
└── routes
    ├── home.dart
    ├── profile.dart
    └── settings.dart

lib/main.dart

参考記事なんかを読んでいるとBottomNavigationBarItemlabelの部分をtitleにしてText()で描画している記事が多いですが、それはv1.19.0からは推奨されていないようです。

@Deprecated('Use "label" instead, as it allows for an improved text-scaling experience. ' 'This feature was deprecated after v1.19.0.'), final

参考:BottomNavigationBarItem class - widgets library - Dart API


lib/main.dart
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'models/bottom_navigation_model.dart';
import 'routes/profile.dart';
import 'routes/home.dart';
import 'routes/settings.dart';

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

class MyApp extends StatelessWidget {
  final List _pageList = [
    Profile(),
    Home(),
    Settings(),
  ];
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutterの練習', //アプリの名前
      theme: ThemeData(
        primaryColor: Colors.green,
      ),
      home: ChangeNotifierProvider<BottomNavigationModel>(
        create: (_) => BottomNavigationModel(),
        child:
            Consumer<BottomNavigationModel>(builder: (context, model, child) {
          return Scaffold(
            // appBar: Header(), //各ファイルでHeader()を実行するのでいらない
            body: _pageList[model.currentIndex], //中身を描画
            //footer部分
            bottomNavigationBar: BottomNavigationBar(
              type: BottomNavigationBarType.fixed,
              items: [
                BottomNavigationBarItem(
                  icon: Icon(Icons.person),
                  label: 'プロフィール',
                ),
                BottomNavigationBarItem(
                  icon: Icon(Icons.home),
                  label: 'ホーム',
                ),
                BottomNavigationBarItem(
                  icon: Icon(Icons.settings),
                  label: '設定',
                ),
              ],
              currentIndex: model.currentIndex,
              onTap: (index) {
                model.currentIndex = index;
              },
              selectedItemColor: Colors.pinkAccent, //選んだ物の色
              unselectedItemColor: Colors.black45, //選んでない物の色
            ),
          );
        }),
      ),
    );
  }
}

lib/header.dart

Icons.addを記述していますが、特に意味はありません。

lib/header.dart
import 'package:flutter/material.dart';

class Header extends StatelessWidget with PreferredSizeWidget {
  final String headerTitle;
  Header({this.headerTitle}); //ヘッダータイトルを変更できるようにする
  @override
  Size get preferredSize => Size.fromHeight(kToolbarHeight);

  @override
  Widget build(BuildContext context) {
    return AppBar(
      title: Text(headerTitle),
      actions: [
        Padding(
          padding: const EdgeInsets.all(8.0),
          child: IconButton(
            icon: Icon(Icons.add),
            onPressed: () {
              //押したときの処理
            },
          ),
        )
      ],
    );
  }
}

lib/models/bottom_navigation_model.dart

lib/models/bottom_navigation_model.dart
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

class BottomNavigationModel extends ChangeNotifier {
  int _currentIndex = 1; //最初に表示される画面

  // getterとsetterを指定しています
  // setのときにnotifyListeners()を呼ぶことアイコンタップと同時に画面を更新しています。
  get currentIndex => _currentIndex;

  set currentIndex(int index) {
    _currentIndex = index;
    notifyListeners(); // View側に変更を通知
  }
}

lib/routes/profile.dart

lib/routes/profile.dart
import 'package:flutter/material.dart';
import '../header.dart';

class Profile extends StatelessWidget {
  final String screenName = 'プロフィール'; //headerに表示される名前
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: Header(headerTitle: screenName),
      body: Center(
        child: Text(screenName),
      ),
    );
  }
}

lib/routes/home.dart

lib/routes/home.dart
import 'package:flutter/material.dart';
import '../header.dart';

class Home extends StatelessWidget {
  final String screenName = 'ホーム'; //headerに表示される名前
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: Header(headerTitle: screenName),
      body: Center(
        child: Text(screenName),
      ),
    );
  }
}

lib/routes/settings.dart

lib/routes/settings.dart
import 'package:flutter/material.dart';
import '../header.dart';

class Settings extends StatelessWidget {
  final String screenName = '設定'; //headerに表示される名前
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: Header(headerTitle: screenName),
      body: Center(
        child: Text(screenName),
      ),
    );
  }
}

参考

Flutter: シンプルでStatelessなBottomNavigationBarを作ってみた話
FlutterでTwitterクライアント作成②フッター追加

2
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?