【问题标题】:How to position items in Appbar flutter如何在 Appbar Flutter 中定位项目
【发布时间】:2021-02-10 15:21:30
【问题描述】:

我正在尝试实现以下渲染:

但我无法将 ClipOval(个人资料图标)重叠在蓝色背景上。这是我的代码:

  Widget build(BuildContext context) {
    return OrientationBuilder(
      builder: (context, orientation) {
        return Scaffold(
          key: _scaffoldKey,
          //empty Appbar will detect that there is a endDrawer, so will add by default a menu icon
          body: Column(
            children: <Widget>[
              AppBarProfile(
                height: 150.0,
                firstIcon: IconButton(
                  onPressed: () {
                    // to open the drawer
                    _scaffoldKey.currentState.openEndDrawer();
                  },
                  icon: Container(
                    child: Icon(Icons.settings),
                    decoration: BoxDecoration(
                      borderRadius: BorderRadius.circular(4),
                      border: Border.all(color: Colors.white),
                    ),
                  ),
                ),
             title: 'My Profile',
                child: ClipOval(
                  child: Container(
                    color: Colors.white,
                    height: 100,
                    width: 100,
                    child: Container(
                      margin: const EdgeInsets.all(4),
                      decoration: BoxDecoration(
                        shape: BoxShape.circle,
                        border: Border.all(
                            color: TheBaseColors.lightBlue, width: 2),
                      ),
                      child: Icon(
                        Icons.person,
                        size: 80,
                        color: TheBaseColors.lightBlue,
                      ),
                    ),
                  ),
                ),
              ),
              Expanded(
                child: Text('I am the body of the screen'),
              ),
            ],
          ),

以下是我的 AppBAr 的代码,我在一个单独的文件中完成了它,因此我可以多次调用它并根据标题、应用栏的高度等更改我想要的值:

class AppBarProfile extends StatelessWidget {
  final Widget firstIcon, child;
  final String title;
  final double height, childHeight;

  const AppBarProfile({
    Key key,
    this.firstIcon,
    this.title,
    this.height,
    this.childHeight,
    this.child,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Stack(
      children: <Widget>[
        ClipPath(
          clipper: _AppBarProfileClipper(childHeight),
          child: Container(
            padding: const EdgeInsets.only(top: 30.0),
            color: TheBaseColors.lightBlue,
            height: height,
            child: Column(
              mainAxisAlignment: MainAxisAlignment.start,
              children: [
                Row(
                  // mainAxisAlignment: MainAxisAlignment.spaceAround,
                  children: <Widget>[
                    Positioned(left: 0, top: 0, child: firstIcon),
                    Text(
                      title,
                      style: TextStyle(
                        fontWeight: FontWeight.w600,
                        fontSize: 18.0,
                        color: Colors.white,
                      ),
                    ),
                  ],
                ),
              ],
            ),
          ),
        ),
        Positioned(
          bottom: 60, //50
          left: 0,
          right: 0,
          child: Align(
            alignment: Alignment.bottomCenter,
            child: child,
          ),
        ),
      ],
    );
  }
}

class _AppBarProfileClipper extends CustomClipper<Path> {
  final double childHeight;

  _AppBarProfileClipper(this.childHeight);

  @override
  Path getClip(Size size) {
    var path = Path();
    path.moveTo(0, size.height - 40.0);
    path.quadraticBezierTo(
        size.width / 2, size.height, size.width, size.height - 40.0);
    path.lineTo(size.width, 0);
    path.lineTo(0, 0);
    return path;
  }

  @override
  bool shouldReclip(covariant CustomClipper<Path> oldClipper) => true;
}

代码结果如下:

【问题讨论】:

    标签: flutter


    【解决方案1】:

    这是您最终结果的实现,我尝试保持与您的代码中相同的参数:

    代码

    class CustomAppBar extends StatelessWidget implements PreferredSizeWidget {
      final Widget firstIcon;
      final Widget child;
      final String title;
      final double height;
      final double childHeight;
      final Color color;
    
      CustomAppBar({
        Key key,
        @required this.title,
        this.height = 200.0,
        @required this.childHeight,
        this.color = Colors.black,
        @required this.firstIcon,
        @required this.child,
      }) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        return SizedBox.fromSize(
          size: preferredSize,
          child: LayoutBuilder(
            builder: (context, constraint) {
              return Stack(
                children: <Widget>[
                  ClipPath(
                    clipper: _AppBarProfileClipper(height),
                    child: Container(
                      width: double.maxFinite,
                      height: preferredSize.height - childHeight,
                      color: color,
                      alignment: Alignment.topCenter,
                      child: Row(
                        children: <Widget>[
                          if (firstIcon != null) firstIcon,
                          if (firstIcon != null) Expanded(child: Container()),
                          Text(
                            title,
                            style: Theme.of(context)
                                .textTheme
                                .headline6
                                .copyWith(color: Colors.white),
                          ),
                          Expanded(child: Container()),
                          IconButton(
                            icon: Icon(
                              Icons.settings,
                              color: Colors.white,
                            ),
                            onPressed: () {},
                          ),
                        ],
                      ),
                    ),
                  ),
                  Positioned.fill(
                    child: Align(
                      alignment: Alignment.bottomCenter,
                      child: child,
                    ),
                  ),
                ],
              );
            },
          ),
        );
      }
    
      @override
      Size get preferredSize => Size.fromHeight(height);
    }
    

    Try the full example on DartPad

    我使用的是PreferredSizeWidget,因此您可以直接在Scaffold 中将其用作AppBar

    Scaffold(
       appBar: CustomAppBar(
          title: 'User Profile',
          childHeight: 40.0,
          firstIcon: firstIconWidget,
          child: childWidget,
       ),
    );
    

    截图

    【讨论】:

      【解决方案2】:

      您是否尝试过使用Align Widget?

       @override
       Widget build(BuildContext context) {
         const double profile_side = 200;
         const double background_height = 300;
         const double widget_height = background_height + profile_side/2;
         return Scaffold(
      
      
           body: Container(
              color: Colors.white,
              height: widget_height,
              child: Stack(
                children: [
                  Container(
                    color: Colors.blue,
                    height: background_height,
                    width: double.infinity,
                  ),
                  Align(
                    alignment: Alignment(0.0, 1),
                    child: Container(
                      color: Colors.yellow,
                      height: profile_side,
                      width: profile_side,
                    ),
                  ),
                  Align(
                    alignment: Alignment(0,-0.8),
                    child: Text('My Profile',style: TextStyle(color: Colors.white,fontWeight: FontWeight.w700,fontSize: 24),),
                  ),
                  Align(
                    alignment: Alignment(-0.9, -0.8),
                    child: Icon(Icons.menu),
                  ),
                  Align(
                    alignment: Alignment(0.9, -0.8),
                    child: Icon(Icons.settings),
                  ),
                ],
              ),
            ),
          );
        }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-03-15
        • 2019-08-08
        • 2019-05-08
        • 2021-02-23
        • 2019-03-28
        • 2018-10-09
        相关资源
        最近更新 更多