-1

enter image description here

I have tried some packages and stack with image but it is not working for me. Any help would be great.

Background image with curve is not working.

  • Does this answer your question? [Flutter BottomNavigationBar center icon style](https://stackoverflow.com/questions/59507143/flutter-bottomnavigationbar-center-icon-style) –  Feb 10 '21 at 11:22
  • @armstrong Tried it. Not useful as per my functionality. – Jay Tarpara Feb 10 '21 at 12:01
  • Which is the difference? –  Feb 10 '21 at 13:08
  • @armstrong Not able to make that curve which are there at left and right side... – Jay Tarpara Feb 10 '21 at 13:22
  • https://stackoverflow.com/questions/56577265/how-to-set-border-radius-to-bottom-app-bar-in-a-flutter-app/56585903 –  Feb 10 '21 at 13:29

1 Answers1

2

Does this work for you?

enter image description here

You should be able to do that with a custom NotchedShape:

class CustomNotchedShape extends NotchedShape {
  const CustomNotchedShape();

  @override
  Path getOuterPath(Rect host, Rect guest) {
    final x = math.min(host.width / 20, host.height / 3);
    final guestMargin = guest == null ? 0 : 1.0;
    if (guest == null || !host.overlaps(guest)) {
      guest = Rect.fromCenter(
          center: Offset(host.width / 2, host.top), width: 0, height: 0);
    }

    num degToRad(num deg) => deg * (math.pi / 180.0);

    return Path()
      ..moveTo(host.left, host.bottom)
      ..quadraticBezierTo(
          host.left + x, host.bottom, host.left + x, host.bottom - x)
      ..lineTo(host.left + x, host.top + x)
      ..quadraticBezierTo(host.left + x, host.top, host.left + 2 * x, host.top)
      ..lineTo(guest.left, host.top)
      ..arcTo(
          Rect.fromCenter(
              center: guest.center,
              width: guest.width + 2 * guestMargin,
              height: guest.width + 2 * guestMargin),
          degToRad(180),
          degToRad(-180),
          false)
      ..lineTo(host.right - 2 * x, host.top)
      ..quadraticBezierTo(
          host.right - x, host.top, host.right - x, host.top + x)
      ..lineTo(host.right - x, host.bottom - x)
      ..quadraticBezierTo(host.right - x, host.bottom, host.right, host.bottom)
      ..close();
  }
}

Then, you use this CustomNotchedShape as the shape of your BottomAppBar:

class MyBottomNavigationBar extends HookWidget {
  @override
  Widget build(BuildContext context) {
    final _currentIndex = useState(1);
    void navigateTo(int index) => _currentIndex.value = index;
    bool active(int index) => _currentIndex.value == index;

    return BottomAppBar(
      color: Theme.of(context).primaryColor,
      shape: CustomNotchedShape(),
      child: Container(
        height: 50,
        child: Padding(
          padding: const EdgeInsets.symmetric(horizontal: 20.0),
          child: Padding(
            padding: const EdgeInsets.symmetric(horizontal: 12.0),
            child: Row(
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
              children: <Widget>[
                IconButton(
                  onPressed: () => navigateTo(0),
                  icon: Icon(Icons.home_outlined),
                  color: active(0) ? Colors.white : Colors.black,
                ),
                IconButton(
                  onPressed: () => navigateTo(1),
                  icon: Icon(Icons.horizontal_split_outlined),
                  color: active(1) ? Colors.white : Colors.black,
                ),
                Padding(
                  padding: EdgeInsets.only(top: 24.0),
                  child: Text('New task'),
                ),
                IconButton(
                  onPressed: () => navigateTo(2),
                  icon: Icon(Icons.access_time_outlined),
                  color: active(2) ? Colors.white : Colors.black,
                ),
                IconButton(
                  onPressed: () => navigateTo(3),
                  icon: Icon(Icons.settings_outlined),
                  color: active(3) ? Colors.white : Colors.black,
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

Full source code

For easy copy-paste.

import 'dart:math' as math;

import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';

void main() {
  runApp(
    MaterialApp(
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        scaffoldBackgroundColor: Color(0xffd3ccca),
        primaryColor: Color(0xff86736c),
        accentColor: Color(0xff76504e),
      ),
      title: 'Flutter Demo',
      home: Scaffold(
        body: MyContent(),
        bottomNavigationBar: MyBottomNavigationBar(),
        floatingActionButton: FloatingActionButton(
          mini: true,
          onPressed: () => print('Adding new task...'),
          child: Icon(Icons.add),
        ),
        floatingActionButtonLocation:
            FloatingActionButtonLocation.miniCenterDocked,
      ),
    ),
  );
}

class MyContent extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Center(child: Text('Does this work for you?'));
  }
}

class MyBottomNavigationBar extends HookWidget {
  @override
  Widget build(BuildContext context) {
    final _currentIndex = useState(1);
    void navigateTo(int index) => _currentIndex.value = index;
    bool active(int index) => _currentIndex.value == index;

    return BottomAppBar(
      color: Theme.of(context).primaryColor,
      shape: CustomNotchedShape(),
      child: Container(
        height: 50,
        child: Padding(
          padding: const EdgeInsets.symmetric(horizontal: 20.0),
          child: Padding(
            padding: const EdgeInsets.symmetric(horizontal: 12.0),
            child: Row(
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
              children: <Widget>[
                IconButton(
                  onPressed: () => navigateTo(0),
                  icon: Icon(Icons.home_outlined),
                  color: active(0) ? Colors.white : Colors.black,
                ),
                IconButton(
                  onPressed: () => navigateTo(1),
                  icon: Icon(Icons.horizontal_split_outlined),
                  color: active(1) ? Colors.white : Colors.black,
                ),
                Padding(
                  padding: EdgeInsets.only(top: 24.0),
                  child: Text('New task'),
                ),
                IconButton(
                  onPressed: () => navigateTo(2),
                  icon: Icon(Icons.access_time_outlined),
                  color: active(2) ? Colors.white : Colors.black,
                ),
                IconButton(
                  onPressed: () => navigateTo(3),
                  icon: Icon(Icons.settings_outlined),
                  color: active(3) ? Colors.white : Colors.black,
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

class CustomNotchedShape extends NotchedShape {
  const CustomNotchedShape();

  @override
  Path getOuterPath(Rect host, Rect guest) {
    final x = math.min(host.width / 20, host.height / 3);
    final guestMargin = guest == null ? 0 : 1.0;
    if (guest == null || !host.overlaps(guest)) {
      guest = Rect.fromCenter(
          center: Offset(host.width / 2, host.top), width: 0, height: 0);
    }

    num degToRad(num deg) => deg * (math.pi / 180.0);

    return Path()
      ..moveTo(host.left, host.bottom)
      ..quadraticBezierTo(
          host.left + x, host.bottom, host.left + x, host.bottom - x)
      ..lineTo(host.left + x, host.top + x)
      ..quadraticBezierTo(host.left + x, host.top, host.left + 2 * x, host.top)
      ..lineTo(guest.left, host.top)
      ..arcTo(
          Rect.fromCenter(
              center: guest.center,
              width: guest.width + 2 * guestMargin,
              height: guest.width + 2 * guestMargin),
          degToRad(180),
          degToRad(-180),
          false)
      ..lineTo(host.right - 2 * x, host.top)
      ..quadraticBezierTo(
          host.right - x, host.top, host.right - x, host.top + x)
      ..lineTo(host.right - x, host.bottom - x)
      ..quadraticBezierTo(host.right - x, host.bottom, host.right, host.bottom)
      ..close();
  }
}
Thierry
  • 7,775
  • 2
  • 15
  • 33