Flutterで次のレイアウトを実装する必要があります。
ユーザーがスクロールするときに、レイアウト全体をスクロールさせたい(ヘッダーとタブバーを非表示にする)。ただし、TabBarViewには制限された高さがなく、ListViewsは子に制限された高さを提供しないため、ListView内にTabBarViewをネストすることはできません。
私はすでにこれらの質問を見てきましたが、それらすべてがこのユースケースに対して不十分な答えを持っています:
class SliverWithTabBar extends StatefulWidget {
@override
_SliverWithTabBarState createState() => _SliverWithTabBarState();
}
class _SliverWithTabBarState extends State<SliverWithTabBar> with SingleTickerProviderStateMixin {
TabController controller;
@override
void initState() {
super.initState();
controller = TabController(length: 3, vsync: this);
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: NestedScrollView(
headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
return [
SliverAppBar(
pinned: false,
backgroundColor: Colors.white,
flexibleSpace: FlexibleSpaceBar(
collapseMode: CollapseMode.pin,
background: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
height: 200.0,
width: double.infinity,
color: Colors.grey,
child: FlutterLogo(),
),
Padding(
padding: const EdgeInsets.all(10.0),
child: Text(
'Business Office',
style: TextStyle(fontSize: 25.0),
textAlign: TextAlign.left,
),
),
Padding(
padding: const EdgeInsets.all(10.0),
child: Text(
'Open now\nStreet Address, 299\nCity, State',
style: TextStyle(fontSize: 15.0),
textAlign: TextAlign.left,
),
),
Padding(
padding: const EdgeInsets.only(right: 10.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Icon(Icons.share),
Padding(
padding: const EdgeInsets.only(left: 10.0),
child: Icon(Icons.favorite),
),
],
),
)
],
),
),
expandedHeight: 380.0,
bottom: TabBar(
indicatorColor: Colors.black,
labelColor: Colors.black,
tabs: [
Tab(text: 'POSTS'),
Tab(text: 'DETAILS'),
Tab(text: 'FOLLOWERS'),
],
controller: controller,
),
)
];
},
body: ListView.builder(
itemCount: 100,
itemBuilder: (BuildContext context, int index) {
return Card(
color: index % 2 == 0 ? Colors.blue : Colors.green,
child: Container(
alignment: Alignment.center,
width: double.infinity,
height: 100.0,
child: Text(
'Flutter is awesome',
style: TextStyle(fontSize: 18.0),
),
),
);
},
),
),
);
}
}
Sliver
を実現するには、NestedScrollView
ウィジェットを探す必要があります。
これにより、headerSliverBuilderプロパティが得られます。このプロパティでは、本文ウィジェットをスクロールしたときに非表示にしたり、画面の上部に固定したりできるヘッダーを実際に収めることができます。この特定の例では、ListView
です。
RenderSliver のドキュメントをご覧ください。