Search code examples
flutterappbar

How to make like this appbar?


enter image description here

appBar: AppBar(
title: Center(
child: SvgPicture.asset("assets/images/logo.svg",
height: 15, width: 15, color: Colors.white,),
),
backgroundColor: const Color.fromRGBO(91, 189, 146, 1),
),

How to add the wave at the bottom of the appbar as in the picture?


Solution

  • The following would do the trick. It uses a CustomPaint widget to draw the semi-circle in the middle and Transform.translate to move the "icon" a bit down.

    This is the result (also, check the live demo on the DartPad)

    Screenshot

    The minimal-reproducible-example source code

    import 'dart:math';
    
    import 'package:flutter/material.dart';
    
    void main() {
      runApp(const MyApp());
    }
    
    class MyApp extends StatelessWidget {
      const MyApp({Key? key}) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Flutter Demo',
          theme: ThemeData(
            primarySwatch: Colors.blue,
          ),
          home: const MyHomePage(),
          debugShowCheckedModeBanner: false,
        );
      }
    }
    
    class MyHomePage extends StatefulWidget {
      const MyHomePage({Key? key}) : super(key: key);
    
      @override
      State<MyHomePage> createState() => _MyHomePageState();
    }
    
    class _MyHomePageState extends State<MyHomePage> {
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            toolbarHeight: 60,
            flexibleSpace: const CustomPaint(
              painter: MyCustomPainter(),
              size: Size.infinite,
            ),
            title: Center(
              child: Transform.translate(
                offset: const Offset(0, 5),
                child: const Center(
                  child: Text(
                    "Q",
                    style: TextStyle(color: Colors.white, fontSize: 30),
                  ),
                ),
              ),
            ),
            backgroundColor: Colors.transparent,
            elevation: 0,
          ),
        );
      }
    }
    
    class MyCustomPainter extends CustomPainter {
      const MyCustomPainter({Listenable? repaint}) : super(repaint: repaint);
    
      static const circleSize = 90.0;
      static const gap = 15.0;
    
      @override
      void paint(Canvas canvas, Size size) {
        var paint = Paint()
          ..style = PaintingStyle.fill
          ..color = const Color.fromRGBO(91, 189, 146, 1);
    
        var shadow = Paint()
          ..style = PaintingStyle.fill
          ..color = const Color.fromARGB(255, 127, 127, 127)
          ..maskFilter = MaskFilter.blur(
            BlurStyle.normal,
            Shadow.convertRadiusToSigma(5),
          );
    
        var path = Path();
        path.lineTo(0, size.height - gap);
        path.lineTo(size.width / 2, size.height - gap);
        path.arcTo(
          Rect.fromLTWH(
            size.width / 2 - circleSize / 2,
            size.height - circleSize,
            circleSize,
            circleSize,
          ),
          pi,
          -pi,
          false,
        );
        path.lineTo(size.width / 2, size.height - gap);
        path.lineTo(size.width, size.height - gap);
        path.lineTo(size.width, 0);
        path.close();
    
        canvas.drawPath(path, shadow);
        canvas.drawPath(path, paint);
      }
    
      @override
      bool shouldRepaint(MyCustomPainter oldDelegate) {
        return false;
      }
    }