以前Flutterアプリを作成した際に開発手順を残してたはずなのに、
どこかにやってしまったので今度こそ残しておく。
誰が消してしまったんd((
# 前提 Flutterアプリの開発手順として「Android Studio」が出てくる事が多いが、今回は「PowerShell + VSCode」で説明していく。
また、デフォルトアプリである「ボタンを押すとカウントアップするだけ」のアプリを改変していく形で説明していく。
# 0. 事前準備 以下から、Flutterをインストールする。 https://flutter.dev/docs/get-started/install
インストールしたら、以下のコマンドを実行。
# 実行すると「Android Studioを入れろ」「FlutterとDartのプラグインが入ってねえぞ」と怒られたりするので、お医者さん(doctor)の指示に従う。
flutter doctor
# 1. プロジェクト作成
以下のコマンドで、Flutterプロジェクトを作成。
# オプション「-i」でiOS/「-a」でAndroidのネイティブコードを指定できるが、特にこだわりはないので何も付けてない
# <例> flutter create -i swift demo_app (default: Objective-C)
# <例> flutter create -a kotlin demo_app (default: Java)
flutter create demo_app
# 2. 必要なディレクトリを作成 手順1でプロジェクトができたので、今後使うであろうディレクトリを作っておく。
# 作成したプロジェクトのフォルダに移動
cd .\demo_app\
# 「スプラッシュ画面」や「アプリアイコン」に使用する画像などを配置するフォルダ
New-Item .\assets -type directory
# Flutterは「BLoC Pattern」であり、以下に分かれる( https://note.com/yamarkz/n/n7f9106e53179 )
# - MVCでいう「M」:Resource
# - MVCでいう「V」:Widget
# - MVCでいう「C」:Bloc
New-Item .\lib\resources -type directory
New-Item .\lib\blocs -type directory
New-Item .\lib\widgets -type directory
# 3. とりあえずHello world. 手順1の時点で「Hello world.」相当はできている。 ただ、保守性や拡張性も考えて`./main.dart`から`./widgets/Hello.dart`を呼び出すようにする。
という事で、まずはファイル作成。
New-Item .\lib\widgets\Hello.dart -type file
次に、`./main.dart`を修正。 やってる事は「デフォルトソースからのコメント削除」「`./widgets/Hello.dart`の呼び出し」。
import 'package:flutter/material.dart';
import 'package:demo_app/widgets/Hello.dart'; // ←←←← 追加(`./widgets/Hello.dart`の呼び出し)
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(title: 'Flutter Demo Home Page'), // ←←←← 追加(`./widgets/Hello.dart`の呼び出し)
);
}
}
次に、./widgets/Hello.dart
を加筆。
やってる事は「main.dart
からの転記&コメント削除」だけ。
//
// デフォルトソースから転記しているだけなので、特にコメントなし
//
import 'package:flutter/material.dart';
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headline4,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}
# 4. スプラッシュ画面の設定 スプラッシュ画面は、アプリ起動時に一時的に表示されるアイコンみたいなやつ。(参考: https://uxmilk.jp/76678 )
設定としては簡単で、以下を実施するだけ。
https://pub.dev/packages/flutter_native_splash
まずは、pubspec.yaml
に以下を追記。
...
dependencies:
flutter_native_splash: ^0.1.9 # ←←←← 追加
flutter_native_splash: # ←←←← 追加
image: "./assets/smartphone_app.png" # いらすとやさんから拝借( https://www.irasutoya.com/2015/06/blog-post_824.html )
color: "#ffffff" # 背景色。必須。設定してなかったら怒られた。
...
あとは、コマンドで以下を実行。( https://pub.dev/packages/flutter_native_splash に書いてる )
flutter pub get
flutter pub run flutter_native_splash:create
# 5. アイコンの変更
言わずもがな、スマホのホーム画面に表示されるアイコンの事。(参考: https://qiita.com/wforskk/items/74d5d22e6ccc2100e5b7 )
設定としては簡単で、以下を実施するだけ。
https://pub.dev/packages/flutter_launcher_icons
まずは、pubspec.yaml
に以下を追記。
...
dependencies:
flutter_launcher_icons: ^0.8.0 # ←←←← 追加
flutter_icons: # ←←←← 追加
android: "launcher_icon"
ios: true
image_path: "./assets/smartphone_app.png" # 面倒臭かったので、手順4と同じ画像を使用
...
あとは、コマンドで以下を実行。( https://pub.dev/packages/flutter_launcher_icons に書いてる )
flutter pub get
flutter pub run flutter_launcher_icons:main
# 6. StatefulとStateless 手順3を見てみると「 `StatefulWidget` 」というクラスを継承している。という事は「 `StatelessWidget` 」というクラスも存在しそうな感じがする。
その推測は正解であり、Flutterでは「Stateful」と「Stateless」の2つの概念が存在する。
その名の通り、
「Stateful」は、state(=状態)を保持している。(何かアクションしたら、何かの値が変動する)
「Stateless」は、state(=状態)を保持していない。(何をしても何も変動しない)
デフォルトアプリを見てみると、
『ボタン』を押したら『変動するテキスト』は「Stateful」で、
ボタンを押しても『変動しないテキスト』は「Stateless」と考えられる。
という事で、StatefulとStatelessに分けてみる。
まずは`./widgets/Hello.dart`について、手順3から以下を変更する。(コメント箇所のみ確認する事)
import 'package:flutter/material.dart';
import 'package:rss_recommender/ui/CustomText.dart'; // ←←←← 追加
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
CustomText(), // ←←←← 変更(`/./ui/CustomText.dart`を呼び出し)
Text(
'$_counter',
style: Theme.of(context).textTheme.headline4,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}
次に、以下のコマンドで `./widgets/CustomText.dart` を作成する。
New-Item .\lib\widgets\CustomText.dart -type file
そして、.\widgets\CustomText.dart
に以下を記載する。
import 'package:flutter/material.dart';
class CustomText extends StatelessWidget {
CustomText();
Widget build(BuildContext context) {
return Text(
'You have pushed the button this many timessssssssss:', // ←←←← 変更箇所が分かりやすくするためにssssssssssとしている
);
}
}
7. ここまでで確認
1~6まで実施してきた事については以下となる。
- スプラッシュ追加
- アイコン変更
- Widgetsの分離
現時点でのディレクトリ構成としては以下の通り。(特に関係ない箇所については省略)
tree
(中略)
├─.dart_tool
├─.idea
├─android
├─assets
│ └─smartphone_app.png
├─build
├─ios
├─lib
│ ├─blocs
│ ├─resources
│ ├─wedgets
│ │ ├─CustomText.dart
│ │ └─Hello.dart
│ └─main.dart
├─test
├─README.md
└─pubspec.yaml
これを動画で確認すると以下の通り。
アイコンが変わっていて、スプラッシュも変わっていて、Statelessなテキストが変わっている事が分かると思う。
(アプリ名が「rss_recommender」なのは、RSSレコメンダーを作りたかったからです。そのままですね。)
999. 今後の展開
まだ使っていない「blocs」「resources」を使っていきたい。
一旦、以上!