よくあるマテリアルデザインをFlutterで簡単に実装してみる
このノートは有料に設定していますが、続きはありません。
少しでもいいなと思ったら投げ銭していただけると嬉しいです。
完成品
完成品はこちら
前提
前提としてFlutterの開発環境を作成しておきましょう。
上の記事は英語ですが、頑張って読んでいただいて環境構築していただけたらと思います。
サーバーサイドの開発環境を作るより圧倒的に楽です。
プロジェクトを作成
プロジェクトを作成したら、色々コメントが書かれたプログラムが書かれていますが無駄なので今回は消してしまいましょう。
画面の真ん中に「Hello World」って表示します。
import 'package:flutter/material.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Flutter Demo',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
home: new MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text("Material App"),
),
body: new Center(
child: new Text(
'Hello World',
),
),
);
}
}
ListViewを作成する
まずはListViewを表示します。
表示する数は仮で10としています。
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text("Material App"),
),
body: ListView(
children: List.generate(10, (index) {
return Text("テストでーす$index");
})
)
);
}
}
ListViewの出し方はたくさんあり、要件によって使い分ける必要があります。
詳しくはCookbookをご覧ください。
カードレイアウトを実装する
いよいよ本格的にカードを作成してみます。
その準備として写真をいくつか用意しましょう。
場所はどこでもいいですが、できるだけわかりやすいところに設置しましょう。
今回はプロジェクト配下に「assets/」というのを作成しそこに写真をおきました。
そしたら、pubspec.ymlを編集します。
name: general_material_app
description: A new Flutter application.
dependencies:
flutter:
sdk: flutter
cupertino_icons: ^0.1.2
dev_dependencies:
flutter_test:
sdk: flutter
flutter:
uses-material-design: true
assets:
- assets/screen0.jpg
- assets/screen1.jpg
- assets/screen2.jpg
- assets/screen3.jpg
- assets/screen4.jpg
- assets/screen5.jpg
- assets/screen6.jpg
- assets/screen7.jpg
- assets/screen8.jpg
- assets/screen9.jpg
修正したら、上のタブから Package get ボタンを押しましょう。
上のように表示されたら完了です。
これで準備は完了です。
カードレイアウトを作成していきます。
(注意:ホットリロードをしている場合は一回実行を終了し、再実行しましょう。画像がうまく読み込めない場合があります。)
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text("Material App"),
),
body: ListView(
children: List.generate(10, (index) {
return Card(
child: Column(
children: <Widget>[
Image.asset("assets/screen$index.jpg"),
Container(
margin: EdgeInsets.all(10.0),
child: ListTile(
title: Text("screen$index.jpg"),
leading: Icon(Icons.person),
subtitle: Text("サブタイトル"),
)),
],
),
);
})));
}
}
もうこれでだいぶ形になりました。
CardViewにタップイベントを追加する
次はカードにタップイベントを追加します。
タップイベントは InkWell を使います。
CardViewをInkWellでラップしましょう。
カードの上にカーソルを置き、左のランプのマークから「wrap with new Widget」をタップしましょう
するとWidgetを挿入できるようになるので挿入しましょう。
InkWellの中にonTap属性を追加すればタップイベントを追加できます。
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text("Material App"),
),
body: ListView(
children: List.generate(10, (index) {
return InkWell(
onTap: (){
// ここに画面遷移の処理を追加する
},
child: Card(
child: Column(
children: <Widget>[
Image.asset("assets/screen$index.jpg"),
Container(
margin: EdgeInsets.all(10.0),
child: ListTile(
title: Text("screen$index.jpg"),
leading: Icon(Icons.person),
subtitle: Text("サブタイトル"),
)),
],
),
),
);
})));
}
}
画面遷移処理を実装する
画面遷移処理を実装しましょう。
まずは、画面遷移先のWidgetを作成しましょう。
main.dartの下に MyHomePageDetail という名前でクラスを作成します。
作成した結果こんな感じ
import 'package:flutter/material.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Flutter Demo',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
home: new MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text("Material App"),
),
body: ListView(
children: List.generate(10, (index) {
return InkWell(
onTap: (){
// ここに画面遷移の処理を追加する
},
child: Card(
child: Column(
children: <Widget>[
Image.asset("assets/screen$index.jpg"),
Container(
margin: EdgeInsets.all(10.0),
child: ListTile(
title: Text("screen$index.jpg"),
leading: Icon(Icons.person),
subtitle: Text("サブタイトル"),
)),
],
),
),
);
})));
}
}
class MyHomePageDetail extends StatefulWidget {
@override
_MyHomePageDetailState createState() => new _MyHomePageDetailState();
}
class _MyHomePageDetailState extends State<MyHomePageDetail> {
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text("Material App"),
),
body: Center(
child: Text("画面遷移できました"),
));
}
}
そこから画面遷移処理を書いていきます。
先ほど InkWell属性にタップイベントを設定したのでその中に画面遷移処理を作ります。
return InkWell(
onTap: () {
Navigator.push(context, MaterialPageRoute(builder: (context) => MyHomePageDetail()));
},
これで画面遷移できるはずです。
次に画面にタップしたデータをパラメータとして渡しましょう。
return InkWell(
onTap: () {
Navigator.push(context, MaterialPageRoute(builder: (context) => MyHomePageDetail("assets/screen$index.jpg")));
},
こんな感じでパラメーターを渡して、
class MyHomePageDetail extends StatefulWidget {
MyHomePageDetail(this._imageName);
final String _imageName;
@override
_MyHomePageDetailState createState() => new _MyHomePageDetailState(_imageName);
}
class _MyHomePageDetailState extends State<MyHomePageDetail> {
_MyHomePageDetailState(this._imageName);
final String _imageName;
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text("Material App"),
),
body: Center(
child: Text("画面遷移できました$_imageName"),
));
}
}
こんな感じで受け取ります。
あとは割愛というか、さわっとコード残しておきます。
class _MyHomePageDetailState extends State<MyHomePageDetail> {
_MyHomePageDetailState(this._imageName);
final String _imageName;
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text("Material App"),
),
body: Center(
child: Column(
children: <Widget>[
Image.asset(_imageName),
Container(
child: ListTile(
title: Text(_imageName),
leading: Icon(Icons.person),
subtitle: Text("お写真ですこれは"),
),
)
],
),
));
}
}
これで完成です。
ソースコードはこちら
宣伝
少しでも投げ銭いただけると次書くモチベーションが上がるのでお願いいたします。
Twitter↓ これからもFlutterについて呟くのフォローお願いします。
ここから先は
¥ 300
投げ銭はいりません。それより無料でできる拡散をしてください!! 感想をツイートしていただけることが一番嬉しいです!!