You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter如何在自定义AppBar中间定位Widget并将头像放入预留圆形凹槽

Flutter自定义AppBar凹槽嵌入头像解决方案

核心问题梳理

  • 你之前将Stack放在AppBar的actions区域,actions是AppBar右侧的操作容器,本身宽度受限,Positioned的坐标是相对于父Stack而非整个屏幕,自然无法定位到AppBar中间位置
  • 错误使用全屏幕高度MediaQuery.of(context).size.height作为Positioned的top值,会直接把头像移出可视区域
  • CustomShapeBorder的Path逻辑错误,重复添加椭圆且未设置挖空规则,无法得到正确的凹槽效果

完整修改代码

import 'package:flutter/material.dart';

class ProfileAppBar extends StatelessWidget implements PreferredSizeWidget {
  final String? name;
  const ProfileAppBar({super.key, this.name});

  // 调整AppBar高度,预留凹槽空间
  @override
  Size get preferredSize => Size.fromHeight(kToolbarHeight + 10);

  @override
  Widget build(BuildContext context) {
    final double width = MediaQuery.of(context).size.width;
    final double appBarHeight = preferredSize.height;

    // 外层用Stack承载AppBar和定位头像
    return Stack(
      clipBehavior: Clip.none, // 允许子组件超出Stack边界显示
      children: [
        // 底层自定义凹槽形状的AppBar
        AppBar(
          shape: const CustomShapeBorder(),
          leading: Row(
            children: [
              IconButton(
                icon: const Icon(Icons.home),
                onPressed: () {
                  Navigator.pushReplacementNamed(context, "/home");
                },
              ),
            ],
          ),
          title: Text(name ?? 'Username'),
          actions: <Widget>[
            IconButton(
              iconSize: 30,
              icon: const Icon(Icons.settings),
              alignment: Alignment.centerRight,
              padding: const EdgeInsets.only(right: 20),
              onPressed: () {
                const profileRoute = "/profile";
                bool isNewRouteSameAsCurrent = false;

                Navigator.popUntil(context, (route) {
                  if (route.settings.name == profileRoute) {
                    isNewRouteSameAsCurrent = true;
                  }
                  return true;
                });

                if (!isNewRouteSameAsCurrent) {
                  Navigator.pushReplacementNamed(context, profileRoute);
                }
              },
            )
          ],
        ),
        // 顶层定位头像,刚好嵌入凹槽
        Positioned(
          left: width / 2 - 30, // 屏幕宽度一半减去头像半径,水平居中
          top: appBarHeight - 30, // AppBar高度减去头像半径,纵向适配凹槽
          child: CircleAvatar(
            backgroundImage: const AssetImage("assets/images/person.jpeg"),
            radius: 30,
            key: const Key("1"),
          ),
        )
      ],
    );
  }
}

class CustomShapeBorder extends ContinuousRectangleBorder {
  const CustomShapeBorder();

  @override
  Path getOuterPath(Rect rect, {TextDirection? textDirection}) {
    Path path = Path();
    // 绘制AppBar基础矩形
    path.addRect(Rect.fromLTWH(0, 0, rect.width, rect.height));
    // 添加底部中间的圆形挖空区域
    path.addOval(
      Rect.fromCircle(
        center: Offset(rect.width / 2, rect.height),
        radius: 40,
      ),
    );
    // 奇偶填充规则,叠加区域会被挖空形成凹槽
    path.fillType = PathFillType.evenOdd;
    return path;
  }
}

内容的提问来源于stack exchange,提问作者Kiko

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.20 07:24:01