タブを上じゃなくてページの途中で使いたくて書きました。
呼び出し側はこんな感じInnerTabController(
initailIndex: 0,
tebSpaceFlex: 3,
freeSpaceFlex: 2,
tabs: [
Tab(child: Text('title1')),
Tab(child: Text('title2')),
],
bodys: [Text('test3'), Text('test2')],
),
いろいろ書きましたが、ちょっと変なことしてます。
TabControllerを使うときにTabBarViewで高さを指定する必要があったので、
一度描画してサイズを取得してそのあとに
サイズを指定して、TabBarViewを表示するということをしてます。
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
class InnerTabController extends StatefulWidget {
final int initailIndex;
final List<Widget> tabs;
final List<Widget> bodys;
final int tebSpaceFlex; // タブを左寄せする場合の割合幅
final int freeSpaceFlex; // タブを左寄せする場合の右側の割合幅
const InnerTabController({
Key? key,
required this.initailIndex,
required this.tabs,
required this.bodys,
this.tebSpaceFlex = 1,
this.freeSpaceFlex = 0,
}) : super(key: key);
@override
InnerTabControllerState createState() => InnerTabControllerState();
}
class InnerTabControllerState extends State<InnerTabController>
with SingleTickerProviderStateMixin {
List<GlobalKey> keys = [];
List<double?> bodyHeights = [];
late TabController tabController;
@override
void initState() {
tabController = TabController(
vsync: this,
length: widget.tabs.length,
initialIndex: widget.initailIndex);
for (int i = 0; i < widget.tabs.length; i++) {
bodyHeights.add(null);
keys.add(GlobalKey());
}
SchedulerBinding.instance.addPostFrameCallback((_) {
setState(() {
for (int i = 0; i < widget.tabs.length; i++) {
bodyHeights[i] = keys[i].currentContext?.size?.height;
}
});
});
super.initState();
}
@override
void dispose() {
tabController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
if (widget.tabs.length != widget.bodys.length) {
throw Exception('tabsとbodysとbodySizesの配列の数を同じにして下さい。');
}
return Column(
children: [
Row(
children: [
Flexible(
flex: widget.tebSpaceFlex,
child: TabBar(
controller: tabController,
tabs: widget.tabs,
indicatorColor: kDefColor,
indicatorSize: TabBarIndicatorSize.label,
),
),
Flexible(
flex: widget.freeSpaceFlex,
child: const SizedBox(),
),
],
),
const Divider(height: 0),
if (bodyHeights[tabController.index] == null)
Container(
key: keys[tabController.index],
alignment: Alignment.centerLeft,
child: widget.bodys[tabController.index],
)
else
SizedBox(
height: bodyHeights[tabController.index],
child: TabBarView(
controller: tabController,
children: widget.bodys,
),
),
],
);
}
}
NestedScrollView
のheaderSliverBuilder
とかに
SliverToBoxAdapter
を使う方法もある。
Flutter開発で知らないと損すること