Flutterを勉強し始めたので知ったことをメモしていく その2
その1 から続く
このスクラップでは、Flutterを勉強し始めて知ったことを、つらつら垂れ流してみます。
目的は、知ったことを忘れないようにメモしておくことです。
もしかしたら、ざっと辿っていただけると、これからFlutterを学ぶ人は、なんとなく全体像が掴めるかもです。
あとは、個人のアウトプットとして垂れ流していくので、間違った情報があるかもです。
ご注意いただければ幸いです🕊
Flutter: 3.24.0
Macbook M1Pro
VisualStudio Code
iOS と Android 向けのアプリを作る
バタバタしていたけれど再開します。
ひさしぶりにプロジェクトを開くと、flutter 3.24.1が来ていました。
プロジェクトのflutterが 3.22.3 だったので、アップデートしておきます。
fvmをバージョン管理ツールとして使っており、
fvm releases
で最新バージョンを確認した後、
fvm install 3.24.1
でインストールし、
fvm use 3.24.1
でプロジェクトのバージョンを固定しました。
(ついでに fvm global 3.24.1
でglobalで使うflutterも上げておきます)
.fvmrc ファイルや fvm flutter --version
が上がっていることを確認。
fvm flutter pub get
で新しいパッケージをインストールし、
fvm flutter pub update
で依存パッケージをアップグレードしました。
ただし、このままだといくつか古いパッケージが残るので、
fvm flutter pub upgrade
で依存関係を把握し、
適当に pubspec.yaml
で使用しているパッケージのバージョンを更新しました。
ここで F5 で VSCode を通して /lib/main.dart
からアプリを起動。
ビルドが走るのですが、
flutter ios/Runner/AppDelegate.swift uses the deprecated @UIApplicationMain attribute, updating.
と注意されているのを発見。
以下の通りに解決。
とりあえず、バージョンアップはこんな感じで。
あとは作り始めて、必要に応じて追加で理解度をあげていくことにします。
ページの切り替えについて考えていて、まあ、とにもかくにも状態管理が必要そうです。
prividerというのがよく使われていたらしいですが、riverpodが流行ってきているらしいので、こちらを採用しました。
flutter pub add flutter_riverpod
でインストールしてもいいし、直接 pubspec.yaml
を編集した後、flutter pub get
してもいいそうです。
flutterのディレクトリ構成ですが、/lib
ディレクトリにプログラムを書いていくようです。
/ios
や /android
などはネイティブコードやそれぞれのプラットフォームに向けた設定ファイルが置かれるとのこと。
/lib
内のディレクトリ構成ですが、ひとまず ファイルタイプで分けることにしました。
viewsやwidgetsフォルダを作ります。
機能別(authとかarticleとか)やドメイン別で分けてもいいのですが、ひとまず、、。
基本的に、lintがしっかり仕事してくれているのか、やばそうなところはwarningが出ます。
例えば、Constructors for public widgets should have a named 'key' parameter. Try adding a named parameter to the constructor.
などです。
これはクラスに keyをつけてね、とのこと。
class ArticleDetailPage extends ConsumerWidget {
const ArticleDetailPage({super.key});
...
のように const ArticleDetailPage({super.key})
を書いておきます。
このsuper.keyは const ArticleDetailPage({Key? key}) : super(key: key);
と同じだそうです。
(2.2くらいから追加された書き方でこちらを使うのを推奨らしい)
あとは、constを使えだの、丁寧に叱ってくれるので、大人しく従います。
class MyApp extends StatefulWidget {
const MyApp({super.key});
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
int _currentIndex = 0;
final List<Widget> _pages = [
...
StatefulWidgetにて、このように書いていたら、MyAppクラスの _MyAppStateのところで怒られました。
どうも_
アンダースコアで始まるクラス名はprivateになるらしく、createState()もprivateにしなさいよ(もしくは_MyAppStateをpublicにしなさいよ)とのことです。
これは、 State<MyApp> createState() => _MyAppState();
のように書くといいとのことです。
NavigationBarを BottomNavigationBar
ウィジェットを使い実装。
ここら辺は探せばたくさん出てきそうなので割愛。
ページ遷移に関しては、Navigator 2.0 による方法もあるようです。
今回はタブの選択に応じて遷移したかったのでRiverpodによって実装しました。
次に、Homeに適当な画像をメインビジュアルとして配置してみることにします。
画像を扱う方法について
- pubspec.yamlにassetsとして登録
flutter:
assets:
- assets/images/
このようにディレクトリごと設定することもできるようです。
(ただし、子ディレクトリのファイルまでは見に行ってくれない模様)
- Image.asset('MY_IMAGE_PATH') のように呼び出す
なお、Image.assetウィジェットはconstをつけることができません。
これは画像が表示される時に動的に評価されるため(ディスプレイに応じたサイズ等)、コンパイル時には評価できないからだそうです。
また、もしウェブ上の画像を表示するときは、Image.network
を使うとのこと。
メモ
-
2x/
や3x/
のようにディレクトリを作ると、解像度ごとに異なる画像を使ってくれるらしい - LazyLoadingができるらしい
- キャッシュが多くならないよう、メモリクリアしたり
- Placeholderを使ったり
黙々とページを作っていきます。
使ったウィジェットをまとめておきます。
・Card ウィジェット
子を持てる。marginつけたり、影を設定したり、constをつけたり、便利に使える
・Container ウィジェット
実行時にインスタンスを生成するらしい。Cardより柔軟に設定できるらしい。
・Row, Column
childrenを並べる。デフォルトだと子要素が一行に収まらないとオーバーフローする。
子要素にExpandedやWrapなどを使って対応。
・Wrap
childrenを並べる。子ウィジェットがスペースに収まりきらない場合、自動的に折り返してくれる。
axisで方向を指定する。
・Expanded
RowやColumn内で使われると、親の残りのスペースを占有する。
flexプロパティで柔軟に比率でスペースを配分することも。
子要素がTextなら、overflow: TextOverflow.ellipsisで省略記号を表示できる。
・SingleChildScrollView
子要素がスクロールできるようになる。
CMSから記事を取得して表示する機能が欲しいです。
-
lib/models/article.dart
に記事classを作成 -
lib/mocks/mock_articles.dart
にモックデータを作成 -
lib/views/article_list_page.dart
でこれらを使って一覧を表示 - 一覧をクリックすると、
lib/views/article_detail_page.dart
で詳細を表示する
という流れで記事一覧を作成しました。
なお、article_list_item.dart
を作って、Listの一要素を別ファイルに分離させました。
いい感じにウィジェットは分けていきたいです。
また、タップした時のアクションは、
GestureDetector(
onTap: () {
// 記事がクリックされた時に詳細ページへ遷移
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ArticleDetailPage(article: article),
),
);
},
child: Card(
// ...
のように、 GestureDetector を使うといいようです。
CMSから取得した記事の本文は、htmlで書かれています。
flutterでは、flutter_html というパッケージを使ってhtmlの要素をflutterのウィジェットに変換して表示できるそうです。
ただし、 flutter_html は2年前から更新が止まっており、新しいflutter 3.24.1では動きませんでした。
そこで、 flutter_widget_from_html を使いました。
pubspec.yaml に追記。
dependencies:
flutter_widget_from_html: ^0.15.2
flutter pub get
でパッケージ更新。
なお、 webview_flutter で表示することもできるようです。
こちらは直接ウェブとして表示できるので、style等をウェブの表示と合わせやすいそうですが、レンダリングがやや遅いとのこと(ざっくり理解だが、ブラウザを用意してそこにレンダリングするかららしい)。
実際にどのくらい遅いのかわからない(気にならないくらいな気がする)のですが、ひとまずflutter_widget_from_htmlを試していくことにします。
他には、markdownから表示するパッケージもあるとのこと。