skip to Main Content

how to draw this curve on bottom navigation using flutter I don know to how make it with flutter I know to make bottom navigation bar but this curve no idea I hope some advise there is the image I hope some tutorial
enter image description here

2

Answers


  1. You might consider using the canvas class, I recommend you to benefit from Flutter’s own documentation.Here is the link ; https://api.flutter.dev/flutter/dart-ui/Canvas-class.html

    Login or Signup to reply.
  2. One of the trick is by:

    1. Stacking the bottom navigation bar with custom curve widget
    2. Set the curve position aligned with the active bottom navigation bar
    3. Animate the curve shape position with AnimatedPositioned to make more ✨

    And this is the code to demonstrate the result:

    import 'package:flutter/material.dart';
    
    void main() => runApp(const BottomNavigationBarExampleApp());
    
    class BottomNavigationBarExampleApp extends StatelessWidget {
      const BottomNavigationBarExampleApp({super.key});
    
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          home: BottomNavigationBarExample(),
        );
      }
    }
    
    class BottomNavigationBarExample extends StatefulWidget {
      const BottomNavigationBarExample({super.key});
    
      @override
      State<BottomNavigationBarExample> createState() =>
          _BottomNavigationBarExampleState();
    }
    
    class _BottomNavigationBarExampleState
        extends State<BottomNavigationBarExample> {
      static const TextStyle optionStyle = TextStyle(
        fontSize: 30,
        fontWeight: FontWeight.bold,
      );
      static const inactiveColor = Color(0xFF4d5a5e);
    
      // you can set the curve size
      static const curveWidth = 300.0;
      static const curveHeight = 75.0;
      
      // total of the navigation bar item
      final count = widgetOptions.length;
      
      // active index state
      int selectedIndex = 0;
    
      // curve position calculation
      double calculatePosition(int pos, double screenWidth) {
        final division = screenWidth / count;
        final divisionPos = division * (pos - 1);
        return (divisionPos) + (division / 2) - (curveWidth / 2);
      }
    
      static const List<Widget> widgetOptions = <Widget>[
        Text(
          'Index 0: Home',
          style: optionStyle,
        ),
        Text(
          'Index 1: Business',
          style: optionStyle,
        ),
        Text(
          'Index 2: School',
          style: optionStyle,
        ),
      ];
    
      void onItemTapped(int index) {
        setState(() {
          selectedIndex = index;
        });
      }
    
      @override
      Widget build(BuildContext context) {
        final screenWidth = MediaQuery.of(context).size.width;
        return Scaffold(
          appBar: AppBar(
            title: const Text('BottomNavigationBar Sample'),
          ),
          body: Center(
            child: widgetOptions.elementAt(selectedIndex),
          ),
          bottomNavigationBar: Container(
            height: curveHeight,
            child: Stack(
              alignment: Alignment.bottomCenter,
              children: [
                // AnimatedPositioned widget to create the animated movement
                AnimatedPositioned(
                  curve: Curves.easeOutBack,
                  duration: Duration(milliseconds: 200),
                  left: calculatePosition(
                    selectedIndex + 1,
                    screenWidth,
                  ),
                  // curve shape with custom painter
                  child: CustomPaint(
                    size: Size(
                      curveWidth,
                      curveHeight,
                    ),
                    painter: RPSCustomPainter(inactiveColor),
                  ),
                ),
                Theme(
                  data: ThemeData(
                    splashColor: Colors.transparent,
                    highlightColor: Colors.transparent,
                    hoverColor: Colors.transparent,
                  ),
                  child: BottomNavigationBar(
                    enableFeedback: false,
                    elevation: 0,
                    backgroundColor: Colors.transparent,
                    selectedItemColor: Colors.white,
                    unselectedItemColor: inactiveColor,
                    items: const <BottomNavigationBarItem>[
                      BottomNavigationBarItem(
                        icon: Icon(Icons.home),
                        label: 'Home',
                      ),
                      BottomNavigationBarItem(
                        icon: Icon(Icons.business),
                        label: 'Business',
                      ),
                      BottomNavigationBarItem(
                        icon: Icon(Icons.school),
                        label: 'School',
                      ),
                    ],
                    currentIndex: selectedIndex,
                    onTap: onItemTapped,
                  ),
                ),
              ],
            ),
          ),
        );
      }
    }
    
    // the custom painter class to draw the curve shape
    class RPSCustomPainter extends CustomPainter {
      RPSCustomPainter(this.color);
      final Color color;
      @override
      void paint(Canvas canvas, Size size) {
        Path path_0 = Path();
        path_0.moveTo(size.width * 0.5, 0);
        path_0.cubicTo(
          size.width * 0.3,
          0,
          size.width * 0.3,
          size.height,
          0,
          size.height,
        );
        path_0.lineTo(size.width, size.height);
        path_0.cubicTo(
          size.width * 0.6,
          size.height,
          size.width * 0.6,
          0,
          size.width * 0.5,
          0,
        );
        path_0.close();
    
        Paint paintFill = Paint()..style = PaintingStyle.fill;
        paintFill.color = color;
        canvas.drawPath(path_0, paintFill);
      }
    
      @override
      bool shouldRepaint(covariant CustomPainter oldDelegate) {
        return true;
      }
    }
    

    And this is the result:

    demo

    Sorry for the imperfect curve shape, I’ve tried my best 😅 you can try to fix it by yourself.

    Hopefully it can solve your problem, Thanks 😉

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search