_Assertionerror
上タブを作っていたときにハマった!
Tabbarを作成していたときに、Widgetのエラーが出てきた!
やったことは、ドキュメントのソースコードを書き換えて使っただけだった!
これを作ります
こちらのコードを書き換えて使った!
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({super.key});
static const String _title = 'Flutter Code Sample';
Widget build(BuildContext context) {
return const MaterialApp(
title: _title,
home: MyStatefulWidget(),
);
}
}
class MyStatefulWidget extends StatefulWidget {
const MyStatefulWidget({super.key});
State<MyStatefulWidget> createState() => _MyStatefulWidgetState();
}
/// [AnimationController]s can be created with `vsync: this` because of
/// [TickerProviderStateMixin].
class _MyStatefulWidgetState extends State<MyStatefulWidget>
with TickerProviderStateMixin {
late TabController _tabController;
void initState() {
super.initState();
_tabController = TabController(length: 3, vsync: this);
}
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('TabBar Widget'),
bottom: TabBar(
controller: _tabController,
tabs: const <Widget>[
Tab(
icon: Icon(Icons.cloud_outlined),
),
Tab(
icon: Icon(Icons.beach_access_sharp),
),
Tab(
icon: Icon(Icons.brightness_5_sharp),
),
],
),
),
body: TabBarView(
controller: _tabController,
children: const <Widget>[
Center(
child: Text("It's cloudy here"),
),
Center(
child: Text("It's rainy here"),
),
Center(
child: Text("It's sunny here"),
),
],
),
);
}
}
こちらのコードを書きかえて、TextWidgetから、WidgetClassに変更したが、buildができなかった?
原因は、DefaultTabControllerの方ではなくて、自分で設定できる方のTabControllerを使ったことが原因らしい?
しかし、新しくプロジェクトを作成してドキュメントのコードを実行してもエラーにならなかった?
エラーを解消した方法
優秀なメンターさんからのアドバイスによると、TabBarの中にonTapがないかららしい!
onTap: ()の中に、indexを書いて、_tabController.animateTo()の中にもindexを書くと、buildが通った???
return Scaffold(
appBar: AppBar(
centerTitle: true, // Androidの場合タイトルを中央寄せにする.
title: const Text('Tabbar'),
bottom: TabBar(
onTap: (index) {
_tabController.animateTo(index);
},
controller: _tabController,
書いてあるコードについて調べてみた
with TickerProviderStateMixinとは何か?
TickerMode で定義されるように、現在のツリーが有効な間だけティックするように設定された Ticker オブジェクトを提供します。
このミキシンを使用するクラスで AnimationController を作成するには、新しいアニメーションコントローラを作成するたびに、vsync: this をアニメーションコントローラのコンストラクタに渡します。
Stateの有効期間中、単一のTickerしか持たない場合(例えば、単一のAnimationControllerのみ)、SingleTickerProviderStateMixinを使用する方が効率的である。これは一般的なケースです。
Dartパッケージ
TabControllerとは何か?
/// TabBar]と[TabBarView]が必要とする状態を管理するオブジェクトを作成します。
/// [TabBarView]の状態を管理するオブジェクトを作成します。
///
/// [length]はNULLや負の値であってはいけません。一般的には、1より大きい値です。
/// 通常は1より大きい値、つまり通常2つ以上のタブがあります。長さ] は
/// [TabBar.tabs] と [TabBarView.children] の長さと一致する必要があります。
///
/// `initialIndex` は [length] で指定された有効な値でなければならず、null であってはいけません。もし
/// [length] が 0 の場合、 `initialIndex` は 0 (デフォルト) でなければなりません。
.animateTo(index)とは何か?
クラスが含まれています。TabController Type: void Function(int, {Curve 曲線, Duration? 持続時間})
indexとpreviousIndexを即座に設定し、現在値からindexまでのアニメーションを再生する。
アニメーションの実行中はindexIsChangingがtrueになります。アニメーションが完了すると、offsetは0.0になります。
Dartパッケージ
今回使用したコード
切り替える画面を作成する。2ページ、3ページとしておきましょうか...
2ページ
import 'package:flutter/material.dart';
class SecondePage extends StatelessWidget {
const SecondePage({Key? key}) : super(key: key);
Widget build(BuildContext context) {
return const Scaffold(
body: Center(
child: Text('2ページ',
style: TextStyle(fontSize: 25, color: Colors.redAccent)),
),
);
}
}
3ページ
import 'package:flutter/material.dart';
class ThirdPage extends StatelessWidget {
const ThirdPage({Key? key}) : super(key: key);
Widget build(BuildContext context) {
return const Scaffold(
body: Center(
child: Text('3ページ',
style: TextStyle(fontSize: 25, color: Colors.blueAccent)),
),
);
}
}
Tabのページ
import 'package:counter/second_page.dart';
import 'package:counter/third_page.dart';
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
// This widget is the root of your application.
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const TabbarExample(),
);
}
}
class TabbarExample extends StatefulWidget {
const TabbarExample({Key? key}) : super(key: key);
State<TabbarExample> createState() => _TabbarExampleState();
}
class _TabbarExampleState extends State<TabbarExample>
with TickerProviderStateMixin {
late TabController _tabController;
void initState() {
super.initState();
_tabController = TabController(length: 2, vsync: this);
}
void dispose() {
super.dispose();
_tabController.dispose();
print('コントローラーの状態を破棄!');
}
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
centerTitle: true, // Androidの場合タイトルを中央寄せにする.
title: const Text('Tabbar'),
bottom: TabBar(
onTap: (index) {// onTapを追加。()の中にindexを書く.
_tabController.animateTo(index);// animateTo()の中にindexを書く.
},
controller: _tabController,
tabs: const <Widget>[
Tab(
icon: Icon(Icons.cloud_outlined),
),
Tab(
icon: Icon(Icons.beach_access_sharp),
),
],
),
),
body: TabBarView(
controller: _tabController,
children: const <Widget>[
// TextWidgetをWedgetClassに変えてページを表示できるようにする.
SecondePage(), ThirdPage()
],
),
);
}
}
まとめ
私が使ったアプリでは、go_router導入していたのですが、エラーの原因はpackageの影響ではなさそうです???
サンプルアプリは、問題なく動作しているので動作検証はできたと思われるので、一旦問題は解決したと思われます。
Discussion