Flutter实战项目-第五篇 自定义AppBar

本文详细介绍了如何在Flutter中自定义AppBar,通过实现PreferredSizeWidget接口,无需使用默认库。示例代码展示了如何创建一个包含返回按钮、主内容区等功能的自定义头部导航,并提供了对状态栏高度和背景颜色的控制。同时,文章提到了在Android平台上设置透明状态栏的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

概要

  • 自定义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, //全局设置透明
   ))
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值