📝
Flutter超入門編を終えての簡単なUI作成
はじめに
Flutter大学 Flutter超入門編を学び終えたので、学んだことを活かし簡単なUIを作りましたの記事にしました。
コードが汚かったり、書き方が間違っている箇所もあると思いますが優しい目で見ていただけると助かります🙇♂️
今回作るもの
Flutter大学 youtube Flutter超入門編で学んだこと + Flutter超入門編では出なかった簡単なWidgetを組み合わせたUI作成
ファーストページ
first_page.dart
import 'package:coriander/second_page.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
class FirstPage extends StatelessWidget {
String titleText = 'Second Page';
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: const Color.fromRGBO(240, 240, 240, 1),
appBar: AppBar(
centerTitle: false,
backgroundColor: Colors.black54,
title: const Text(
"Flutter入門編総復習",
style: TextStyle(fontWeight: FontWeight.bold),
),
actions: <Widget>[
IconButton(
onPressed: () {
showDialog(
context: context,
builder: (context) {
return const AlertDialog(
title: Text(
'メニューバーが押されました !',
textAlign: TextAlign.center,
style: TextStyle(fontSize: 16),
));
},
);
},
icon: const Icon(Icons.menu)),
IconButton(
onPressed: () {
showDialog(
context: context,
builder: (context) {
return const AlertDialog(
title: Text(
'設定ボタンが押されました !',
textAlign: TextAlign.center,
style: TextStyle(fontSize: 16),
));
},
);
},
icon: const Icon(Icons.settings)),
const SizedBox(width: 16),
],
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Image.network(
"https://example.com/flutter-mobile-web-desktop.jpg"),
const SizedBox(height: 24),
const Text("Flutter Demo App",
style: TextStyle(
fontSize: 16,
color: Colors.black54,
fontWeight: FontWeight.bold)),
SizedBox(height: 20),
TextField(
decoration: const InputDecoration(
border: OutlineInputBorder(),
labelText: 'SecondPage title',
),
onChanged: (text) {
titleText = text;
},
),
SizedBox(height: 16),
SizedBox(
height: 40,
width: 180,
child: ElevatedButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => SecondPage(titleText)),
);
},
style: ElevatedButton.styleFrom(
primary: Colors.black54,
shape: const StadiumBorder(),
),
child: const Text("Submit"),
),
)
],
),
),
),
floatingActionButton: FloatingActionButton(
backgroundColor: Colors.black54,
onPressed: () {
showDialog(
context: context,
builder: (context) {
return const AlertDialog(
title: Text(
'すでにホームです!',
textAlign: TextAlign.center,
style: TextStyle(fontSize: 16),
));
},
);
},
tooltip: 'Increment',
child: const Icon(Icons.home),
),
);
}
}
内容
- appBar
- メニューアイコン・設定アイコン、各々のダイアログを表示
- body
- Columnで縦に表示
- テキストフィールドに入力した値がセカンドページのタイトルに
- Submitボタンでセカンドページに画面遷移
- floatingActionButton
- ホームアイコンを押すとダイアログ表示
セカンドページ
second_page.dart
import 'dart:ffi';
import 'package:coriander/first_page.dart';
import 'package:coriander/main.dart';
import 'package:coriander/third_page.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
class SecondPage extends StatelessWidget {
SecondPage(this.titleText);
String titleText;
// 記事の配列
final List<Map<String, String>> articles = [
{
'image': 'https://exaple/canada01.jpg',
'text': 'カナディアンロッキー',
},
{
'image': 'https://exaple/aurora02.jpg',
'text': 'イエローナイフのオーロラ',
},
{
'image': 'https://exaple/img03.jpg',
'text': 'モニュメントバレー',
},
{
'image': 'https://exaple/uyuni01.jpg',
'text': 'ウユニ塩湖',
},
{
'image': 'https://exaple/img05.jpg',
'text': 'ブルーホール',
},
{
'image': 'https://exaple/img06.jpg',
'text': 'マウナ・ケア',
},
{
'image': 'https://exaple/antelope01.jpg',
'text': 'アンテロープキャニオン',
},
{
'image': 'https://exaple/iguazu02.jpg',
'text': 'イグアスの滝',
},
{
'image':
'https://exaple/machupicchu02.jpg',
'text': 'マチュピチュ',
},
];
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: const Color.fromRGBO(240, 240, 240, 1),
appBar: AppBar(
centerTitle: false,
backgroundColor: Colors.black54,
title: Text(
titleText,
style: TextStyle(fontWeight: FontWeight.bold),
),
actions: <Widget>[
IconButton(
onPressed: () {
showDialog(
context: context,
builder: (context) {
return const AlertDialog(
title: Text(
'メニューバーが押されました !',
textAlign: TextAlign.center,
style: TextStyle(fontSize: 16),
));
},
);
},
icon: const Icon(Icons.menu)),
IconButton(
onPressed: () {
showDialog(
context: context,
builder: (context) {
return const AlertDialog(
title: Text(
'設定ボタンが押されました !',
textAlign: TextAlign.center,
style: TextStyle(fontSize: 16),
));
},
);
},
icon: const Icon(Icons.settings)),
const SizedBox(width: 16),
],
),
body: Padding(
padding: EdgeInsets.all(16),
child: GridView.builder(
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
crossAxisSpacing: 8,
),
itemCount: articles.length,
itemBuilder: (BuildContext context, int index) {
return Column(
children: <Widget>[
// 画像にonTapをつける
GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ThirdPage(
"${articles[index]['text']}",
"${articles[index]['image']}")),
);
},
child: Image.network("${articles[index]['image']}")),
const SizedBox(height: 4),
Text("${articles[index]['text']}")
],
);
},
)),
floatingActionButton: FloatingActionButton(
backgroundColor: Colors.black54,
onPressed: () {
Navigator.popUntil(context, (route) => route.isFirst);
},
tooltip: 'Back Home',
child: const Icon(Icons.home),
),
);
}
}
内容
- appBar
- タイトルがファーストページのテキストフィールドで入力したテキスト
- アイコンはファーストページと同じ
- body
- 記事(写真とタイトル)の配列をGridViewで2列で表示
- 記事画像クリックでサードページに画面遷移
- floatingActionButton
- ホームアイコンを押すとファーストページに画面遷移
サードページ
third_page.dart
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:coriander/second_page.dart';
class ThirdPage extends StatelessWidget {
ThirdPage(this.imageText, this.imageSrc);
final String imageText;
final String imageSrc;
var alertText = "";
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: const Color.fromRGBO(240, 240, 240, 1),
appBar: AppBar(
centerTitle: false,
backgroundColor: Colors.black54,
title: const Text(
"Third Page",
style: TextStyle(fontWeight: FontWeight.bold),
),
actions: <Widget>[
IconButton(
onPressed: () {
showDialog(
context: context,
builder: (context) {
return const AlertDialog(
title: Text(
'メニューバーが押されました !',
textAlign: TextAlign.center,
style: TextStyle(fontSize: 16),
));
},
);
},
icon: const Icon(Icons.menu)),
IconButton(
onPressed: () {
showDialog(
context: context,
builder: (context) {
return const AlertDialog(
title: Text(
'設定ボタンが押されました !',
textAlign: TextAlign.center,
style: TextStyle(fontSize: 16),
));
},
);
},
icon: const Icon(Icons.settings)),
const SizedBox(width: 16),
],
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Image.network(imageSrc),
const SizedBox(
height: 16,
),
Text(
imageText,
style: const TextStyle(
fontSize: 16,
color: Colors.black54,
fontWeight: FontWeight.bold),
),
],
)),
),
floatingActionButton: FloatingActionButton(
backgroundColor: Colors.black54,
onPressed: () {
Navigator.popUntil(context, (route) => route.isFirst);
},
tooltip: 'Increment',
child: const Icon(Icons.home),
),
);
}
}
内容
- appBar
- タイトルの表示
- アイコンはファーストページと同じ
- body
- セカンドページでクリックした記事の画像とタイトルを表示
- floatingActionButton
- ホームアイコンを押すとファーストページに画面遷移
おわりに
まだ、簡単な機能しか作れませんが、これから複雑なものも作れるように、勉強していきたいと思います。
もし間違っている部分や改善した方がいい箇所などあれば、コメントをいただけるとありがたいです!
また、アウトプットとしてこれからも投稿していきたいと思います。
最後までご覧いただきありがとうございました🙇♂️
Discussion