Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
Flutterハンズオン 4
Search
Aya Ebata
September 09, 2024
Technology
180
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Flutterハンズオン 4
Aya Ebata
September 09, 2024
More Decks by Aya Ebata
See All by Aya Ebata
JEP 526: Lazy Constants
aya_ebata
0
75
Flutterハンズオン 5
aya_ebata
0
110
JEP 480: Structured Concurrency
aya_ebata
0
300
Flutterハンズオン 3
aya_ebata
0
110
Flutterハンズオン 2
aya_ebata
0
120
Flutterハンズオン 1
aya_ebata
0
150
あたらしい もじれつの かきかた
aya_ebata
0
150
社内勉強会vol.3@ごーふぁー荘
aya_ebata
0
810
社内勉強会vol.2@ごーふぁー荘
aya_ebata
1
820
Other Decks in Technology
See All in Technology
【技術的負債conf】事業成長に伴う技術的負債の説明責任とAIによるモニタリング、認知的負債について
i35_267
3
2k
積み重なった技術負債への挑戦 〜初手としての全社ゴト化〜
techtekt
PRO
0
1.5k
Goodbye ShellScript, Hello File-based App
shunsock
0
640
技術的負債から考える、AI時代のエンジニアリング投資 — ビズリーチの技術的負債と向き合った経験から、変更し続けられるソフトウェアを考える/ technical-debt-con2026
visional_engineering_and_design
4
3.5k
CLIライブラリ開発を支える技術
htnabe
0
140
負債のメタファと2026年 / Debt Metaphor in Agentic Engineering Age 202609 Edition
twada
PRO
10
4.9k
AI 時代のスタートアップエコシステ厶から考究する技術的負債との向き合い方
m3m0r7
PRO
3
2.5k
AIによるクリエイティブ生成を行う上での試行錯誤
plaidtech
PRO
0
170
What the customer really needed
kawaguti
PRO
3
220
すぐできる衛星通信対応 あとは山奥に行くだけ
tatetate55
0
140
AIエージェントの自己改善をどう設計するか / How to Design Self-Improvement for AI Agents
22mi
25
17k
EventBridge に「合流」はない ― サーバーレスのワークフローを育てるということ / No Join in EventBridge
yusukeshimizu
2
430
Featured
See All Featured
Sharpening the Axe: The Primacy of Toolmaking
bcantrill
46
3k
How to Ace a Technical Interview
jacobian
281
24k
Primal Persuasion: How to Engage the Brain for Learning That Lasts
tmiket
0
460
CoffeeScript is Beautiful & I Never Want to Write Plain JavaScript Again
sstephenson
162
16k
Building the Perfect Custom Keyboard
takai
2
880
The Hidden Cost of Media on the Web [PixelPalooza 2025]
tammyeverts
2
500
コードの90%をAIが書く世界で何が待っているのか / What awaits us in a world where 90% of the code is written by AI
rkaga
63
46k
Gemini Prompt Engineering: Practical Techniques for Tangible AI Outcomes
mfonobong
2
530
Done Done
chrislema
186
17k
How GitHub (no longer) Works
holman
316
150k
Conquering PDFs: document understanding beyond plain text
inesmontani
PRO
4
3.1k
Joys of Absence: A Defence of Solitary Play
codingconduct
1
530
Transcript
Flutterハンズオン 4 2024/09/10 社内勉強会 えばた あや
今日話すこと 1. VSCodeでFlutterプロジェクトを開始する 2. Flutterの基礎
1. VSCodeでFlutterプロジェクトを 開始する
VSCodeでFlutterプロジェクトを開始する 0. VSCodeを開く - 以下のコマンドと同様なことをVSCodeでやっていきます $ flutter create [プロジェクト名]
VSCodeでFlutterプロジェクトを開始する 1. コマンドパレットを開き、[Flutter: New Project]を検索し選択する
VSCodeでFlutterプロジェクトを開始する 2. [Application]を選択し、プロジェクトを作成するフォルダを選択する
VSCodeでFlutterプロジェクトを開始する 3. スネークケースでプロジェクトに名前を付ける
VSCodeでFlutterプロジェクトを開始する 4. iOSのシミュレータ/Androidの エミュレータを開いて、 VSCodeでデバイスの選択を して、実行できることを確認 する
VSCodeでFlutterプロジェクトを開始する ※ たまにデバイスの選択が反映されないことがあるので、その場合は コマンドパレットで[Developer: Reload Window]を実行
VSCodeでFlutterプロジェクトを開始する 5. 前回同様、カウンターアプリが表示されれば成功
2. Flutterの基礎
Flutterの基礎 本日はこちらを元にやっていきます! https://docs.flutter.dev/ui
Hello World!を出力する 1. カウンターアプリの実装を削除する - MyAppクラスのbuild()メソッドの中身を全部削除する - その下にあるクラスも消しちゃってOK
Hello World!を出力する 2. MyAppクラスのbuild()メソッドに以下を貼り付ける return const Center( child: Text( 'Hello,
world!', textDirection: TextDirection.ltr, ), );
Hello World!を出力する 3. 保存をすると、ホットリロードが走って反映される!
Hello World!を出力する 解説 import 'package:flutter/material.dart'; void main() { runApp(const MyApp()); }
class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return const Center( child: Text( 'Hello, world!', textDirection: TextDirection.ltr, ), ); } }
Hello World!を出力する 解説 - マテリアルデザインのFlutter開発で必要なものが入っている packageをインポートする import 'package:flutter/material.dart';
Hello World!を出力する 解説 - runApp()でアプリを開始する - runApp()の中に直接CenterやTextなどのウィジェットを書く のではなく、クラスを呼ぶようにする -> 直接書くとホットリロードが効かないよ! void
main() { runApp(const MyApp()); }
Hello World!を出力する 解説 - StatelessWidgetを継承する - 状態を持たないウィジェットであることを意味する - 状態を持つ場合はStatefulWidgetを使用する class MyApp
extends StatelessWidget { // ... }
Hello World!を出力する 解説 - buildメソッドにウィジェットの実装を書いていく @override Widget build(BuildContext context) { //
... }
Hello World!を出力する 解説 - Center: 中央に表示する - child: センターにするウィジェットを指定する - Text:
文字列を表示する - textDirection: テキストの開始位置(今回は左を指定) return const Center( child: Text('Hello, world!', textDirection: TextDirection.ltr), );
その他のよく使うウィジェット - Row: 水平方向のレイアウトを作成する ※ Centerウィジェットのchildを以下に変更 Row( textDirection: TextDirection.ltr, mainAxisSize:
MainAxisSize.min, children: [ Text('Hello, world!1', textDirection: TextDirection.ltr), Text('Hello, world!2', textDirection: TextDirection.ltr), ], ),
その他のよく使うウィジェット - Row: 水平方向のレイアウトを作成する 以下が出力される
その他のよく使うウィジェット - Column: 垂直方向のレイアウトを作成する ※ MyAppクラスのbuildメソッドのreturnに以下を追加 const Column( mainAxisAlignment: MainAxisAlignment.center,
children: [ Text('Hello, world!1', textDirection: TextDirection.ltr), Text('Hello, world!2', textDirection: TextDirection.ltr), ], );
その他のよく使うウィジェット - Column: 垂直方向のレイアウトを作成する 以下が出力される
その他のよく使うウィジェット - Stack: レイアウトを重ねて配置する ※ MyAppクラスのbuildメソッドのreturnに以下を追加 const Center( child: Stack(
textDirection: TextDirection.ltr, children: [ Text('Hello, world!1', textDirection: TextDirection.ltr), Text('Hello, world!2', textDirection: TextDirection.ltr), ], ), );
その他のよく使うウィジェット - Stack: レイアウトを重ねて配置する 以下が出力される(1と2の文字が重なってる)
その他のよく使うウィジェット - Container: 箱のウィジェットが作成できる ※ MyAppクラスのbuildメソッドのreturnに以下を追加 Center( child: Container( color:
Colors.blue, width: 100, height: 100, ), );
その他のよく使うウィジェット - Container: 箱のウィジェットが作成できる 以下が出力される
テーマを反映させる - mainのrunApp()にMaterialAppを追加する - 上層部にウィジェットを追加するにはcommand+.でwrapできる - テーマの設定、ルートの管理、ローカライゼーションなどが できるようになる void main()
{ runApp(const MaterialApp(title: 'Flutter Tutorial', home: MyApp())); }
テーマを反映させる - MyAppクラスのbuildメソッドにScaffoldを追加する - Material Designの基本的なビジュアルレイアウト構造を提供する @override Widget build(BuildContext context)
{ return const Scaffold( body: Center( child: Text('Hello World!'), ), ); }
テーマを反映させる - テーマが反映されたことを確認
AppBarを追加する - ScaffoldにappBarを追加する - constをScaffoldからCenterに書き換える(余計な再描画を防ぐため) @override Widget build(BuildContext context) {
return const Scaffold( appBar: AppBar(title: const Text('Example title')), body: const Center(child: Text('Hello World!')), ); }
AppBarを追加する - AppBarが反映されたことを確認
ハンバーガーメニューを追加する - AppBarの引数に以下を追加 leading: const IconButton( icon: Icon(Icons.menu), tooltip: 'Navigation
menu', onPressed: null, ),
ハンバーガーメニューを追加する - ハンバーガーメニューが反映されたことを 確認
検索アイコンを追加する - AppBarの引数に以下を追加 actions: const [ IconButton( icon: Icon(Icons.search), tooltip:
'Search', onPressed: null, ), ],
検索アイコンを追加する - 検索アイコンが反映されたことを確認
フローティングアクションボタンを追加する - Scaffoldの引数に以下を追加 floatingActionButton: const FloatingActionButton( tooltip: 'Add', onPressed: null,
child: Icon(Icons.add), ),
フローティングアクションボタンを追加する - フローティングアクションボタンが 反映されたことを確認
インクリメントできるボタンを追加する - 以下のようなものを追加していきます
インクリメントできるボタンを追加する - Scaffoldのbodyにある「Hello World!」を出力するテキストをColumn ウィジェットでwrapする -> 垂直方向にウィジェットを追加できるようになる Column( mainAxisAlignment: MainAxisAlignment.center,
children: [ Text('Hello World!'), ], ),
インクリメントできるボタンを追加する - ボタンとテキストが横並びのウィジェットを作りたいのでRowを追加 body: const Center( child: Column( mainAxisAlignment: MainAxisAlignment.center,
children: [ Text('Hello World!'), Row(mainAxisAlignment: MainAxisAlignment.center, children: []), ], ), ),
インクリメントできるボタンを追加する - Rowのchildrenにボタンを追加 Row( mainAxisAlignment: MainAxisAlignment.center, children: [ ElevatedButton( onPressed:
null, // TODO: 後で実装する child: Text('Increment'), ), ], ),
インクリメントできるボタンを追加する - Rowの中にテキストも追加 Row( mainAxisAlignment: MainAxisAlignment.center, children: [ ElevatedButton(onPressed: null,
child: Text('Increment')), Text('Count: 0'), ], ),
インクリメントできるボタンを追加する - ボタンとテキストの間を少し開ける Row( mainAxisAlignment: MainAxisAlignment.center, children: [ ElevatedButton(onPressed: null,
child: Text('Increment')), SizedBox(width: 16), Text('Count: 0'), ], ),
インクリメントできるボタンを追加する 1. ElevatedButtonのonPressedを空の無名関数に置き換える 2. ElevatedButtonが定数ではなくなるのでbody直後のconstを削除 3. その代わり、TextとSizedBoxにconstを追加 ElevatedButton( onPressed: ()
{ // TODO: 後で実装する }, child: const Text('Increment'), ),
状態(state)管理を用意する - インクリメントのための状態管理を用意する(以下現状) class MyApp extends StatelessWidget { const MyApp({super.key});
@override Widget build(BuildContext context) { // ... } }
状態(state)管理を用意する - MyAppを_MyAppStateに変更し、State<MyApp>を継承する - コンストラクタはここではいらなくなる class _MyAppState extends State<MyApp> {
@override Widget build(BuildContext context) { // ... } }
状態(state)管理を用意する - MyAppクラスをまた新しく追加する - 状態を扱うのでStatefulWidgetを継承する - ここでコンストラクタの定義をする class MyApp extends
StatefulWidget { const MyApp({super.key}); @override State<MyApp> createState() => _MyAppState(); }
状態(state)管理を用意する - _MyAppStateクラスに以下の状態を追加する int _counter = 0; void _increment() {
setState(() { _counter++; }); }
状態(state)管理を適用する - ElevatedButtonに先ほど定義した_increment()メソッドを指定する ElevatedButton( onPressed: _increment, child: const Text('Increment'), ),
状態(state)管理を適用する - Textに先ほど定義した_counter変数を指定する - _counter変数の値は動的に変化する値になるのでconstを削除する ElevatedButton( onPressed: _increment, child: const
Text('Count: $_counter'), ),
状態(state)管理を適用する - Incrementボタンをクリックして カウントアップされることを確認 する
リファクタリングする - Countのテキストを別ウィジェットに切り出すために、 CounterDisplayクラスを用意する class CounterDisplay extends StatelessWidget { const
CounterDisplay({super.key}); @override Widget build(BuildContext context) { return const Text('Count: x'); // いったん仮の値 } }
リファクタリングする - CounterDisplayウィジェットを呼び出すように変更する Row( mainAxisAlignment: MainAxisAlignment.center, children: [ ElevatedButton(onPressed: _increment,
child: const Text('Increment')), const SizedBox(width: 16), const CounterDisplay(), ], ),
リファクタリングする - _counterの値を使うために、CounterDisplayクラスに値をcount という名前で渡すように変更する // コンストラクタにthis.countを追加 const CounterDisplay({required this.count, super.key});
// countプロパティを追加 final int count;
リファクタリングする - CounterDisplayクラスのbuildメソッドにてcountを表示する - 動的な値になるのでTextについていたconstは削除する @override Widget build(BuildContext context) {
return const Text('Count: $count'); }
リファクタリングする - CounterDisplayの呼び出し部分に_counterを渡す - こちらも動的な値を扱うため、CounterDisplayの前のconstを削除する const CounterDisplay(count: _counter)
リファクタリングする ※ command+. -> Extract Widget -> CounterDisplayを入力でも作成できる
リファクタリングする 練習問題 1. IncrementボタンをCounterIncrementorクラスに切り出す - voidのメソッドを渡すための型はVoidCallbackです 2. 作成したCounterIncrementorウィジェットを使ってIncrementボタン を呼び出して表示する 3. カウントアップができることを確認する
リファクタリングする 練習問題 解答例 class CounterIncrementor extends StatelessWidget { const CounterIncrementor({required this.onPressed, super.key});
final VoidCallback onPressed; @override Widget build(BuildContext context) { return ElevatedButton( onPressed: onPressed, child: const Text('Increment'), ); } }
リファクタリングする 練習問題 解答例 Row( mainAxisAlignment: MainAxisAlignment.center, children: [ CounterIncrementor(onPressed: _increment), const SizedBox(width:
16), CounterDisplay(count: _counter), ], ),
リファクタリングする 練習問題 解答例 ※ 状態管理しているメソッドを渡している場合はExtract Widgetをすると 怒られるので、一旦空の無名関数を渡してあげると出来るようになる
まとめ - VSCodeでFlutterアプリを新規作成する方法を学んだ - Flutterで簡単なアプリを作成した