![見出し画像](https://assets.st-note.com/production/uploads/images/9326976/rectangle_large_type_2_0664d98da9a66b6700b2505cdd391124.png?width=1200)
Flutter生活2日目 画面遷移とタブ
どうもFlutter生活2日目のファームノート菅原です。
本日はアプリらしくなる様に画面遷移を作ってみました。
データ周りをちゃんとSingletonにする
factoryとかあるっぽいんですがいまいち、よくわからなかったので昔からの伝統的な描き方してみてます。
import 'package:scoped_model/scoped_model.dart';
class RoutingModel extends Model {
static final RoutingModel _instance = RoutingModel();
static RoutingModel get instance {
return _instance;
}
int _tabIndex = 0;
int get tabIndex => _tabIndex;
void setTabIndex(int index) {
// First, increment the counter
_tabIndex = index;
// Then notify all the listeners.
notifyListeners();
}
}
とりあえず画面の用意
画面実装だるいのでデザイン画像を貼り付けて画面を作ります。
この辺を参考に画像をコードから扱えるようにします。
画面に貼り付けてみる
ちょっと長い画面だったりとかでスクロールちゃいたくなったりしたので、公式リファレンスのWidget Categoryから適当にそれっぽいコンポーネントを漁って、SingleChildScrollViewを発見したのでおもむろに組み込む
@override
Widget build(BuildContext context) {
return SingleChildScrollView(
child: Image.asset('assets/DashBoard.png'),
);
}
https://docs.flutter.io/flutter/widgets/SingleChildScrollView-class.html
タブコンテンツとして作った画面を配置
昨日作ったタブのコンテンツに当ててみる。
RoutingModelのSingleton化が光ります。
Storeのバケツリレーがなくなりました。
あと、なんかノッチ周りのマージンが面倒だったので、SafeAreaコンポーネントをさして適当にごまかしています。
// main.dart
Widget build(BuildContext context) {
return ScopedModel<RoutingModel>(
model: RoutingModel.instance,
child: MaterialApp(
theme: ThemeData(
primarySwatch: Colors.green,
brightness: Brightness.dark,
),
home: SafeArea(
child: Scaffold(
body: ScopedModelDescendant<RoutingModel>(
builder: (context, child, model) {
if (model.tabIndex == 0) {
return DashBoard();
}
else if(model.tabIndex == 1) {
return Search();
}
else {
return NotificationView();
}
}
),
bottomNavigationBar:BottomTab(),
)
)
)
);
下タブの実装ですね。
ModelをSingletonで叩いてる以外は大した事ないですね。
// BottomTab.dart
import 'package:flutter/material.dart';
import 'package:love_letter/store/RoutingModel.dart';
import 'package:scoped_model/scoped_model.dart';
class BottomTab extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ScopedModel<RoutingModel>(
model: RoutingModel.instance,
child: ScopedModelDescendant<RoutingModel>(
builder: (context, child, model) =>
BottomNavigationBar(
currentIndex: model.tabIndex,
onTap: (int page) => RoutingModel.instance.setTabIndex(page),
items: [
BottomNavigationBarItem(
icon: new Icon(Icons.home),
title: new Text('DashBoard'),
),
BottomNavigationBarItem(
icon: new Icon(Icons.search),
title: new Text('Search'),
),
BottomNavigationBarItem(
icon: Icon(Icons.notifications),
title: Text('Notification')
)
],
)
),
);
}
}
上タブ切り替えしたくなった
というわけでやりました。
AppBarって結構カスタムできるんですね。
タイトルにアイコンつけたいなーとか思ってたんですが、AppBarのtitleってWidgetなので、なんでもぶっこめるんですね。
bottomという引数でAppbarの下に要素を混ぜれれるんですな。
import 'package:flutter/material.dart';
class DashBoard extends StatelessWidget {
@override
Widget build(BuildContext context) {
return DefaultTabController(
length: 2,
child: Scaffold(
appBar: AppBar(
backgroundColor: Colors.transparent,
elevation: 0,
// titleにアイコン領域をぶっこんでみている
title: Row(
children: <Widget>[
Container(
color: Colors.green,
constraints: BoxConstraints(
maxHeight: 30.0,
maxWidth: 30.0,
minWidth: 15.0,
minHeight: 15.0
),
),
Text('帯広牧場')
],
),
bottom: TabBar(
tabs: [
Tab(text: "Home",),
Tab(text: "Chew"),
],
)
)
,
body: TabBarView(
children: [
SingleChildScrollView(
child: Image.asset('assets/DashBoard.png'),
),
Center(
child: Text('page2')
),
],
),
)
);
// return SingleChildScrollView(
// child: Image.asset('assets/DashBoard.png'),
// );
}
}
普通にRouterで処理する画面遷移を作ってみる
とりあえず適当な画面
import 'package:flutter/material.dart';
import 'package:love_letter/components/template/CowDetail.dart';
class NotificationView extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Center(
child: RaisedButton(
child: Text('Notification'),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => CowDetail()),
);
}
),
);
}
}
飛び先を作ってみる
import 'package:flutter/material.dart';
class CowDetail extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Second Screen"),
),
body: Center(
child: RaisedButton(
onPressed: () {
Navigator.pop(context);
},
child: Text('Go back!'),
),
),
);
}
}
だいたい、これでタブでの遷移とRouter.push,pop的な導線を作ることができました。
だんだんそれっぽくなって来ました。
ファームノートでインタラクションデザイナーやってます。 最近はFigmaとFlutterでアプリを作っています。