如何在 Flutter 中自定义 SliverAppBar?
How to make custom SliverAppBar in Flutter?
Sliver App Bar
大家好,我正在开发 Sliver Appbar,但我想要这种类型的自定义 SliverAppbar,我该如何实现?
试试这个并根据您的要求进行自定义
class MyWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return CustomScrollView(
slivers: [
SliverAppBar(
expandedHeight: 300,
pinned: true,
flexibleSpace: FlexibleSpaceBar(
title: const FittedBox(
child: Text("loadedServices.title"),
),
background: Image.network(
"https://picsum.photos/250?image=9",
fit: BoxFit.fill,
),
),
),
SliverList(
delegate: SliverChildListDelegate(
[
const SizedBox(height: 30.0),
Padding(
padding: const EdgeInsets.only(left: 8.0, right: 8.0),
child: Column(
children: [
const Text(
"loadedServices.description",
textAlign: TextAlign.justify,
style: TextStyle(
fontFamily: 'OpenSans',
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 20),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Card(
elevation: 8,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(30),
topRight: Radius.circular(30),
),
),
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 12.0,
vertical: 8,
),
child: Column(
children: const [
Text(
"loadedServices.totalClass",
style: TextStyle(fontSize: 14),
),
Text(
"Total Class",
style: TextStyle(fontSize: 12),
),
],
),
),
),
Card(
elevation: 8,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(30),
topRight: Radius.circular(30),
),
),
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 12.0,
vertical: 8,
),
child: Column(
children: const [
Text(
"loadedServices.classDuration",
style: TextStyle(fontSize: 14),
),
Text(
"Class Duration",
style: TextStyle(fontSize: 12),
),
],
),
),
),
Card(
elevation: 8,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(30),
topRight: Radius.circular(30),
),
),
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 12.0,
vertical: 8,
),
child: Column(
children: const [
Text(
"loadedServices.courseDuration",
style: TextStyle(fontSize: 14),
),
Text(
"Course Duration",
style: TextStyle(fontSize: 12),
),
],
),
),
),
],
),
const SizedBox(height: 20),
const Text(
'For further Information make a phone call or contact our WhatsApp Number',
textAlign: TextAlign.justify,
style: TextStyle(
fontSize: 20.0,
color: Colors.green,
fontWeight: FontWeight.bold,
),
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const SizedBox(width: 10),
const Text(
'Or',
style: TextStyle(
fontSize: 20.0,
//color: Colors.green,
fontWeight: FontWeight.bold,
),
),
IconButton(
color: Colors.green,
icon: const Icon(
Icons.favorite,
size: 35,
),
onPressed: (){
},
),
],
),
const SizedBox(height: 20),
const Text(
'Visit Our WebSite',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 20.0,
color: Colors.green,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 10),
const SizedBox(height: 20),
const Text(
'Visit Our Social Platform',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 20.0,
color: Colors.green,
fontWeight: FontWeight.bold,
),
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
IconButton(
color: Colors.greenAccent,
icon: const Icon(
Icons.favorite,
size: 35,
),
onPressed: (){},
),
IconButton(
color: Colors.red,
icon: const Icon(
Icons.favorite,
size: 35,
),
onPressed: (){},
),
],
),
],
),
),
const SizedBox(height: 260),
],
),
),
],
);
}
}
您可以尝试使用 SliverPersistentHeader
小部件和 CustomScrollView
中包含的一堆条子来模拟相同的情况。您需要做的就是给 AppBar
、SliverPersistentHeader
和第一个 Sliver
相同的背景颜色。
看看下面的代码(抱歉格式不正确)。最后我还附上了一张 gif 动图(抱歉设计不佳)。
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
static const String _title = 'Flutter Code Sample';
@override
Widget build(BuildContext context) {
return const MaterialApp(
title: _title,
home: MyStatefulWidget(),
debugShowCheckedModeBanner: false,
);
}
}
class MyStatefulWidget extends StatefulWidget {
const MyStatefulWidget({Key? key}) : super(key: key);
@override
State<MyStatefulWidget> createState() => _MyStatefulWidgetState();
}
class _MyStatefulWidgetState extends State<MyStatefulWidget> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(backgroundColor: const Color(0xff222222),
title: const Text("JazzCash"),
elevation: 0,
actions: const [Icon(Icons.info), Icon(Icons.notifications)]),
body: CustomScrollView(
slivers: <Widget>[
// persistent header
SliverPersistentHeader(
pinned: true,
delegate: SliverAppBarDelegate(
minHeight: 60.0,
maxHeight: 60.0,
child: Container(
color: const Color(0xff222222), child:Row(children:
const [SizedBox(width: 10), CircleAvatar(), SizedBox(width: 10), Text("Muhammad", style: TextStyle(fontSize: 20, color: Colors.white)),
])),
),
),
SliverList(
delegate: SliverChildListDelegate(
[
// first sliver
Container(color: const Color(0xff222222),
padding: const EdgeInsets.all(10),
child: Column(crossAxisAlignment: CrossAxisAlignment.start,
children: [const Text("Login -->", style: TextStyle(color: Colors.amber, fontSize: 25, fontWeight: FontWeight.bold)),
const Text("to Make Payments", style: TextStyle(color: Colors.white, fontSize: 25, fontWeight: FontWeight.bold)),
const SizedBox(height: 10),
Row(children: [ElevatedButton(onPressed: (){}, child: const Text("Add money")), const SizedBox(width: 20), ElevatedButton(onPressed: (){}, child: const Text("Add account"))])
])),
Container(color: Colors.purple, height: 150.0),
Container(color: Colors.green, height: 150.0),
],
),
),
],
),
);
}
}
// defining delegate for sliverpersistendheader
class SliverAppBarDelegate extends SliverPersistentHeaderDelegate {
SliverAppBarDelegate({
@required this.minHeight,
@required this.maxHeight,
@required this.child,
});
final double? minHeight;
final double? maxHeight;
final Widget? child;
@override
double get minExtent => minHeight!;
@override
double get maxExtent => math.max(maxHeight!, minHeight!);
@override
Widget build(
BuildContext context,
double shrinkOffset,
bool overlapsContent)
{
return SizedBox.expand(child: child);
}
@override
bool shouldRebuild(SliverAppBarDelegate oldDelegate) {
return maxHeight != oldDelegate.maxHeight ||
minHeight != oldDelegate.minHeight ||
child != oldDelegate.child;
}
}
Sliver App Bar
大家好,我正在开发 Sliver Appbar,但我想要这种类型的自定义 SliverAppbar,我该如何实现?
试试这个并根据您的要求进行自定义
class MyWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return CustomScrollView(
slivers: [
SliverAppBar(
expandedHeight: 300,
pinned: true,
flexibleSpace: FlexibleSpaceBar(
title: const FittedBox(
child: Text("loadedServices.title"),
),
background: Image.network(
"https://picsum.photos/250?image=9",
fit: BoxFit.fill,
),
),
),
SliverList(
delegate: SliverChildListDelegate(
[
const SizedBox(height: 30.0),
Padding(
padding: const EdgeInsets.only(left: 8.0, right: 8.0),
child: Column(
children: [
const Text(
"loadedServices.description",
textAlign: TextAlign.justify,
style: TextStyle(
fontFamily: 'OpenSans',
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 20),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Card(
elevation: 8,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(30),
topRight: Radius.circular(30),
),
),
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 12.0,
vertical: 8,
),
child: Column(
children: const [
Text(
"loadedServices.totalClass",
style: TextStyle(fontSize: 14),
),
Text(
"Total Class",
style: TextStyle(fontSize: 12),
),
],
),
),
),
Card(
elevation: 8,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(30),
topRight: Radius.circular(30),
),
),
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 12.0,
vertical: 8,
),
child: Column(
children: const [
Text(
"loadedServices.classDuration",
style: TextStyle(fontSize: 14),
),
Text(
"Class Duration",
style: TextStyle(fontSize: 12),
),
],
),
),
),
Card(
elevation: 8,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(30),
topRight: Radius.circular(30),
),
),
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 12.0,
vertical: 8,
),
child: Column(
children: const [
Text(
"loadedServices.courseDuration",
style: TextStyle(fontSize: 14),
),
Text(
"Course Duration",
style: TextStyle(fontSize: 12),
),
],
),
),
),
],
),
const SizedBox(height: 20),
const Text(
'For further Information make a phone call or contact our WhatsApp Number',
textAlign: TextAlign.justify,
style: TextStyle(
fontSize: 20.0,
color: Colors.green,
fontWeight: FontWeight.bold,
),
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const SizedBox(width: 10),
const Text(
'Or',
style: TextStyle(
fontSize: 20.0,
//color: Colors.green,
fontWeight: FontWeight.bold,
),
),
IconButton(
color: Colors.green,
icon: const Icon(
Icons.favorite,
size: 35,
),
onPressed: (){
},
),
],
),
const SizedBox(height: 20),
const Text(
'Visit Our WebSite',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 20.0,
color: Colors.green,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 10),
const SizedBox(height: 20),
const Text(
'Visit Our Social Platform',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 20.0,
color: Colors.green,
fontWeight: FontWeight.bold,
),
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
IconButton(
color: Colors.greenAccent,
icon: const Icon(
Icons.favorite,
size: 35,
),
onPressed: (){},
),
IconButton(
color: Colors.red,
icon: const Icon(
Icons.favorite,
size: 35,
),
onPressed: (){},
),
],
),
],
),
),
const SizedBox(height: 260),
],
),
),
],
);
}
}
您可以尝试使用 SliverPersistentHeader
小部件和 CustomScrollView
中包含的一堆条子来模拟相同的情况。您需要做的就是给 AppBar
、SliverPersistentHeader
和第一个 Sliver
相同的背景颜色。
看看下面的代码(抱歉格式不正确)。最后我还附上了一张 gif 动图(抱歉设计不佳)。
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
static const String _title = 'Flutter Code Sample';
@override
Widget build(BuildContext context) {
return const MaterialApp(
title: _title,
home: MyStatefulWidget(),
debugShowCheckedModeBanner: false,
);
}
}
class MyStatefulWidget extends StatefulWidget {
const MyStatefulWidget({Key? key}) : super(key: key);
@override
State<MyStatefulWidget> createState() => _MyStatefulWidgetState();
}
class _MyStatefulWidgetState extends State<MyStatefulWidget> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(backgroundColor: const Color(0xff222222),
title: const Text("JazzCash"),
elevation: 0,
actions: const [Icon(Icons.info), Icon(Icons.notifications)]),
body: CustomScrollView(
slivers: <Widget>[
// persistent header
SliverPersistentHeader(
pinned: true,
delegate: SliverAppBarDelegate(
minHeight: 60.0,
maxHeight: 60.0,
child: Container(
color: const Color(0xff222222), child:Row(children:
const [SizedBox(width: 10), CircleAvatar(), SizedBox(width: 10), Text("Muhammad", style: TextStyle(fontSize: 20, color: Colors.white)),
])),
),
),
SliverList(
delegate: SliverChildListDelegate(
[
// first sliver
Container(color: const Color(0xff222222),
padding: const EdgeInsets.all(10),
child: Column(crossAxisAlignment: CrossAxisAlignment.start,
children: [const Text("Login -->", style: TextStyle(color: Colors.amber, fontSize: 25, fontWeight: FontWeight.bold)),
const Text("to Make Payments", style: TextStyle(color: Colors.white, fontSize: 25, fontWeight: FontWeight.bold)),
const SizedBox(height: 10),
Row(children: [ElevatedButton(onPressed: (){}, child: const Text("Add money")), const SizedBox(width: 20), ElevatedButton(onPressed: (){}, child: const Text("Add account"))])
])),
Container(color: Colors.purple, height: 150.0),
Container(color: Colors.green, height: 150.0),
],
),
),
],
),
);
}
}
// defining delegate for sliverpersistendheader
class SliverAppBarDelegate extends SliverPersistentHeaderDelegate {
SliverAppBarDelegate({
@required this.minHeight,
@required this.maxHeight,
@required this.child,
});
final double? minHeight;
final double? maxHeight;
final Widget? child;
@override
double get minExtent => minHeight!;
@override
double get maxExtent => math.max(maxHeight!, minHeight!);
@override
Widget build(
BuildContext context,
double shrinkOffset,
bool overlapsContent)
{
return SizedBox.expand(child: child);
}
@override
bool shouldRebuild(SliverAppBarDelegate oldDelegate) {
return maxHeight != oldDelegate.maxHeight ||
minHeight != oldDelegate.minHeight ||
child != oldDelegate.child;
}
}