Closed18
【Flutter編】Flutter入門してみた(作業ログ)
プロジェクトの作り方
- 以下のコマンドを打って雛形を生成する
flutter create プロジェクト名
静的解析の設定方法
- デフォルトでインストールされているflutter_lintsを使用する
- 静的解析のオプションは
analysis_options.yaml
で設定できる
Widget
- UIを構築する上で必要になるクラス
- UIに関する機能を提供するものやUI以外の機能(ナビゲーション)を提供するものもある
- Flutterで予め用意されているWidgetやWidget同士を組み合わせた独自のWidgetを使ってUIを構築する
- 独自のWidgetを作成する際には
StatelessWidget
かStatefulWidget
のどちらかを継承する必要がある
MaterialApp
- アプリケーションのテーマを決定したり、ページ遷移のためのNavigatorを構築する
class App extends StatelessWidget {
const App({Key? key}) : super(key: key);
Widget build(BuildContext context) {
// 最初に表示するページとしてHomeScreen Widgetを指定
return const MaterialApp(
home: HomeScreen(),
);
}
}
Scaffold
- ページを構成する際に便利なWidget
- プロパティに表示したいWidgetを指定してあげることでUIの構築ができる
Scaffold(
// 画面中央に「ホーム」という文字列を表示する
body: Center(
child: Text('ホーム'),
),
);
AppBar
- 画面上部のヘッダを表示する際に使用するWidget
- ScaffoldのappBarプロパティにこいつを指定して使う
- 状態遷移後にもとの画面に戻るボタンが自動で追加されて便利
Scaffold(
// ヘッダーに「ToDo」という文字列を表示させる
appBar: AppBar(
title: const Text('ToDo'),
),
body: const Center(
child: Text('ホーム'),
),
);
ListView.builder
- リスト形式で表示する際に使用するWidget
- 画面に表示したい要素の個数が多いときに名前付きコンストラクタ(builder)を使ってインスタンスを生成する
Scaffold(
body: ListView.builder(
// itemCountプロパティに指定された数だけListTileWidgetを表示する
// indexは0からインクリメントされる
itemBuilder: (context, index) => ListTile(
title: Text(_todos[index]),
),
itemCount: _todos.length,
),
);
ListTile
- ListViewと併用して使えるWidget
- プロパティで表示位置を指定できる(例:leading: 左端 title:leadingの右隣 trailing:右端)
FloatingActionButton
- 画面上に浮かんでいるようなボタンを表示する際に使うWidget
- ScaffoldのfloatingActionButtonプロパティにこいつを指定して使う
Scaffold(
floatingActionButton: FloatingActionButton(
// 十字に無印の背景のようなボタンを表示する
child: const Icon(Icons.add),
// ボタンが押されたら_todosに新しい要素を追加する
onPressed: () {
_todos.add('Todo ${_todos.length + 1}');
},
),
);
画面に表示する要素に変更があったときにそれを画面に反映させるには?
- StatefulWidgetを継承したWIdgetを使用して、反映させたい要素を
setState
で囲む
class HomeScreen extends StatefulWidget {
const HomeScreen({Key? key}) : super(key: key);
State<HomeScreen> createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
// 仮データ
final _todos = List.generate(
10,
(index) => 'ToDo ${index + 1}',
);
Widget build(BuildContext context) {
return Scaffold(
body: ListView.builder(
itemBuilder: (context, index) => ListTile(
title: Text(_todos[index]),
),
itemCount: _todos.length,
),
floatingActionButton: FloatingActionButton(
child: const Icon(Icons.add),
onPressed: () {
// setStateで囲まれた処理が実行されたら、自動的に画面が再構築される
setState(() {
_todos.add('Todo ${_todos.length + 1}');
});
},
),
);
}
}
CheckboxListTile
- 要素をリスト表示することに加えてチェックボックスも一緒に表示したいときに使用するWidget
- onChangedプロパティでチェックのオンオフを実装できる
- チェックのオンオフを画面に反映させたいときにはonChangedの中身をsetStateで囲む
class HomeScreen extends StatefulWidget {
const HomeScreen({Key? key}) : super(key: key);
State<HomeScreen> createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
// 仮データ
final _todos = List.generate(
10,
(index) => ToDo(title: 'ToDo ${index + 1}'),
);
Widget build(BuildContext context) {
return Scaffold(
body: ListView.builder(
itemBuilder: (context, index) =>CheckboxListTile(
// チェックボックスの状態が変化したら再描画
onChanged: (checked) {
setState(() {
// チェック状態を反転させる
_todos[index].archived = !_todos[index].archived;
});
},
// チェックボックスの状態(onかoffか)
value: _todos[index].archived,
title: Text(_todos[index].title),
),
itemCount: _todos.length,
),
floatingActionButton: FloatingActionButton(
child: const Icon(Icons.add),
onPressed: () {
setState(() {
_todos.add(ToDo(title: 'Todo ${_todos.length + 1}'),);
});
},
),
);
}
}
freezed
- イミュータブル(変更不可能)なクラスを作成する際に使用するパッケージ
- ミュータブルなクラスにメタデータとfactoryコンストラクタを加えてコードを生成する
- 生成されたコードをpartで取り込むことで、変更差分のある新しいインスタンスを生成できるcopyWithが使えるようになる
import 'package:freezed_annotation/freezed_annotation.dart';
part 'user.freezed.dart';
class User with _$User{
factory ToDo({
required String name,
required String grade,
(false) bool active,
}) = _User;
}
- 以下のコマンドを上のファイルがあるディレクトリで実行すると
user.freezed.dart
が生成される
flutter pub run build_runner build
- copyWithはこんなかんじに使う
void main(){
final user_previous = User('alice', 'grade1');
// user_previousのnameプロパティだけ変更したい
final user_other = user_previous.copyWith(name: 'Bob');
print(user_previous); // name:Alice grade:grade1 active:false
print(user_other); // name:Bob grade:grade1 active:false
}
sembast
- ローカルデータベースを使えるようにするパッケージ
- NoSQLの一種で、json_serializableと相性が良い
- path_providerパッケージのWidgetsFlutterBinding.ensureInitialized()を使ってアプリが利用できるパスを取得し、そこにデータベースのファイルを置く
- 基本的にDB関係の処理は非同期で書く
初期化
final appDir = await getApplicationDocumentsDirectory();
// 利用できるパスにデータベースのファイルを作る
_database = await databaseFactoryIo.openDatabase(
join(appDir.path, 'todo.db'),
);
_store = intMapStoreFactory.store('todo');
追加
// json形式に変換する
// 追加に成功したら、追加した予定に紐づくkeyが帰ってくる
final key = await _store.add(_database, todo.toJson());
更新
// keyを指定して更新
_store.record(key).put(_database, todo.toJson());
全件取得
final result = await _store.find( _database,finder: Finder(sortOrders: [SortOrder(Field.key, false)],),);
FutureBuilder
- futureプロパティに指定した関数の返り値によって返すWidgetを変えることができる
- builderプロパティはfutureの処理状態に応じて、指定された関数を複数回実行する
このスクラップは2022/09/18にクローズされました