FlutterでAndroid、iOS版のアプリを作った際に色んなトラブルにハマりました。自分用の戒めを込めてのメモ。
Dart、Flutterのオススメの技術書について
・2021年6月時点では、オススメはマジでない
・公式サイトをあさったり、ネット上のサンプル見てる方がマシ
・動作しないソースコード、説明がわかりにくい、そもそも公式サイトの日本語訳の書籍しかない
VSCodeを日本語化したい
Japanese Language Pack for Visual Studio Code
・Visual Studio Code 起動
・View > Command Palette > Configure Display Language > Install Additional Laugage
・サイドバーに表示された中 > Japanese Language Pack for Visual Studio Code > nstall
・画面右下Restart Now か VSCodeを再起動
or
・サイドバーの拡張機能(正方形が4つあるマーク) Ctrl + Shift + X
AndroidとiOSともにTitleテキストを中央寄せした
ナビゲーションバーのタイトルは各OSによって動作が異なる
Android・・・文字が左寄せ
iOS・・・文字が中央寄せ
明示的に中央寄せしたい場合は下記
1 2 3 4 |
appBar: AppBar( centerTitle: true, // 中央寄せを設定 title: Text("Center Title"), ), |
TextFieldに複数行入力できるようにしたい
1 2 3 4 5 6 7 |
TextField( keyboardType: TextInputType.multiline, // 追加 maxLines: null, // 追加 decoration: InputDecoration( hintText: 'TextField', ), ), |
WebでのDebugBuild時のDebugマークを消す
1 2 3 4 5 |
Widget build(BuildContext context) { return MaterialApp( debugShowCheckedModeBanner: false, // 追加 ); } |
assertって何?
・条件式がtrueにならなければ、エラーを表示してプログラムをとめてくれるやつ
・Dartはnullに厳しいので変数用意したらとりあえず記載しておくと便利
ミニマムのコピペ用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
import 'package:flutter/material.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( body: Center( child: Text('test') ), ), ); } } |
final bool flag = false;
assert(flag == null);
みたいに書くとflagが初期化されてない場合に、赤い画面とともにエラー終了してくれる
Flutterの新しいButton、RaisedButtonなどは非推奨
・RaisedButtonなどはFlutter2では非推奨
・VSCodeで使えるけど取り消し線が入ってれば下記に差し替え
FlatButton・・・TextButton
RaisedButton・・・ElevatedButton
OutlineButton・・・OutlinedButton
見た目は勿論だが、一部押したときの動作アニメーションも変わる
データを保存したい
・とりあえずという場合はSharedPreferences
・AndroidはSharedPreferences、iOSはUserDefaults()の処理に自動変換してくれる
・bool、int、double、String、List
・クラスなどを保存したい場合、jsonエンコード、デコードしてList
・Reduxの方が便利
pubspec.yaml > shared_preferencesの追記 > flutter pub get
1 2 3 4 5 6 7 |
dependencies: flutter: sdk: flutter # ↓を追加 shared_preferences: ^0.5.12+4 # ↑を追加 |
・記載したらターミナルからflutter pub get
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
import 'package:shared_preferences/shared_preferences.dart'; // Int型を読込 Future<int> _loadInt(String key, int defaultValue) async { final SharedPreferences prefs = await SharedPreferences.getInstance(); // キーが存在しているか if (prefs.containsKey(key)) { return prefs.getInt(key); } else { return defaultValue; } } final int test = 0; _loadInt('test').then .then((value) => {print(value)}); |
・上記ではtestキーからデータを読み込む
・画面上に表示する値を変えたい場合はprint部分をsetStateで更新する
・thenは処理が完了した後にする処理を追記できる
ターミナルやデバッグコンソールを開きたい場合
・画面下の青いバー > 左下の3つのアイコン(エラー、警告、お知らせみたいなやつ)
・ターミナルからパッケージをインストールしたり、Buildができる
・新しいパッケージを追加したら常にflutter pub getする
VS Codeは自動でやってくれることも
・いつまでも終わらない場合、Verが違ったりコメントの書き方が間違えてる可能性あり
↑ 実際にやった
ファイル分割して別ファイルを呼び出したい場合
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
import './nextScreen.dart'; // 呼び出したいファイルから見ての相対パス 例 topScreen.dart class hoge1 { } class hoge2 { } ↓ topScreen.dart import './nextScreen.dart'; // 呼び出したいファイルから見ての相対パス class hoge1 { } nextScreen.dart class hoge1 { } |
オリジナルクラスを実装したい場合
・Dartではクラス継承すると継承元の関数を呼び出せないっぽい
・staticをつければ実体を用意しなくてもオリジナルクラスが使えるようになる
1 2 3 4 5 6 7 8 |
class MyClass { static int sum(int a, int b){ return (a+b); } } import './MyClass.dart'; // 呼び出したいファイルから見ての相対パス print( MyClass.sum(1, 2) ); // 3が出力される |
SnackBarを表示
・Andoroidでよくある下からお知らせがでるやつ
1 2 |
final snackBar = SnackBar(content: Text('SnackBar')); ScaffoldMessenger.of(context).showSnackBar(snackBar); |
参考
https://flutter.dev/docs/cookbook/design/snackbars
画面左上のナビゲーションバー、戻るボタンで遷移元画面に値を渡す方法
・遷移元は非同期処理で遷移、遷移先はonWillPopで値を渡す処理が必要
遷移先
1 2 3 4 5 6 7 |
return WillPopScope( onWillPop: () { // 第2引数に渡す値を設定 Navigator.pop(context, 'back'); return Future.value(false); }, ); |
・Future.value(false)にしないと、遷移元にまでpopされる
・遷移元でNavigator.pushしてる部分を書き換えないとクラッシュする可能性あり (下記参照)
遷移元
1 2 3 4 5 6 7 8 9 |
var result = await Navigator.push( context, MaterialPageRoute( builder: (context) => NextScreen(model: model))); if (result != null) { setState(() { model = result; }); |
Androidのアイコンが拡大されて表示される
・しばらく前に仕様変更があったみたい
・Frontの画像が拡大表示されるっぽい
・下記で実際のイメージを見てみるとよいかも
https://adapticon.mariusclaret.com/
画面遷移でpopする際はcanPopを見た方が良いかも
・通常、前の画面に戻るだけなら Navigator.of(context).pop(); だけでOK
・デバッグしていると、TOPページを遷移後のページなどでテストしたい時がある
・そういう場合に、前ページがないのでpopするとクラッシュしたり動作がおかしくなることがあった
・canPopを噛ますことで解決可能
1 2 3 |
if (Navigator.of(context).canPop()) { Navigator.of(context).pop(); } |
Andoroid実機テストでVSCode – You don’t have an extension for debugging YAML error
・デバッグの開始ではなく、デバッグなしで開始を選択する
・ショートカットキーF5でなくではなく、Shift + F5
OSによって処理を分けたい場合(Android、iOS)
・try catchを使うこと
・使わないとWeb版でクラッシュ
1 2 3 4 5 6 7 8 9 10 |
import 'dart:io'; // プラットフォームが Android か iOS の場合 try { if (Platform.isAndroid || Platform.isIOS) { // Paddingボタンの位置を調整する _hoge1 = 0.0; _hoge2 = 33.0; } } catch (e) {} |
info: Name non-constant identifiers using lowerCamelCase.
・定数でないものは小文字から始めろという警告
・コーディング規約で決まっててこういう警告文出るのは個人的にはうれしい
final int HogeCounter
↓
final int hogeCounter
定数は
static final int HOGE = 3;
static const int HOGE = 3;
のように記載する
リストを結合するしたり、コピーしたい場合
これはできない
List
List
単一
var newList = new List.from(list1)..addAll(list2);
複数
var newList = [list1, list2, list3].expand((x) => x).toList()
var newList = […list1, …list2, …list3]; // Dart2.3以降ならスプレッド演算子でも可能
Android用証明書の作り方
・Windowsキー > Power shellと入力 > Windows Power Shellを右クリック > 管理者として実行
・cd “C:\Program Files (x86)\Java\jre1.8.0_291\bin”
↑はインストールしている場所、binフォルダ内にkeytoolがある
・他サイトだと下記みたいな書き方が多かった
・これだとリリース用のapk作るときにエラーが発生(詳細は下記)
keytool -genkey -v -keystore release.jks -alias hogehoge -validity 50000
・こっちの書き方が良さそう
keytool -genkey -v -keystore release.jks -keyalg RSA -keysize 2048 -validity 10000 -alias hogehoge
・ルートでの起動だと「.\」を付与しないとダメかも
.\keytool -genkey -v -keystore release.jks -keyalg RSA -keysize 2048 -validity 10000 -alias hogehoge
エラー内容
Suggestion [3,General]: コマンド keytool は見つかりませんでしたが、現在の場所に存在します。Windows PowerShell は、既定では、現在の場所からコマンドを読み込みません。
このコマンドを信頼する場合は、”.\keytool” と入力してください。詳細については、”get-help about_Command_Precedence” と入力してヘルプを参照してください。
・処理が通ったら下記みたいにテキストをいれてyでbinフォルダ内に証明書ができる
キーストアのパスワードを入力してください:
新規パスワードを再入力してください:
姓名は何ですか。
[Unknown]: hoge
組織単位名は何ですか。
[Unknown]: hoge
組織名は何ですか。
[Unknown]: hoge
都市名または地域名は何ですか。
[Unknown]: hogeku
都道府県名または州名は何ですか。
[Unknown]: tokyo
この単位に該当する2文字の国コードは何ですか。
[Unknown]: jp
CN=hoge, OU=hoge, O=hoge, L=hogeku, ST=tokyo, C=jpでよろしいですか。
[いいえ]: y
Androidのリリース用apkを出力する際に出るエラー 「Could not get unknown property ‘keystorePropertiesFile’ for SigningConfig_Decorated{name=release, storeFile=null, storePassword=null, keyAlias=null, keyPassword=null, storeType=jks, v1SigningEnabled=true, v2SigningEnabled=true, v1SigningConfigured=false, v2SigningConfigured=false} of type com.android.build.gradle.internal.dsl.SigningConfig.」
・flutter build apkでエラーが出る場合
・使ってる証明書の形式がいけない可能性あり、上記を参照してキー証明書を作り直す
エラー内容
FAILURE: Build failed with an exception.
* Where:
Build file ‘D:\Dropbox\flutter\clipmemo\android\app\build.gradle’ line: 47
* What went wrong:
A problem occurred evaluating project ‘:app’.
> Could not get unknown property ‘keystorePropertiesFile’ for SigningConfig_Decorated{name=release, storeFile=null, storePassword=null, keyAlias=null, keyPassword=null, storeType=jks, v1SigningEnabled=true, v2SigningEnabled=true, v1SigningConfigured=false, v2SigningConfigured=false} of type com.android.build.gradle.internal.dsl.SigningConfig.
* Try:
Run with –stacktrace option to get the stack trace. Run with –info or –debug option to get more log output. Run with –scan to get full insights.
* Get more help at https://help.gradle.org
Run with –stacktrace option to get the stack trace.
Run with –info or –debug option to get more log output.
Run with –scan to get full insights.
Androidリリース用apkの出力
・下記が一番わかりやすかった。
・先人たちは天才、神
【Flutter】Androidアプリのリリースビルドをしてみる
https://qiita.com/rkowase/items/f1012ef0738791dd6084
アイコン画像をiOSとAndroid同時に自動出力する
・flutter_launcher_iconsが鬼便利
・特定の画像を一括でリサイズしてくれる
・なぜか最新Verがエラーで動かなかった
参考
実際に使えたpubspec.yml
1 2 3 4 5 6 7 8 9 10 11 12 13 |
dev_dependencies: flutter_test: sdk: flutter flutter_launcher_icons: "^0.7.0" flutter_icons: android: true # "launcher_icon" ios: true image_path: "assets/icon/icon.png" adaptive_icon_background: 'assets/icon/ic_background.png' adaptive_icon_foreground: 'assets/icon/ic_foreground.png' # flutter packages pub run flutter_launcher_icons:main # https://adapticon.mariusclaret.com/ |
Android用のapkを生成する
・ターミナルでflutter build apk (各種設定必須)
・公開リリース用の場合は、リリースビルドにしないとダメ
・証明書関連でエラーがでたので、ビルドできない場合は上記の証明書作成を参照
参考
https://qiita.com/kasa_le/items/d23075d817f42e869778
Android版でのアプリ名、パッケージ名を変更したい
アプリ名の変更
・AndroidManifest.xml
1 2 3 |
<application Android:name="io.flutter.app.FlutterApplication" Android:label="AppName"> |
パッケージ名の変更
・AndroidManifest.xml
1 2 |
<manifest xmlns:Android="http://schemas.Android.com/apk/res/Android" package="your.company.name"> |
・build.gradle(プロジェクト名\android\app)
別場所にもあるので注意
1 2 3 4 5 6 7 8 |
defaultConfig { // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). applicationId "your.company.name" minSdkVersion 16 targetSdkVersion 30 versionCode flutterVersionCode.toInteger() versionName flutterVersionName } |
・MainActivity.Java がある場合
package your.company.name;
・合わせてディレクトリ名も変更
com.old.name から your.company.nameへ変更した場合
Android\app\src\main\Java\com\old\name
↓
Android\app\src\main\Java\your\company\name
iOSでのアプリ名、パッケージ名を変更したい
Info.plistディレクトリ内のファイルからバンドル識別子を変更します。
プロジェクト名\ios\Runner\Info.plist
アプリ名の変更
パッケージ名の変更
キーボードを出す際のBOTTOM OVERFLOWED BY ** PIXELSへの対処法
・iOSの実機だとキーボードを出して改行すると警告
・resizeToAvoidBottomInsetを使って、自動的にリサイズしないようにすると消える
1 2 3 |
Scaffold( resizeToAvoidBottomInset: false, body: hogehoge...) |
参考
https://qiita.com/mu-suke08/items/40e8f203f78f96a47bda
・Runner.xcodeproj ではなくRunner.xcworkspace で開く
・それでも出るならおそらくCocoa Pods関連のエラー
・画面左側のCocoa Pods関連が赤くなってないかチェック
・正常にインストールされていない可能性あり
・プロジェクト名/ios直下にインストールする
Cocoa Podsインストール方法
cd ios
pod install
その他メモ
・Tooltipとはアイコン等を長押しした際に表示されるテキストメッセージのこと
・関数の前の「_」はprivate関数の意味、付与すると自動的にprivateになる、つけばければpublic関数
void _hogehoge() と void hogehoge() は違うので注意
コメントを残す