PR

[Flutter]Flutter Widget of the Week「#109 Flow」、「#110 TabPageSelector」、「#111 Theme」

Flutter

はじめに

前回はFlutter Widget of the Weekの「#106 html」、「#107 RefreshIndicator」、「#108 font_awesome_flutter」を紹介しました。

今回はその続きで「#109 Flow」、「#110 TabPageSelector」、「#111 Theme」の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.9

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

#109 Flow

Flowとは

ウィジェットのリストをアニメーションで展開したりすることができるのがFlowです。

サンプルコード

import 'package:flutter/material.dart';

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

  @override
  State<SamplePage109> createState() => _SamplePage109State();
}

class _SamplePage109State extends State<SamplePage109>
    with SingleTickerProviderStateMixin {
  late AnimationController animationController;

  @override
  void initState() {
    super.initState();

    animationController = AnimationController(
      duration: const Duration(milliseconds: 250),
      vsync: this,
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Flow'),
        centerTitle: true,
      ),
      body: SafeArea(
        child: Flow(
          delegate: _SamplePage109Delegate(animationController),
          children: [
            FloatingActionButton(
              heroTag: 'menu',
              onPressed: () {
                animationController.status == AnimationStatus.completed
                    ? animationController.reverse()
                    : animationController.forward();
              },
              child: const Icon(Icons.menu),
            ),
            FloatingActionButton(
              heroTag: 'add',
              onPressed: () {},
              child: const Icon(Icons.add),
            ),
            FloatingActionButton(
              heroTag: 'remove',
              onPressed: () {},
              child: const Icon(Icons.remove),
            ),
          ],
        ),
      ),
    );
  }
}

class _SamplePage109Delegate extends FlowDelegate {
  _SamplePage109Delegate(this.animation) : super(repaint: animation);

  final Animation<double> animation;

  @override
  void paintChildren(FlowPaintingContext context) {
    for (var i = context.childCount - 1; i >= 0; i--) {
      final offset = i * animation.value * 50;
      context.paintChild(
        i,
        transform: Matrix4.translationValues(
          offset,
          offset,
          0,
        ),
      );
    }
  }

  @override
  bool shouldRepaint(covariant _SamplePage109Delegate oldDelegate) {
    return animation != oldDelegate.animation;
  }
}

結果

動画

公式リファレンス

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

#110 TabPageSelector

TabPageSelectorとは

リスト内の現在位置を示すドット、SwiftだとPageControlを実現できるウィジェットです。

サンプルコード

import 'package:flutter/material.dart';

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

  @override
  State<SamplePage110> createState() => _SamplePage110State();
}

class _SamplePage110State extends State<SamplePage110>
    with SingleTickerProviderStateMixin {
  late final TabController tabController;

  final icons = const <IconData>[
    Icons.home,
    Icons.drive_eta,
    Icons.settings,
  ];

  @override
  void initState() {
    super.initState();
    tabController = TabController(
      length: 3,
      vsync: this,
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('TabPageSelector'),
        centerTitle: true,
        bottom: TabBar(
          controller: tabController,
          tabs: icons
              .map(
                (icon) => Tab(
                  child: Icon(icon),
                ),
              )
              .toList(),
        ),
      ),
      body: SafeArea(
        child: Stack(
          children: [
            TabBarView(
              controller: tabController,
              children: icons
                  .map(
                    (icon) => Center(
                      child: Icon(
                        icon,
                        size: 128,
                      ),
                    ),
                  )
                  .toList(),
            ),
            Positioned(
              bottom: 0,
              left: 0,
              right: 0,
              child: Center(
                child: TabPageSelector(
                  controller: tabController,
                ),
              ),
            )
          ],
        ),
      ),
    );
  }
}

結果

動画

公式リファレンス

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

#111 Theme

Themeとは

その名の通り、アプリのデザインのテーマを変更できる仕組みです。

マテリアルデザインのプライマリーカラーやフォントなど自分好みにカスタマイズできます。

サンプルコード

import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';

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

  @override
  State<SamplePage111> createState() => _SamplePage111State();
}

class _SamplePage111State extends State<SamplePage111> {
  int _counter = 0;

  @override
  Widget build(BuildContext context) {
    return Theme(
      data: Theme.of(context).copyWith(
        colorScheme: ColorScheme.fromSwatch(
          primarySwatch: Colors.orange,
        ),
        textTheme: GoogleFonts.emilysCandyTextTheme(),
        scaffoldBackgroundColor: Colors.orange[100],
      ),
      child: Scaffold(
        appBar: AppBar(
          title: const Text('Theme'),
          centerTitle: true,
        ),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              const Text(
                'You have pushed the button this many times:',
              ),
              Text(
                '$_counter',
                style: Theme.of(context).textTheme.headline4,
              ),
            ],
          ),
        ),
        floatingActionButton: FloatingActionButton(
          onPressed: () {
            setState(() {
              _counter += 1;
            });
          },
          tooltip: 'Increment',
          child: const Icon(Icons.add),
        ), //
      ),
    );
  }
}

結果

動画

公式リファレンス

Theme class - material library - Dart API
API docs for the Theme class from the material 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をコピーしました