如何创建一个具有上方固定元素和下方浮动元素的 SliverAppBar?
How to create a SliverAppBar, that has a upper pinned and lower floating element?
所以我想创建一个 SliverAppBar,其中上半部分固定并始终显示。
即使未到达列表顶部,下部也必须浮动并在向下滚动时显示。
让它对我有用的唯一方法是在彼此之上添加 2 个 sliverappbar,但我觉得这不是最好的方法。那么如何正确完成呢?
return Scaffold(
body: NestedScrollView(
body: ListView.builder(
itemBuilder: (context, index) => Text(index.toString())),
headerSliverBuilder: (context, hasScrolled) {
return [
const SliverAppBar(
title: Text('pinned'),
pinned: true,
centerTitle: true,
),
const SliverAppBar(
floating: true,
snap: true,
title: Text('floating'),
),
];
},
),
);
所以从视觉上看,这就是我要找的东西,我只是不确定实现。
这是你想要的吗,顺便说一句,它不是动画的。
class CUstomScrolling extends StatefulWidget {
const CUstomScrolling({Key? key}) : super(key: key);
@override
_CUstomScrollingState createState() => _CUstomScrollingState();
}
class _CUstomScrollingState extends State<CUstomScrolling> {
final ScrollController controller = ScrollController();
bool _showNavBar = true;
@override
void initState() {
super.initState();
controller.addListener(() {
if (controller.hasClients) {
if (controller.position.userScrollDirection ==
ScrollDirection.forward &&
!_showNavBar) {
setState(() {
_showNavBar = true;
});
} else if (controller.position.userScrollDirection ==
ScrollDirection.reverse &&
_showNavBar) {
setState(() {
_showNavBar = false;
});
}
}
});
}
@override
void dispose() {
controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: NestedScrollView(
body: ListView.builder(
controller: controller,
itemBuilder: (context, index) => Text(
index.toString(),
),
),
headerSliverBuilder: (context, hasScrolled) {
return [
const SliverAppBar(
title: Text('pinned'),
pinned: true,
centerTitle: true,
),
if (_showNavBar)
const SliverAppBar(
pinned: false,
floating: true,
title: Text('floating'),
),
];
},
),
);
}
}
这样就可以了:
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Title')),
body: CustomScrollView(
slivers: [
SliverAppBar(
floating: true,
title: Text('Test'),
),
SliverList(
delegate: SliverChildBuilderDelegate(
(context, index) => ListTile(title: Text('Item #$index')),
childCount: 1000,
),
),
],
),
);
所以我想创建一个 SliverAppBar,其中上半部分固定并始终显示。 即使未到达列表顶部,下部也必须浮动并在向下滚动时显示。
让它对我有用的唯一方法是在彼此之上添加 2 个 sliverappbar,但我觉得这不是最好的方法。那么如何正确完成呢?
return Scaffold(
body: NestedScrollView(
body: ListView.builder(
itemBuilder: (context, index) => Text(index.toString())),
headerSliverBuilder: (context, hasScrolled) {
return [
const SliverAppBar(
title: Text('pinned'),
pinned: true,
centerTitle: true,
),
const SliverAppBar(
floating: true,
snap: true,
title: Text('floating'),
),
];
},
),
);
所以从视觉上看,这就是我要找的东西,我只是不确定实现。
这是你想要的吗,顺便说一句,它不是动画的。
class CUstomScrolling extends StatefulWidget {
const CUstomScrolling({Key? key}) : super(key: key);
@override
_CUstomScrollingState createState() => _CUstomScrollingState();
}
class _CUstomScrollingState extends State<CUstomScrolling> {
final ScrollController controller = ScrollController();
bool _showNavBar = true;
@override
void initState() {
super.initState();
controller.addListener(() {
if (controller.hasClients) {
if (controller.position.userScrollDirection ==
ScrollDirection.forward &&
!_showNavBar) {
setState(() {
_showNavBar = true;
});
} else if (controller.position.userScrollDirection ==
ScrollDirection.reverse &&
_showNavBar) {
setState(() {
_showNavBar = false;
});
}
}
});
}
@override
void dispose() {
controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: NestedScrollView(
body: ListView.builder(
controller: controller,
itemBuilder: (context, index) => Text(
index.toString(),
),
),
headerSliverBuilder: (context, hasScrolled) {
return [
const SliverAppBar(
title: Text('pinned'),
pinned: true,
centerTitle: true,
),
if (_showNavBar)
const SliverAppBar(
pinned: false,
floating: true,
title: Text('floating'),
),
];
},
),
);
}
}
这样就可以了:
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Title')),
body: CustomScrollView(
slivers: [
SliverAppBar(
floating: true,
title: Text('Test'),
),
SliverList(
delegate: SliverChildBuilderDelegate(
(context, index) => ListTile(title: Text('Item #$index')),
childCount: 1000,
),
),
],
),
);