概要
- 自定义AppBar
- AppBar笼罩层
一、Appbar源码解析
打开Scaffold appBar字段,我们可以看到,源码中appBar的类型是PreferredSizeWidget,而PreferredSizeWidget本身是一个抽象类,只需要实现Size get preferredSize。那也就是说,我们可以完全抛开Flutter自带的Appbar,自己通过实现PreferredSizeWidget来自定义Appbar。以下代码即可实现用户自定义的Appbar,不需要使用其自带库的。
import 'package:flutter/material.dart';
class CustomBar extends StatelessWidget implements PreferredSizeWidget{
final bool? back;
final Widget? child;
final double? appBarHeight;
final Color? appBarBackgroupColor;
final EdgeInsetsGeometry? appBarPadding;
final bool? spaceBar;
final Color? spaceBarBackgroupColor;
final Decoration? decoration;
/// * back 是否显示返回按钮
/// * child 主内容区
/// * appBar 头部导航
/// * appBarHeight 头部导航高度
/// * appBarBackgroupColor 底色
/// * appBarPadding 内边距
/// * spaceBar 状态栏是否占用高度
/// * spaceBarBackgroupColor 占用的高度底色
const CustomBar({
Key? key,
this.back=true,
this.child,
this.appBarHeight=40.0,
this.appBarBackgroupColor=Colors.transparent,
this.appBarPadding=const EdgeInsets.fromLTRB(5, 0, 5, 0),
this.spaceBar=true,
this.spaceBarBackgroupColor=Colors.transparent,
this.decoration
}) : super(key: key);
@override
Size get preferredSize => const Size.fromHeight(200);
List<Widget> renderAppBarChildren(BuildContext context){
late List<Widget> children =[];
if(back!){
children.add(
InkWell(
child:const Icon(
IconData(0xe710,fontFamily:'iconfont'),
color: Color(0xFF262626),
size:30
),
onTap: (){
Navigator.pop(context);
},
)
);
}
if(child != null){
children.add(
Expanded(child: child!)
);
}
return children;
}
List<Widget> renderChildren(BuildContext context){
final double topHeihgt = MediaQuery.of(context).padding.top;
late List<Widget> reslut=[];
if(spaceBar!){
reslut.add(
Container(
padding: EdgeInsets.only(top: topHeihgt),
color: spaceBarBackgroupColor,
)
);
}
if(child != null){
reslut.add(
Container(
color: appBarBackgroupColor,
height: appBarHeight,
padding: appBarPadding,
child: Row(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: renderAppBarChildren(context),
),
)
);
}
return reslut;
}
@override
Widget build(BuildContext context) {
late double allHeihgt = 0;
if(spaceBar!){
allHeihgt = allHeihgt+MediaQuery.of(context).padding.top;
}
if(child != null){
allHeihgt =allHeihgt+appBarHeight!;
}
return Container(
height: allHeihgt,
decoration:decoration??null,
child: Column(
children: renderChildren(context)
),
);
}
}
这里需要特别注意状态栏的高度可以通过MediaQuery.of(context).padding.top;来获取,灵活控制。在安卓下,状态栏是有笼罩层的。可以再runApp()之后去掉其笼罩。
runApp(const MyApp())
if(Platform.isAndroid){
SystemChrome.setSystemUIOverlayStyle(const SystemUiOverlayStyle(
statusBarColor: Colors.transparent, //全局设置透明
))
}