はじめに
前回は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.
コメント