これは何?
最近、若者の間で「クソアプリ」なるものを作って公開するのが話題になっているようで。いや確かに「ちゃんとしたもの」を作ろうとすると、それはそれで多大なる労力が必要になってハードルも上がるのだけれども、クソアプリでいいやってハードルを下げると「ちょっとかじってみる」程度の経験を積むにはいいし、やったことを公開することで情報の整理にもつながっていい気がするな、ということで最近気になるFlutterで負けじとクソアプリを作ってみた。
ソースコードはコチラ。
Flutterとは?
Android/iOSのマルチデバイス対応のアプリが1つのソースコードで開発できるというGoogleが作った技術。Dart言語で実装する。
やったこと
開発環境の構築
大いにこの記事を参考にしており「開発環境の構築」は全く同じなので端折ります(手抜き)
Flutterに入門してクソアプリを作るまで
https://qiita.com/matsushou/items/f62ca1fb249670d7dbbc
ちなバージョンは
- Flutter v1.2.1 (for Mac)
- Android Studio 3.4
- FlutterとDartのプラグインを入れる
Dartに再入門する
筆者Google好きで、Dartが公開された直後(1.0以前)にかじったことがあったので、おさらい的に言語仕様(結構変わっている...)を見直してみる。
Language Tourをナナメ読む
https://www.dartlang.org/guides/language/language-tour
前述の参考記事のとおり Important concepts まで読んだが、Javaエンジニアとしては以下を踏まえればどうにかなりそう。
- 型はある、クラス定義も継承もある、ちゃんとオブジェクト指向
-
new
は2.x系から省略可能になった(当時のリリースノート) - アンダースコア
_
始まりの変数/関数/クラスがprivateになる- 可視性を示す修飾子 public/private はない
Flutterアプリを作ってみる
-
Android Studioから「Start a new Flutter project」を選択
-
Flutter Applicationを選択してNext
-
Project nameを適当に指定(デフォルトの
flutter_app
のままでもいい)してNext -
Company domainを適当に指定、Sample Applicationの "generate sample content" にチェックしてFinish
-
-
main.dart
にメインロジックが記載されている - ちゃんとテストコード
widget_test.dart
も用意されているのが素敵
-
-
Emulatorを用意して起動
- AVD Managerから端末のVMを用意して起動する
- +ボタンを押すと画面に表示された数値が増えていくサンプルアプリらしい
-
サンプルアプリの画像は前述の記事にキャプチャがあるので、そっちを見てください(という手抜き)
-
アプリを実装する
クソアプリの境界線ってどこだろう?うっかりちゃんと作ってしまうとクソではなくなってしまうので、ここは慎重にクソアプリを作る必要がある。
今回は、macOSを始めとして Google Chrome や Evernote でも実装されている流行りの DarkMode を搭載すべく「ダークモードへの切り替え」をこのアプリに実装してみることにする。
漢は黙ってCI
とはいえロジックに手を出し始めるのではなく、眼の前に動くコードとテストコードがあるなら、まずCIを回さないとね。ということでCircleCIでのビルドを設定しておく。
- 生成されたサンプルプロジェクトをそのままコミット&GitHubへプッシュする。
次に挙げるサイトを参考にすると、すでにFlutter用のビルドコンテナが用意されているのが分かるので、単純に .circleci/config.yml
を追加するだけで、CircleCI上でビルドが動くようになる。作業ログ
version: 2
jobs:
build:
docker:
- image: cirrusci/flutter
steps:
- checkout
- run: flutter doctor
- run: flutter test
- run: flutter build -v apk
これで、branch push 時や、master マージ時にビルドが走るようになる。コケたら教えてくれるので、あんしんあんしん。
モード切り替え用のコントロール(Switch)を配置
よし、本筋に戻ってまずはスイッチを配置するぞ。ということでサンプルをググってみる。
これがシンプルにまとまっていて分かりやすい。他にもサンプルケースが色々あって良さげ。このサイトはGitBookで作られていて、元のリポジトリは ここ のようだ。
main.dart
の内容をまるっとこのサンプルに書き換えて実行してみたら、ちゃんとスイッチのサンプルが表示された。
そうそう、それよそれ。
今回はタイトル付きのスイッチを使いたいので、この部分+ _onChanged2()
関数をパクればよろし。
new SwitchListTile(
value: _value2,
onChanged: _onChanged2,
title: new Text('Hello World', style: new TextStyle(fontWeight: FontWeight.bold, color: Colors.red)),
)
実際には、こんなソースを child: Column()
の children: <Widget>[]
の先頭に追加しました。
この時点ではまだ _changeDarkMode()
関数はテキトーです。
Container(
padding: EdgeInsets.all(40.0),
child: SwitchListTile(
value: _isDarkMode,
onChanged: _changeDarkMode,
title: Text('Dark mode', style: new TextStyle(fontWeight: FontWeight.bold)),
),
),
見た目はこんな感じに。
パーツを配置しただけで「Dark modeに切り替えられる感」が8割増しましたね。
いざ、DarkModeへ切り替え
残るは _changeDarkMode()
関数の実装だ。ということで試しに backgroundColor
指定だけblackで追加したら、文字は黒のままで画面全体が真っ黒になってしまったので、どうやら何か違うらしい。調べてみると Theme を切り替える必要がありそう。
Using Themes to share colors and font styles - Flutter
でもこの実装を真面目にやると面倒くさいなぁ、と調べ続けていたら、DynamicTheme
というドンピシャなwidgetが公開されていたので、これを使おう。
- How to Dynamic Theming in Flutter – Aswin Mohan – Medium
- How to dynamically change the theme in Flutter – ProAndroidDev
pubspec.yaml
のdependenciesに1行追加する。
dependencies:
...(中略)
dynamic_theme: ^1.0.0
main.dart
の修正箇所はこんな感じ。(抜粋)
import 'package:dynamic_theme/dynamic_theme.dart';
...(中略)
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return DynamicTheme(
defaultBrightness: Brightness.light,
data: (brightness) => ThemeData(
primarySwatch: Colors.blue,
brightness: brightness,
),
themedWidgetBuilder: (context, theme) {
return MaterialApp(
title: 'Flutter Demo',
theme: theme,
home: MyHomePage(title: 'Flutter Dark Mode Sample'),
);
}
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
bool _isDarkMode = false;
void _changeDarkMode(bool value) {
setState(() {
_isDarkMode = value;
var _brightness = Brightness.light;
if (_isDarkMode) {
_brightness = Brightness.dark;
}
DynamicTheme.of(context).setBrightness(_brightness);
});
}
...(略)
}
- 結果
-
うーん、、、冷静に見ると「だからどうした感」のあるクソアプリですね
-
参考:作業ログ
感想
- 簡単にスマホアプリが作れそう
- 今回はアプリを最終ビルドするところまでやっていないけど、簡単な動作確認レベルならすぐイケる
- dart はキャッチアップ楽ちん
- エディタの補完も効けば何の苦もない
- ソースコードの保存 → エミュレータへの自動反映、での動作確認が非常に快適
- クソアプリ作ってみるの楽しい
GW後半に軽くプログラミングしてみたい方は、いかがでしょうか?
お粗末さまでした。