PR

[Flutter]Flutter Widget of the Week「#85 sqflite」、「#86 SliverAppBar」、「#87 InteractiveViewer」

Flutter

はじめに

前回はFlutter Widget of the Weekの「#82 AboutDialog」、「#83 async」、「#84 url_launcher」を紹介しました。

今回はその続きで「#85 sqflite」、「#86 SliverAppBar」、「#87 InteractiveViewer」の3つです。

前回の記事はこちら

またGitHubにも公開しています。

GitHub - nobushiueshi/flutter_widget_of_the_week
Contribute to nobushiueshi/flutter_widget_of_the_week development by creating an account on GitHub.

Flutter Widget of the Week

環境

  • Flutter 3.3.3

記事にした時点でのバージョンです。GitHubに公開しているのは常に最新の安定版(stable)を使う予定です。

#85 sqflite

sqfliteとは

FlutterでSQLiteを扱うためのパッケージです。

このパッケージを使うことでデータを永続化できます。

サンプルコード

import 'package:flutter/material.dart';
import 'package:path/path.dart';
import 'package:sqflite/sqflite.dart';

class SamplePage085 extends StatefulWidget {
  const SamplePage085({
    super.key,
  });

  @override
  State<SamplePage085> createState() => _SamplePage085State();
}

class _SamplePage085State extends State<SamplePage085> {
  final String databaseName = 'sample.db';
  final List<String> migrationScripts = [
    'CREATE TABLE test (id INTEGER PRIMARY KEY, name TEXT)',
  ];
  Database? db;
  List<Map<String, Object?>>? maps = [];

  @override
  void initState() {
    super.initState();
    Future(() async {
      final databasesPath = await getDatabasesPath();
      final path = join(databasesPath, databaseName);
      db = await openDatabase(
        path,
        version: migrationScripts.length,
        onCreate: (database, version) async {
          debugPrint('onCreate');
          for (var i = 0; i < version; i++) {
            await database.execute(migrationScripts[i]);
          }
        },
        onUpgrade: (database, oldVersion, newVersion) async {
          debugPrint('onUpgrade');
          for (var i = oldVersion; i < newVersion; i++) {
            await database.execute(migrationScripts[i]);
          }
        },
      );
      await query();
    });
  }

  Future<void> query() async {
    maps = await db?.rawQuery('SELECT * FROM Test');
    setState(() {});
  }

  Future<void> increment() async {
    await db?.transaction<void>((txn) async {
      await txn.rawInsert(
        // ignore: lines_longer_than_80_chars
        'INSERT INTO Test(name) VALUES("${DateTime.now().toLocal().toString()}")',
      );
    });
    await query();
  }

  @override
  void dispose() {
    Future(() async {
      await db?.close();
    });
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('sqflite'),
        centerTitle: true,
      ),
      body: SafeArea(
        child: ListView.builder(
          itemCount: maps?.length ?? 0,
          itemBuilder: (context, index) {
            final map = maps![index];
            final id = map['id'] ?? 0;
            final name = map['name'] ?? '';
            return ListTile(
              title: Text('id : $id'),
              subtitle: Text('$name'),
              dense: true,
            );
          },
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: increment,
        child: const Icon(Icons.add),
      ),
    );
  }
}

結果

データを追加後、アプリを再起動してもデータが残っています。

動画

公式リファレンス

sqflite | Flutter Package
Flutter plugin for SQLite, a self-contained, high-reliability, embedded, SQL database engine.

#86 SliverAppBar

SliverAppBarとは

アプリのヘッダーであるAppBarをスクロールで変化させたり、消したりしたい場合はSliverAppBarを使います。

SliverAppBarは主にCustomScrollViewNestedScrollViewと共に利用します。

Flutter Widget of the Weekの初期の頃に紹介されています。まさかの2回目です。

サンプルコード

import 'package:flutter/material.dart';

class SamplePage086 extends StatelessWidget {
  const SamplePage086({
    super.key,
  });

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: CustomScrollView(
        slivers: <Widget>[
          SliverAppBar(
            expandedHeight: 200,
            stretch: true,
            floating: true,
            flexibleSpace: const FlexibleSpaceBar(
              title: Text('SliverAppBar'),
              background: FlutterLogo(
                size: 256,
              ),
              stretchModes: <StretchMode>[
                StretchMode.zoomBackground,
                StretchMode.blurBackground,
                StretchMode.fadeTitle,
              ],
            ),
            onStretchTrigger: () async {
              debugPrint('onStretchTrigger');
            },
          ),
          SliverFixedExtentList(
            delegate: SliverChildBuilderDelegate((context, index) {
              return Container(
                alignment: Alignment.center,
                color: Colors.blue[100 * (index % 9)],
                child: Text('List Item $index'),
              );
            }),
            itemExtent: 50,
          ),
        ],
      ),
    );
  }
}

結果

SliverAppBarが伸びたり、スクロールすると見えなくなります

動画

公式リファレンス

SliverAppBar class - material library - Dart API
API docs for the SliverAppBar class from the material library, for the Dart programming language.

#87 InteractiveViewer

InteractiveViewerとは

InteractiveViewerを使うことでウィジェットの拡大や縮小やパンができます。

サンプルコード

import 'package:flutter/material.dart';

class SamplePage087 extends StatelessWidget {
  const SamplePage087({
    super.key,
  });

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('InteractiveViewer'),
        centerTitle: true,
      ),
      body: SafeArea(
        child: Center(
          child: InteractiveViewer(
            child: const FlutterLogo(
              size: 512,
            ),
          ),
        ),
      ),
    );
  }
}

結果

ピンチインするとFlutterのロゴが拡大できます。

動画

公式リファレンス

InteractiveViewer class - widgets library - Dart API
API docs for the InteractiveViewer class from the widgets library, for the Dart programming language.

さいごに

このシリーズ、終りが見えない。。。

そして追いつく前にYouTubeのFlutter Widget of the Weekが終わってしまい、悲しみ。

おすすめ参考書

リンク

GitHub - nobushiueshi/flutter_widget_of_the_week
Contribute to nobushiueshi/flutter_widget_of_the_week development by creating an account on GitHub.

コメント

タイトルとURLをコピーしました