MNBLabs
MNBLabs

Reputation: 85

How to have custom nav bar animation in flutter?

For animation I want the slide to move to the item I select.
What will be the best way to do so?

I want some thing like this circular_bottom_navigation

Please someone explain me to achieve the desired result.

Firstly, I am having a problem that I cannot align the icons with the slide in the center. enter image description here

How can I align it perfectly?

error in layout in widget inspector in the row:
enter image description here

code:

/// bottom nav bar
      Row(
      children: [
        SizedBox(
          width: size.width,
          height: size.height / 10,
          child: Stack(
            alignment: Alignment.center,
            children: [
              Container(
                alignment: Alignment.center,
                child: ClipRRect(
                  child: BackdropFilter(
                    filter: ImageFilter.blur(
                      sigmaX: 15,
                      sigmaY: 15,
                    ),
                    child: Container(
                      decoration: BoxDecoration(
                        color: Theme.of(context).brightness == Brightness.light
                            ? const Color.fromRGBO(184, 99, 99, 0.28)
                            : const Color.fromRGBO(255, 255, 255, 0.1),
                        border: Border(
                          top: BorderSide(
                            width: 1,
                            color:
                                Theme.of(context).brightness != Brightness.light
                                    ? Colors.white.withOpacity(0.2)
                                    : Colors.pink.withOpacity(0.2),
                          ),
                        ),
                      ),
                    ),
                  ),
                ),
              ),

              /// slide
              Container(
                width: 50,
                height: 50,
                decoration: BoxDecoration(
                  image: DecorationImage(
                    image: Theme.of(context).brightness == Brightness.light
                        ? const AssetImage('assets/images/lgt_slide.png')
                        : const AssetImage('assets/images/drk_slide.png'),
                    fit: BoxFit.fill,
                  ),
                ),
              ),

              /// bar items
              Row(
                crossAxisAlignment: CrossAxisAlignment.center,
                mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                children: [
                  bnbItems('assets/icons/icn1.png', 0, 25.33),
                  bnbItems('assets/icons/icn2.png', 0, 32),
                  bnbItems('assets/icons/icn3.png', 0, 33.33),
                  bnbItems('assets/icons/icn4.png', 0, 17),
                  bnbItems('assets/icons/icn5.png', 0, 30),
                ],
              ),
            ],
          ),
        ),
      ],
    );
  }

  Widget bnbItems(String image, int index, double height) {
    return GestureDetector(
      onTap: () => setState(() {
        selectedIndex = index;
      }),
      child: Image.asset(
        image,
        height: height,
      ),
    );
  }

Upvotes: 0

Views: 1007

Answers (1)

noxgood
noxgood

Reputation: 180

  1. Centering

To me it looks like the size of the assets images might be different or they centre of the image might not be where it seems to be, you can check it by wrapping image in a coloured container to see it's size or just use Widget inspector tool.

  1. Animations

I suggest you use presets like this https://gallery.flutter.dev/#/demo/bottom-navigation

Other option would be to use PositionedTransition on your Container, or SlideTransition. Here is an example https://api.flutter.dev/flutter/widgets/PositionedTransition-class.html

  1. Quick example of animation for container on tap(I simply modified this code a bit https://api.flutter.dev/flutter/material/BottomNavigationBar-class.html)
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 const MaterialApp(
      title: 'test_so',
      home: HomePage(),
    );
  }
}

class HomePage extends StatefulWidget {
  const HomePage({super.key});

  @override
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage>
    with SingleTickerProviderStateMixin {
  late final AnimationController _controller = AnimationController(
    duration: const Duration(milliseconds: 300),
    vsync: this,
  );

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  int _selectedIndex = 0;
  static const TextStyle optionStyle =
      TextStyle(fontSize: 30, fontWeight: FontWeight.bold);
  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) {
    _controller.animateTo(index / 2);
    setState(() {
      _selectedIndex = index;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('BottomNavigationBar Sample'),
      ),
      body: Center(
        child: _widgetOptions.elementAt(_selectedIndex),
      ),
      bottomNavigationBar: Stack(
        alignment: Alignment.center,
        children: [
          BottomNavigationBar(
            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,
            selectedItemColor: Colors.amber[800],
            onTap: _onItemTapped,
          ),
          SlideTransition(
            position: Tween<Offset>(
              begin: const Offset(-1.0, 0.0),
              end: const Offset(1.0, 0.0),
            ).animate(
              CurvedAnimation(
                parent: _controller,
                curve: Curves.linear,
              ),
            ),
            child: Container(
              height: 48,
              width: MediaQuery.of(context).size.width / 3,
              color: Colors.black26,
            ),
          ),
        ],
      ),
    );
  }
}

Upvotes: 1

Related Questions