Flutterメモ
// Flutter frameworkで捕捉できないエラーを捕捉する
runZonedGuarded(() async {
}, (Object error, StackTrace trace) {});
WidgetsFlutterBinding.ensureInitialized();
- Flutter EngineとFlutter frameworkを紐付ける役割。
-
runApp
を呼び出す前にFluttter Engineの機能を利用したい場合にrunApp
の前で呼び出す。
— dart-define=Flavor=dev
で指定された環境変数を読み込む
String.fromEnvironment('Flavor')
例
class Environment {
static Future<void> load() async {
final flavor = Flavor.values.byName(String.fromEnvironment('Flavor'));
}
}
flutter packages pub run flutter_launcher_icons:main
コマンドで
Cannot open file, path = 'assets/images/app_icon_prod.png' (OS Error: No such file or directory, errno = 2)
pub finished with exit code 2
というエラーが表示された。
原因は
image_path: "assets/images/app_icon_dev.png"
lib/assets/...
から指定されていないこと
String.fromEnvironment('Flavor')
で値がnullだった場合の対処法
const String.fromEnvironment('Flavor')
const
をつける。
WebやmacOSをプロジェクトからoffにするコマンド
flutter config --no-enable-web
flutter config --no-enable-macos-desktop
Flutter Lint
-
prefer_relative_imports
相対インポートと絶対インポートを混在させると、同じメンバーが 2 つの異なる方法でインポートされるという混乱が生じる。ディレクトリ内のファイルに対して一貫して相対インポートを使用するようにすることです 。 -
invalid_annotation_target
参考
ProviderScope
FlutterのTextButtonのパディングをなくす方法
TextButton(
child: const Text('ボタン'),
style: ButtonStyle(
padding: MaterialStateProperty.all(EdgeInsets.zero),
minimumSize: MaterialStateProperty.all(Size.zero),
tapTargetSize: MaterialTapTargetSize.shrinkWrap,
),
ListViewで
Vertical viewport was given unbounded height.
が出た時にチェックすること。
Column
の中にListView
を定義していた場合、Expanded
かFlexible
でラップする。
参考
Containerでの余白の付け方
FireStore導入時にXCode Buildで時間がかかってしまう場合の対処法
①Podfileのコメントを外す
# Uncomment this line to define a global platform for your project
platform :ios, '11.0'
②pod 'FirebaseFirestore', :git => 'https://github.com/invertase/firestore-ios-sdk-frameworks.git', :tag => '10.3.0'
の指定をPodfile
に追記する
target 'Runner' do
use_frameworks!
use_modular_headers!
pod 'FirebaseFirestore', :git => 'https://github.com/invertase/firestore-ios-sdk-frameworks.git', :tag => '10.3.0'
flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
end
③Podfile.lock
を削除し、Pod install --repo-update
を実行する
Splash画面表示後、非同期の初期化処理を終えて次の画面に遷移したい場合。
mainメソッドの中でrunAppを複数回呼び出して切り替える。
main() async {
runApp(new SplashScreen());
var foo = await init();
runApp(new FullApp(foo: foo));
}
freezed
で.g.dart
ファイルが生成されないときの確認事項
-
pubspec.yaml
にjson_serializable
の追加をし忘れ -
.fromJson
を記述していない -
part
ディレクティブを記述していない -
pubspec.lock
を削除し、再度パッケージをインストールする
TabBarで選択時のインディケーターをタイトル部だけにするか、選択タブ全体にするかを決定する方法
→TabBar
のindicatorSize
で指定する。
bottom: TabBar(
indicatorSize: TabBarIndicatorSize.tab,
tabs: PurchasedTabItem.tabs(context),
),
ListTile
でカード型のレイアウトの際、Exapande Column
の子要素が上寄せされない時に確認すること。
Row
にcrossAxisAlignment: CrossAxisAlignment.start
を指定する
Row(
crossAxisAlignment: CrossAxisAlignment.start, // ここ
mainAxisSize: MainAxisSize.min,
children: [
Padding(
padding: const EdgeInsets.only(top: 8, bottom: 8, right: 16),
child: Image.asset('images/sample.jpg'),
),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: EdgeInsets.only(top: 10, right: 2),
child: Text('ホゲホゲ'),
),
Padding(
padding: EdgeInsets.only(
top: 18,
right: 44,
),
child: Text('ふがふが'),
),
],
),
),
],
)
flutterで配列の要数数が少ない時に画面サイズを満たすContainer
で、要素数が増えた場合にはスクロールするContainer
を実装したい時はどうすれば良いか。
→ CustomScrollView
を使用する。
return Scaffold(
body: SafeArea(
child: CustomScrollView(
slivers: [
SliverFillRemaining(
hasScrollBody: false,
child: Container(
padding: const EdgeInsets.all(16),
color: context.colorScheme.surface,
child: Container(
decoration: BoxDecoration(
color: context.colorScheme.primary,
borderRadius: BorderRadius.circular(10),
),
child: Column(
children: strList2
.map(
(str) => SizedBox(
width: double.infinity,
height: 50,
child: Text(str),
),
)
.toList(),
),
),
),
),
],
),
),
);
Riverpod generator使用時のkeepAliveをtrueにすべき時の要点
- 画面に紐づかなくて、いつでも参照しておきたい情報をkeepAliveでtrueにする
- iOSでいうところのAppdelegateに保存しておくような情報
go router
Riverpod ref.refresh
とref.invalidate
の違いについて
- ref.invalidate
プロバイダを破棄(プロバイダに保持している値のキャッシュを破棄)し、新しい値を取得する
プロバイダの保持している値を単に更新した時に用いる - ref.refresh
プロバイダを破棄(プロバイダに保持している値のキャッシュを破棄)し、新しい値を取得する。invalidateとの違いは、refreshでは更新された値を返却し、ローディングなどの状態遷移を行うので、例えばプロバイダの更新中のローディング状態中に何かしたい(インディケーターを表示する等)の処理を行いたい場合に使用する。
ScrollViewで最後尾までスクロールしたことを探知したい
Stack
使用時にRow
やColumn
などで謎のマージンが取れない場合、確認すべき箇所
1、IconButton
はマージンを持っているので、IconButton
のpadding
をzero
にする。
2、SizedBox
でwidth
/height
を指定する
@override
Widget build(BuildContext context) {
final listTile = Row(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
_buildPackageView(context),
_buildListTileContentView(context),
],
);
return Stack(
children: [
listTile,
Positioned.fill(
child: Material(
type: MaterialType.transparency,
child: InkWell(
onTap: () {
widget.onTap(widget.item);
},
),
),
),
Positioned(
bottom: 0,
right: 0,
child: _buildActions(context),
),
],
);
}
Widget _buildActions(BuildContext context) {
return Row(
mainAxisSize: MainAxisSize.min,
children: [
if (widget.item.sampleMovieUrl != null &&
widget.item.sampleMovieUrl!.isNotEmpty)
buildSampleButton(widget.item.sampleMovieUrl!),
// 2.の例
SizedBox(
width: 24,
height: 24,
child: buildFavoriteIcon(),
),
],
);
}
Widget buildFavoriteIcon() {
final colors = Theme.of(context).extension<FavoriteStarIconColor>();
return IconButton(
iconSize: 24,
// 1.の例
padding: EdgeInsets.zero,
onPressed: () {
widget.onHeartTap(widget.item);
_animationController
.forward()
.then((value) => _animationController.reverse());
},
icon: ScaleTransition(
scale: _animation,
child: Icon(
widget.item.isFavorite ? Icons.star : Icons.star_border,
color: widget.item.isFavorite
? colors?.afterStarColor
: colors?.beforeStarColor,
),
),
);
}
Widget buildSampleButton(String url) {
final sampleMovieButton = SvgPicture.asset(
Assets.icMonthlySampleButton,
width: 99,
height: 24,
);
return IconButton(
padding: EdgeInsets.zero,
icon: sampleMovieButton,
onPressed: () => widget.onSampleButtonTap(url),
).paddingOnly(right: 16);
}