├── .gitignore ├── .metadata ├── CHANGELOG.md ├── LICENSE ├── README.md ├── doc └── assets │ ├── animated-bottom-navigation-bar.gif │ ├── animated-bottom-navigation-bar.jpg │ ├── example-cornered-bar.jpeg │ ├── example-cornered-notched-bar.jpeg │ ├── example-default-notch-center.jpeg │ ├── example-notched-end.jpeg │ ├── example-plain-bar.jpeg │ ├── example-smooth-notch-center.jpeg │ ├── example-soft-notch-center.jpeg │ └── example-very-smooth-notch-center.jpeg ├── example ├── .gitignore ├── README.md ├── android │ ├── .gitignore │ ├── app │ │ ├── build.gradle │ │ └── src │ │ │ ├── debug │ │ │ └── AndroidManifest.xml │ │ │ ├── main │ │ │ ├── AndroidManifest.xml │ │ │ ├── kotlin │ │ │ │ └── com │ │ │ │ │ └── lanars │ │ │ │ │ └── lanarsnavbarflutter │ │ │ │ │ └── MainActivity.kt │ │ │ └── res │ │ │ │ ├── drawable │ │ │ │ └── launch_background.xml │ │ │ │ ├── mipmap-hdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-mdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xxhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xxxhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ └── values │ │ │ │ └── styles.xml │ │ │ └── profile │ │ │ └── AndroidManifest.xml │ ├── build.gradle │ ├── gradle.properties │ ├── gradle │ │ └── wrapper │ │ │ └── gradle-wrapper.properties │ ├── res │ │ └── values │ │ │ └── strings_en.arb │ └── settings.gradle ├── ios │ ├── .gitignore │ ├── Flutter │ │ ├── AppFrameworkInfo.plist │ │ ├── Debug.xcconfig │ │ └── Release.xcconfig │ ├── Runner.xcodeproj │ │ ├── project.pbxproj │ │ ├── project.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata │ │ │ │ ├── IDEWorkspaceChecks.plist │ │ │ │ └── WorkspaceSettings.xcsettings │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ └── Runner.xcscheme │ ├── Runner.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ ├── IDEWorkspaceChecks.plist │ │ │ └── WorkspaceSettings.xcsettings │ └── Runner │ │ ├── AppDelegate.swift │ │ ├── Assets.xcassets │ │ ├── AppIcon.appiconset │ │ │ ├── Contents.json │ │ │ ├── Icon-App-1024x1024@1x.png │ │ │ ├── Icon-App-20x20@1x.png │ │ │ ├── Icon-App-20x20@2x.png │ │ │ ├── Icon-App-20x20@3x.png │ │ │ ├── Icon-App-29x29@1x.png │ │ │ ├── Icon-App-29x29@2x.png │ │ │ ├── Icon-App-29x29@3x.png │ │ │ ├── Icon-App-40x40@1x.png │ │ │ ├── Icon-App-40x40@2x.png │ │ │ ├── Icon-App-40x40@3x.png │ │ │ ├── Icon-App-60x60@2x.png │ │ │ ├── Icon-App-60x60@3x.png │ │ │ ├── Icon-App-76x76@1x.png │ │ │ ├── Icon-App-76x76@2x.png │ │ │ └── Icon-App-83.5x83.5@2x.png │ │ └── LaunchImage.imageset │ │ │ ├── Contents.json │ │ │ ├── LaunchImage.png │ │ │ ├── LaunchImage@2x.png │ │ │ ├── LaunchImage@3x.png │ │ │ └── README.md │ │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ │ ├── Info.plist │ │ └── Runner-Bridging-Header.h ├── lib │ ├── main.dart │ └── theme │ │ ├── app_theme.dart │ │ └── custom_colors_theme.dart ├── pubspec.yaml └── res │ └── values │ └── strings_en.arb ├── lib ├── animated_bottom_navigation_bar.dart └── src │ ├── around_custom_painter.dart │ ├── bubble_selection_painter.dart │ ├── circular_notch_and_corner_clipper.dart │ ├── circular_notched_and_cornered_shape.dart │ ├── exceptions.dart │ ├── gap_item.dart │ ├── navigation_bar_item.dart │ ├── safe_area_values.dart │ ├── tab_item.dart │ └── visible_animator.dart ├── pubspec.yaml └── test └── animatedbottomnavigationbar_test.dart /.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | 12 | # IntelliJ related 13 | *.iml 14 | *.ipr 15 | *.iws 16 | .idea/ 17 | 18 | # The .vscode folder contains launch configuration and tasks you configure in 19 | # VS Code which you may wish to be included in version control, so this line 20 | # is commented out by default. 21 | #.vscode/ 22 | 23 | # Flutter/Dart/Pub related 24 | **/doc/api/ 25 | .dart_tool/ 26 | .flutter-plugins 27 | .flutter-plugins-dependencies 28 | .packages 29 | .pub-cache/ 30 | .pub/ 31 | build/ 32 | pubspec.lock 33 | # i18n 34 | lib/generated 35 | res/values 36 | 37 | # Android related 38 | **/android/**/gradle-wrapper.jar 39 | **/android/.gradle 40 | **/android/captures/ 41 | **/android/gradlew 42 | **/android/gradlew.bat 43 | **/android/local.properties 44 | **/android/**/GeneratedPluginRegistrant.java 45 | 46 | # iOS/XCode related 47 | **/ios/**/*.mode1v3 48 | **/ios/**/*.mode2v3 49 | **/ios/**/*.moved-aside 50 | **/ios/**/*.pbxuser 51 | **/ios/**/*.perspectivev3 52 | **/ios/**/*sync/ 53 | **/ios/**/.sconsign.dblite 54 | **/ios/**/.tags* 55 | **/ios/**/.vagrant/ 56 | **/ios/**/DerivedData/ 57 | **/ios/**/Icon? 58 | **/ios/**/Pods/ 59 | **/ios/**/.symlinks/ 60 | **/ios/**/profile 61 | **/ios/**/xcuserdata 62 | **/ios/.generated/ 63 | **/ios/Flutter/App.framework 64 | **/ios/Flutter/Flutter.framework 65 | **/ios/Flutter/Flutter.podspec 66 | **/ios/Flutter/Generated.xcconfig 67 | **/ios/Flutter/app.flx 68 | **/ios/Flutter/app.zip 69 | **/ios/Flutter/flutter_assets/ 70 | **/ios/Flutter/flutter_export_environment.sh 71 | **/ios/ServiceDefinitions.json 72 | **/ios/Runner/GeneratedPluginRegistrant.* 73 | 74 | # Exceptions to above rules. 75 | !**/ios/**/default.mode1v3 76 | !**/ios/**/default.mode2v3 77 | !**/ios/**/default.pbxuser 78 | !**/ios/**/default.perspectivev3 79 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages 80 | -------------------------------------------------------------------------------- /.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: 7f56b53de4e5da2147c4d30d857a72c6f2e4f42f 8 | channel: dev 9 | 10 | project_type: package 11 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## [1.4.0] - 2025-02-11 2 | * Fix displaying gradient for background in bottom navigation bar [#76](https://github.com/LanarsInc/animated-bottom-navigation-bar-flutter/pull/76), thanks to [huykgit98](https://github.com/huykgit98) 3 | * Increase flutter to `>=3.16.0` and dart to `>=3.0.0` versions 4 | 5 | ## [1.3.3] - 2024-01-31 6 | * Fix animation controllers memory leak by [Clon1998](https://github.com/Clon1998) 7 | 8 | ## [1.3.2] - 2024-01-18 9 | * Add `blurFilter` parameter 10 | 11 | ## [1.3.1] - 2024-01-17 12 | * Fix [#65](https://github.com/LanarsInc/animated-bottom-navigation-bar-flutter/issues/65) 13 | 14 | ## [1.3.0] - 2023-09-22 15 | * Add `scaleFactor` parameter by [Oubi256](https://github.com/Oubi256) 16 | * Update README.md 17 | 18 | ## [1.2.1] - 2023-09-13 19 | * Bump sdk version to `>=2.12.0 <4.0.0` 20 | * Update README.md 21 | 22 | ## [1.2.0] - 2023-03-09 23 | * Fix [#46](https://github.com/LanarsInc/animated-bottom-navigation-bar-flutter/issues/46) 24 | * Update example 25 | 26 | ## [1.1.0+1] - 2022-12-27 27 | * Update README.md 28 | 29 | ## [1.1.0] - 2022-08-18 30 | * Add `elevation` parameter 31 | * Remove default value for `shadow` 32 | 33 | ## [1.0.1] - 2022-07-04 34 | * Fix [#40](https://github.com/vizhan-lanars/animated-bottom-navigation-bar-flutter/issues/40) 35 | 36 | ## [1.0.0] - 2022-06-17. 37 | * **Breaking change**. `SafeArea` params grouped to `SafeAreaValues` object. 38 | * **Breaking change**. Remove `elevation` parameter in favour of `shadow` parameter. 39 | * Add shadow customization by [Prn-Ice](https://github.com/Prn-Ice) 40 | * Add hide on scroll animation by [Prn-Ice](https://github.com/Prn-Ice) 41 | * Add border customization 42 | * Add `backgroundGradient` parameter 43 | * Fix [#34](https://github.com/vizhan-lanars/animated-bottom-navigation-bar-flutter/issues/34) 44 | * Add `blurEffect` parameter 45 | 46 | ## [0.3.3] - 2022-05-18. 47 | * Add SafeArea setting by [DenchikBY](https://github.com/DenchikBY) 48 | * Fix floating-point comparison by [franciscrispin](https://github.com/franciscrispin) 49 | 50 | ## [0.3.2] - 2021-03-22. 51 | * Fix [#16](https://github.com/LanarsInc/animated-bottom-navigation-bar-flutter/issues/16) 52 | * Update example 53 | 54 | ## [0.3.1+1] - 2021-03-10. 55 | * Clean up code 56 | 57 | ## [0.3.1] - 2021-03-09. 58 | * Fix [#2](https://github.com/LanarsInc/animated-bottom-navigation-bar-flutter/issues/2) 59 | 60 | ## [0.3.0] - 2021-03-09. 61 | * Migrate to null safety [#15](https://github.com/LanarsInc/animated-bottom-navigation-bar-flutter/issues/15) 62 | 63 | ## [0.2.1] - 2020-12-27. 64 | * Resolve `List` warning 65 | 66 | ## [0.2.0] - 2020-11-30. 67 | 68 | * Enhancement [#4](https://github.com/LanarsInc/animated-bottom-navigation-bar-flutter/issues/4) 69 | * Enhancement [#5](https://github.com/LanarsInc/animated-bottom-navigation-bar-flutter/issues/5) 70 | * Add `NotchSmoothness.sharpEdge` type 71 | 72 | ## [0.1.3] - 2020-11-26. 73 | 74 | * Fix [#1](https://github.com/LanarsInc/animated-bottom-navigation-bar-flutter/issues/1) by [LuizFilipeMedeira](https://github.com/LuizFilipeMedeira) 75 | 76 | ## [0.1.2+2] - 2020-04-24. 77 | 78 | * Update package README.md 79 | 80 | ## [0.1.2+1] - 2020-04-23. 81 | 82 | * Add example source files 83 | 84 | ## [0.1.2] - 2020-04-23. 85 | 86 | * Update example README.md 87 | 88 | ## [0.1.1] - 2020-04-23. 89 | 90 | * Update asset links 91 | 92 | ## [0.1.0] - 2020-04-23. 93 | 94 | * Format files 95 | 96 | ## [0.0.1] - 2020-04-23. 97 | 98 | * Initial release of `animated_bottom_navigation_bar` -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 2-Clause License 2 | 3 | Copyright (c) 2020, LanarsInc 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 20 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 23 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | © 2020 GitHub, Inc. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![SWUbanner](https://raw.githubusercontent.com/vshymanskyy/StandWithUkraine/main/banner2-direct.svg)](https://vshymanskyy.github.io/StandWithUkraine) 2 | 3 | AnimatedBottomNavigationBar is a customizable widget inspired by [dribble shot](https://dribbble.com/shots/7134849-Simple-Tab-Bar-Animation). 4 | 5 | [![pub package](https://img.shields.io/pub/v/animated_bottom_navigation_bar.svg)](https://pub.dev/packages/animated_bottom_navigation_bar) 6 | 7 | [!["Buy Me A Coffee"](https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png)](https://www.buymeacoffee.com/lanars) 8 | 9 | 10 | 11 | With `AnimatedBottomNavigationBar.builder` you are able to customize tab view however you need. In this case you are responsible to handle an active(inactive) state of tabs. 12 | 13 | 14 | 15 | # Getting Started 16 | 17 | To get started, place your `AnimatedBottomNavigationBar` or `AnimatedBottomNavigationBar.builder` in the bottomNavigationBar slot of a `Scaffold`. 18 | The `AnimatedBottomNavigationBar` respects `FloatingActionButton` location. 19 | For example: 20 | 21 | ```dart 22 | Scaffold( 23 | body: Container(), //destination screen 24 | floatingActionButton: FloatingActionButton( 25 | //params 26 | ), 27 | floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked, 28 | bottomNavigationBar: AnimatedBottomNavigationBar( 29 | icons: iconList, 30 | activeIndex: _bottomNavIndex, 31 | gapLocation: GapLocation.center, 32 | notchSmoothness: NotchSmoothness.verySmoothEdge, 33 | leftCornerRadius: 32, 34 | rightCornerRadius: 32, 35 | onTap: (index) => setState(() => _bottomNavIndex = index), 36 | //other params 37 | ), 38 | ); 39 | ``` 40 | 41 | There is also a more flexible way to build `bottomNavigationBar` with Builder (see [example](https://pub.dev/packages/animated_bottom_navigation_bar/example) for more insights): 42 | ```dart 43 | Scaffold( 44 | body: Container(), //destination screen 45 | floatingActionButton: FloatingActionButton( 46 | //params 47 | ), 48 | floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked, 49 | bottomNavigationBar: AnimatedBottomNavigationBar.builder( 50 | itemCount: iconList.length, 51 | tabBuilder: (int index, bool isActive) { 52 | return Icon( 53 | iconList[index], 54 | size: 24, 55 | color: isActive ? colors.activeNavigationBarColor : colors.notActiveNavigationBarColor, 56 | ); 57 | activeIndex: _bottomNavIndex, 58 | gapLocation: GapLocation.center, 59 | notchSmoothness: NotchSmoothness.verySmoothEdge, 60 | leftCornerRadius: 32, 61 | rightCornerRadius: 32, 62 | onTap: (index) => setState(() => _bottomNavIndex = index), 63 | //other params 64 | ), 65 | ); 66 | ``` 67 | 68 | 69 | 70 | 71 | # Customization 72 | 73 | AnimatedBottomNavigationBar is customizable and works with 2, 3, 4, or 5 navigation elements. 74 | ```dart 75 | Scaffold( 76 | bottomNavigationBar: AnimatedBottomNavigationBar( 77 | icons: iconList, 78 | activeIndex: _bottomNavIndex, 79 | onTap: (index) => setState(() => _bottomNavIndex = index), 80 | //other params 81 | ), 82 | ); 83 | ``` 84 | 85 | 86 | ```dart 87 | Scaffold( 88 | bottomNavigationBar: AnimatedBottomNavigationBar( 89 | icons: iconList, 90 | activeIndex: _bottomNavIndex, 91 | leftCornerRadius: 32, 92 | rightCornerRadius: 32, 93 | onTap: (index) => setState(() => _bottomNavIndex = index), 94 | //other params 95 | ), 96 | ); 97 | ``` 98 | 99 | 100 | ```dart 101 | Scaffold( 102 | floatingActionButton: FloatingActionButton( 103 | //params 104 | ), 105 | floatingActionButtonLocation: FloatingActionButtonLocation.endDocked, 106 | bottomNavigationBar: AnimatedBottomNavigationBar( 107 | icons: iconList, 108 | activeIndex: _bottomNavIndex, 109 | gapLocation: GapLocation.end, 110 | notchSmoothness: NotchSmoothness.defaultEdge, 111 | onTap: (index) => setState(() => _bottomNavIndex = index), 112 | //other params 113 | ), 114 | ); 115 | ``` 116 | 117 | 118 | ```dart 119 | Scaffold( 120 | floatingActionButton: FloatingActionButton( 121 | //params 122 | ), 123 | floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked, 124 | bottomNavigationBar: AnimatedBottomNavigationBar( 125 | icons: iconList, 126 | activeIndex: _bottomNavIndex, 127 | gapLocation: GapLocation.center, 128 | notchSmoothness: NotchSmoothness.defaultEdge, 129 | onTap: (index) => setState(() => _bottomNavIndex = index), 130 | //other params 131 | ), 132 | ); 133 | ``` 134 | 135 | 136 | ```dart 137 | Scaffold( 138 | floatingActionButton: FloatingActionButton( 139 | //params 140 | ), 141 | floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked, 142 | bottomNavigationBar: AnimatedBottomNavigationBar( 143 | icons: iconList, 144 | activeIndex: _bottomNavIndex, 145 | gapLocation: GapLocation.center, 146 | notchSmoothness: NotchSmoothness.softEdge, 147 | onTap: (index) => setState(() => _bottomNavIndex = index), 148 | //other params 149 | ), 150 | ); 151 | ``` 152 | 153 | 154 | ```dart 155 | Scaffold( 156 | floatingActionButton: FloatingActionButton( 157 | //params 158 | ), 159 | floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked, 160 | bottomNavigationBar: AnimatedBottomNavigationBar( 161 | icons: iconList, 162 | activeIndex: _bottomNavIndex, 163 | gapLocation: GapLocation.center, 164 | notchSmoothness: NotchSmoothness.smoothEdge, 165 | onTap: (index) => setState(() => _bottomNavIndex = index), 166 | //other params 167 | ), 168 | ); 169 | ``` 170 | 171 | 172 | ```dart 173 | Scaffold( 174 | floatingActionButton: FloatingActionButton( 175 | //params 176 | ), 177 | floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked, 178 | bottomNavigationBar: AnimatedBottomNavigationBar( 179 | icons: iconList, 180 | activeIndex: _bottomNavIndex, 181 | gapLocation: GapLocation.center, 182 | notchSmoothness: NotchSmoothness.verySmoothEdge, 183 | onTap: (index) => setState(() => _bottomNavIndex = index), 184 | //other params 185 | ), 186 | ); 187 | ``` 188 | 189 | 190 | # Driving Navigation Bar Changes 191 | 192 | You have to change the active navigation bar tab programmatically by passing a new activeIndex to the AnimatedBottomNavigationBar widget. 193 | 194 | ```dart 195 | class _MyAppState extends State { 196 | int activeIndex; 197 | 198 | /// Handler for when you want to programmatically change 199 | /// the active index. Calling `setState()` here causes 200 | /// Flutter to re-render the tree, which `AnimatedBottomNavigationBar` 201 | /// responds to by running its normal animation. 202 | void _onTap(int index) { 203 | setState((){ 204 | activeIndex = index; 205 | }); 206 | } 207 | 208 | Widget build(BuildContext context) { 209 | return AnimatedBottomNavigationBar( 210 | activeIndex: activeIndex, 211 | onTap: _onTap, 212 | //other params 213 | ); 214 | } 215 | } 216 | ``` -------------------------------------------------------------------------------- /doc/assets/animated-bottom-navigation-bar.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LanarsInc/animated-bottom-navigation-bar-flutter/c27bf4f36be60b9d61da6efcae9908c4b2423613/doc/assets/animated-bottom-navigation-bar.gif -------------------------------------------------------------------------------- /doc/assets/animated-bottom-navigation-bar.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LanarsInc/animated-bottom-navigation-bar-flutter/c27bf4f36be60b9d61da6efcae9908c4b2423613/doc/assets/animated-bottom-navigation-bar.jpg -------------------------------------------------------------------------------- /doc/assets/example-cornered-bar.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LanarsInc/animated-bottom-navigation-bar-flutter/c27bf4f36be60b9d61da6efcae9908c4b2423613/doc/assets/example-cornered-bar.jpeg -------------------------------------------------------------------------------- /doc/assets/example-cornered-notched-bar.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LanarsInc/animated-bottom-navigation-bar-flutter/c27bf4f36be60b9d61da6efcae9908c4b2423613/doc/assets/example-cornered-notched-bar.jpeg -------------------------------------------------------------------------------- /doc/assets/example-default-notch-center.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LanarsInc/animated-bottom-navigation-bar-flutter/c27bf4f36be60b9d61da6efcae9908c4b2423613/doc/assets/example-default-notch-center.jpeg -------------------------------------------------------------------------------- /doc/assets/example-notched-end.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LanarsInc/animated-bottom-navigation-bar-flutter/c27bf4f36be60b9d61da6efcae9908c4b2423613/doc/assets/example-notched-end.jpeg -------------------------------------------------------------------------------- /doc/assets/example-plain-bar.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LanarsInc/animated-bottom-navigation-bar-flutter/c27bf4f36be60b9d61da6efcae9908c4b2423613/doc/assets/example-plain-bar.jpeg -------------------------------------------------------------------------------- /doc/assets/example-smooth-notch-center.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LanarsInc/animated-bottom-navigation-bar-flutter/c27bf4f36be60b9d61da6efcae9908c4b2423613/doc/assets/example-smooth-notch-center.jpeg -------------------------------------------------------------------------------- /doc/assets/example-soft-notch-center.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LanarsInc/animated-bottom-navigation-bar-flutter/c27bf4f36be60b9d61da6efcae9908c4b2423613/doc/assets/example-soft-notch-center.jpeg -------------------------------------------------------------------------------- /doc/assets/example-very-smooth-notch-center.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LanarsInc/animated-bottom-navigation-bar-flutter/c27bf4f36be60b9d61da6efcae9908c4b2423613/doc/assets/example-very-smooth-notch-center.jpeg -------------------------------------------------------------------------------- /example/.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | 12 | # IntelliJ related 13 | *.iml 14 | *.ipr 15 | *.iws 16 | .idea/ 17 | 18 | # The .vscode folder contains launch configuration and tasks you configure in 19 | # VS Code which you may wish to be included in version control, so this line 20 | # is commented out by default. 21 | #.vscode/ 22 | 23 | # Flutter/Dart/Pub related 24 | **/doc/api/ 25 | **/ios/Flutter/.last_build_id 26 | .dart_tool/ 27 | .flutter-plugins 28 | .flutter-plugins-dependencies 29 | .packages 30 | .pub-cache/ 31 | .pub/ 32 | /build/ 33 | pubspec.lock 34 | 35 | # Web related 36 | lib/generated_plugin_registrant.dart 37 | 38 | # Symbolication related 39 | app.*.symbols 40 | 41 | # Obfuscation related 42 | app.*.map.json 43 | 44 | # Exceptions to above rules. 45 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages 46 | -------------------------------------------------------------------------------- /example/README.md: -------------------------------------------------------------------------------- 1 | # /example/lib/main.dart 2 | 3 | ```dart 4 | import 'dart:async'; 5 | 6 | import 'package:animated_bottom_navigation_bar/animated_bottom_navigation_bar.dart'; 7 | import 'package:circular_reveal_animation/circular_reveal_animation.dart'; 8 | import 'package:flutter/foundation.dart'; 9 | import 'package:flutter/material.dart'; 10 | import 'package:flutter/services.dart'; 11 | 12 | void main() => runApp(MyApp()); 13 | 14 | class MyApp extends StatelessWidget { 15 | @override 16 | Widget build(BuildContext context) { 17 | return MaterialApp( 18 | debugShowCheckedModeBanner: false, 19 | title: 'Flutter Demo', 20 | theme: ThemeData( 21 | primarySwatch: Colors.blue, 22 | scaffoldBackgroundColor: Colors.white, 23 | visualDensity: VisualDensity.adaptivePlatformDensity, 24 | ), 25 | home: MyHomePage(title: 'Animated Navigation Bottom Bar'), 26 | ); 27 | } 28 | } 29 | 30 | class MyHomePage extends StatefulWidget { 31 | MyHomePage({Key key, this.title}) : super(key: key); 32 | 33 | final String title; 34 | 35 | @override 36 | _MyHomePageState createState() => _MyHomePageState(); 37 | } 38 | 39 | class _MyHomePageState extends State with SingleTickerProviderStateMixin { 40 | var _bottomNavIndex = 0; //default index of first screen 41 | 42 | AnimationController _animationController; 43 | Animation animation; 44 | CurvedAnimation curve; 45 | 46 | final iconList = [ 47 | Icons.brightness_5, 48 | Icons.brightness_4, 49 | Icons.brightness_6, 50 | Icons.brightness_7, 51 | ]; 52 | 53 | @override 54 | void initState() { 55 | super.initState(); 56 | final systemTheme = SystemUiOverlayStyle.light.copyWith( 57 | systemNavigationBarColor: HexColor('#373A36'), 58 | systemNavigationBarIconBrightness: Brightness.light, 59 | ); 60 | SystemChrome.setSystemUIOverlayStyle(systemTheme); 61 | 62 | _animationController = AnimationController( 63 | duration: Duration(seconds: 1), 64 | vsync: this, 65 | ); 66 | curve = CurvedAnimation( 67 | parent: _animationController, 68 | curve: Interval( 69 | 0.5, 70 | 1.0, 71 | curve: Curves.fastOutSlowIn, 72 | ), 73 | ); 74 | animation = Tween( 75 | begin: 0, 76 | end: 1, 77 | ).animate(curve); 78 | 79 | Future.delayed( 80 | Duration(seconds: 1), 81 | () => _animationController.forward(), 82 | ); 83 | } 84 | 85 | @override 86 | Widget build(BuildContext context) { 87 | return Scaffold( 88 | extendBody: true, 89 | appBar: AppBar( 90 | title: Text( 91 | widget.title, 92 | style: TextStyle(color: Colors.white), 93 | ), 94 | backgroundColor: HexColor('#373A36'), 95 | ), 96 | body: NavigationScreen( 97 | iconList[_bottomNavIndex], 98 | ), 99 | floatingActionButton: ScaleTransition( 100 | scale: animation, 101 | child: FloatingActionButton( 102 | elevation: 8, 103 | backgroundColor: HexColor('#FFA400'), 104 | child: Icon( 105 | Icons.brightness_3, 106 | color: HexColor('#373A36'), 107 | ), 108 | onPressed: () { 109 | _animationController.reset(); 110 | _animationController.forward(); 111 | }, 112 | ), 113 | ), 114 | floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked, 115 | bottomNavigationBar: AnimatedBottomNavigationBar( 116 | icons: iconList, 117 | backgroundColor: HexColor('#373A36'), 118 | activeIndex: _bottomNavIndex, 119 | activeColor: HexColor('#FFA400'), 120 | splashColor: HexColor('#FFA400'), 121 | inactiveColor: Colors.white, 122 | notchAndCornersAnimation: animation, 123 | splashSpeedInMilliseconds: 300, 124 | notchSmoothness: NotchSmoothness.defaultEdge, 125 | gapLocation: GapLocation.center, 126 | leftCornerRadius: 32, 127 | rightCornerRadius: 32, 128 | onTap: (index) => setState(() => _bottomNavIndex = index), 129 | ), 130 | ); 131 | } 132 | } 133 | 134 | class NavigationScreen extends StatefulWidget { 135 | final IconData iconData; 136 | 137 | NavigationScreen(this.iconData) : super(); 138 | 139 | @override 140 | _NavigationScreenState createState() => _NavigationScreenState(); 141 | } 142 | 143 | class _NavigationScreenState extends State with TickerProviderStateMixin { 144 | AnimationController _controller; 145 | Animation animation; 146 | 147 | @override 148 | void didUpdateWidget(NavigationScreen oldWidget) { 149 | super.didUpdateWidget(oldWidget); 150 | if (oldWidget.iconData != widget.iconData) { 151 | _startAnimation(); 152 | } 153 | } 154 | 155 | @override 156 | void initState() { 157 | _controller = AnimationController( 158 | vsync: this, 159 | duration: Duration(milliseconds: 1000), 160 | ); 161 | animation = CurvedAnimation( 162 | parent: _controller, 163 | curve: Curves.easeIn, 164 | ); 165 | _controller.forward(); 166 | super.initState(); 167 | } 168 | 169 | _startAnimation() { 170 | _controller = AnimationController( 171 | vsync: this, 172 | duration: Duration(milliseconds: 1000), 173 | ); 174 | animation = CurvedAnimation( 175 | parent: _controller, 176 | curve: Curves.easeIn, 177 | ); 178 | _controller.forward(); 179 | } 180 | 181 | @override 182 | void dispose() { 183 | _controller.dispose(); 184 | super.dispose(); 185 | } 186 | 187 | @override 188 | Widget build(BuildContext context) { 189 | return Container( 190 | width: double.infinity, 191 | height: double.infinity, 192 | color: Colors.white, 193 | child: Center( 194 | child: CircularRevealAnimation( 195 | animation: animation, 196 | centerOffset: Offset(80, 80), 197 | maxRadius: MediaQuery.of(context).size.longestSide * 1.1, 198 | child: Icon( 199 | widget.iconData, 200 | color: HexColor('#FFA400'), 201 | size: 160, 202 | ), 203 | ), 204 | ), 205 | ); 206 | } 207 | } 208 | 209 | class HexColor extends Color { 210 | HexColor(final String hexColor) : super(_getColorFromHex(hexColor)); 211 | 212 | static int _getColorFromHex(String hexColor) { 213 | hexColor = hexColor.toUpperCase().replaceAll('#', ''); 214 | if (hexColor.length == 6) { 215 | hexColor = 'FF' + hexColor; 216 | } 217 | return int.parse(hexColor, radix: 16); 218 | } 219 | } 220 | ``` -------------------------------------------------------------------------------- /example/android/.gitignore: -------------------------------------------------------------------------------- 1 | gradle-wrapper.jar 2 | /.gradle 3 | /captures/ 4 | /gradlew 5 | /gradlew.bat 6 | /local.properties 7 | GeneratedPluginRegistrant.java 8 | -------------------------------------------------------------------------------- /example/android/app/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id "com.android.application" 3 | id "kotlin-android" 4 | id "dev.flutter.flutter-gradle-plugin" 5 | } 6 | 7 | def localProperties = new Properties() 8 | def localPropertiesFile = rootProject.file('local.properties') 9 | if (localPropertiesFile.exists()) { 10 | localPropertiesFile.withReader('UTF-8') { reader -> 11 | localProperties.load(reader) 12 | } 13 | } 14 | 15 | def flutterRoot = localProperties.getProperty('flutter.sdk') 16 | if (flutterRoot == null) { 17 | throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") 18 | } 19 | 20 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode') 21 | if (flutterVersionCode == null) { 22 | flutterVersionCode = '1' 23 | } 24 | 25 | def flutterVersionName = localProperties.getProperty('flutter.versionName') 26 | if (flutterVersionName == null) { 27 | flutterVersionName = '1.0' 28 | } 29 | 30 | android { 31 | namespace "com.lanars.lanarsnavbarflutter" 32 | compileSdk 34 33 | 34 | compileOptions { 35 | sourceCompatibility JavaVersion.VERSION_1_8 36 | targetCompatibility JavaVersion.VERSION_1_8 37 | } 38 | 39 | kotlinOptions { 40 | jvmTarget = '1.8' 41 | } 42 | 43 | sourceSets { 44 | main.java.srcDirs += 'src/main/kotlin' 45 | } 46 | 47 | lintOptions { 48 | disable 'InvalidPackage' 49 | } 50 | 51 | defaultConfig { 52 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). 53 | applicationId "com.lanars.lanarsnavbarflutter" 54 | minSdk 19 55 | targetSdk 34 56 | versionCode flutterVersionCode.toInteger() 57 | versionName flutterVersionName 58 | } 59 | 60 | buildTypes { 61 | release { 62 | // TODO: Add your own signing config for the release build. 63 | // Signing with the debug keys for now, so `flutter run --release` works. 64 | signingConfig signingConfigs.debug 65 | } 66 | } 67 | namespace 'com.lanars.lanarsnavbarflutter' 68 | } 69 | 70 | flutter { 71 | source '../..' 72 | } 73 | 74 | dependencies { 75 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.9.22" 76 | } 77 | -------------------------------------------------------------------------------- /example/android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /example/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 11 | 19 | 23 | 27 | 32 | 36 | 37 | 38 | 39 | 40 | 41 | 43 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /example/android/app/src/main/kotlin/com/lanars/lanarsnavbarflutter/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.lanars.lanarsnavbarflutter 2 | 3 | import io.flutter.embedding.android.FlutterActivity 4 | 5 | class MainActivity: FlutterActivity() { 6 | } 7 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/drawable/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LanarsInc/animated-bottom-navigation-bar-flutter/c27bf4f36be60b9d61da6efcae9908c4b2423613/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LanarsInc/animated-bottom-navigation-bar-flutter/c27bf4f36be60b9d61da6efcae9908c4b2423613/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LanarsInc/animated-bottom-navigation-bar-flutter/c27bf4f36be60b9d61da6efcae9908c4b2423613/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LanarsInc/animated-bottom-navigation-bar-flutter/c27bf4f36be60b9d61da6efcae9908c4b2423613/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LanarsInc/animated-bottom-navigation-bar-flutter/c27bf4f36be60b9d61da6efcae9908c4b2423613/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /example/android/app/src/profile/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /example/android/build.gradle: -------------------------------------------------------------------------------- 1 | allprojects { 2 | repositories { 3 | google() 4 | mavenCentral() 5 | } 6 | } 7 | 8 | rootProject.buildDir = '../build' 9 | subprojects { 10 | project.buildDir = "${rootProject.buildDir}/${project.name}" 11 | } 12 | subprojects { 13 | project.evaluationDependsOn(':app') 14 | } 15 | 16 | tasks.register("clean", Delete) { 17 | delete rootProject.buildDir 18 | } 19 | -------------------------------------------------------------------------------- /example/android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx1536M 2 | android.enableR8=true 3 | android.useAndroidX=true 4 | android.enableJetifier=true 5 | android.defaults.buildfeatures.buildconfig=true 6 | android.nonTransitiveRClass=false 7 | android.nonFinalResIds=false 8 | -------------------------------------------------------------------------------- /example/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip 4 | networkTimeout=10000 5 | validateDistributionUrl=true 6 | zipStoreBase=GRADLE_USER_HOME 7 | zipStorePath=wrapper/dists 8 | -------------------------------------------------------------------------------- /example/android/res/values/strings_en.arb: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /example/android/settings.gradle: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | def flutterSdkPath = { 3 | def properties = new Properties() 4 | file("local.properties").withInputStream { properties.load(it) } 5 | def flutterSdkPath = properties.getProperty("flutter.sdk") 6 | assert flutterSdkPath != null, "flutter.sdk not set in local.properties" 7 | return flutterSdkPath 8 | }() 9 | 10 | includeBuild("$flutterSdkPath/packages/flutter_tools/gradle") 11 | 12 | repositories { 13 | google() 14 | mavenCentral() 15 | gradlePluginPortal() 16 | } 17 | } 18 | 19 | plugins { 20 | id "dev.flutter.flutter-plugin-loader" version "1.0.0" 21 | id "com.android.application" version "8.3.0" apply false 22 | id "org.jetbrains.kotlin.android" version "1.9.22" apply false 23 | } 24 | 25 | include ":app" -------------------------------------------------------------------------------- /example/ios/.gitignore: -------------------------------------------------------------------------------- 1 | *.mode1v3 2 | *.mode2v3 3 | *.moved-aside 4 | *.pbxuser 5 | *.perspectivev3 6 | **/*sync/ 7 | .sconsign.dblite 8 | .tags* 9 | **/.vagrant/ 10 | **/DerivedData/ 11 | Icon? 12 | **/Pods/ 13 | **/.symlinks/ 14 | profile 15 | xcuserdata 16 | **/.generated/ 17 | Flutter/App.framework 18 | Flutter/Flutter.framework 19 | Flutter/Flutter.podspec 20 | Flutter/Generated.xcconfig 21 | Flutter/app.flx 22 | Flutter/app.zip 23 | Flutter/flutter_assets/ 24 | Flutter/flutter_export_environment.sh 25 | ServiceDefinitions.json 26 | Runner/GeneratedPluginRegistrant.* 27 | 28 | # Exceptions to above rules. 29 | !default.mode1v3 30 | !default.mode2v3 31 | !default.pbxuser 32 | !default.perspectivev3 33 | -------------------------------------------------------------------------------- /example/ios/Flutter/AppFrameworkInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | App 9 | CFBundleIdentifier 10 | io.flutter.flutter.app 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | App 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1.0 23 | MinimumOSVersion 24 | 12.0 25 | 26 | 27 | -------------------------------------------------------------------------------- /example/ios/Flutter/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /example/ios/Flutter/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 54; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; 11 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; 12 | 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; 13 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 14 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 15 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; 16 | /* End PBXBuildFile section */ 17 | 18 | /* Begin PBXCopyFilesBuildPhase section */ 19 | 9705A1C41CF9048500538489 /* Embed Frameworks */ = { 20 | isa = PBXCopyFilesBuildPhase; 21 | buildActionMask = 2147483647; 22 | dstPath = ""; 23 | dstSubfolderSpec = 10; 24 | files = ( 25 | ); 26 | name = "Embed Frameworks"; 27 | runOnlyForDeploymentPostprocessing = 0; 28 | }; 29 | /* End PBXCopyFilesBuildPhase section */ 30 | 31 | /* Begin PBXFileReference section */ 32 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 33 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; 34 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; 35 | 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; 36 | 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 37 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; 38 | 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; 39 | 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; 40 | 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; 41 | 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 42 | 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 43 | 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 44 | 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 45 | /* End PBXFileReference section */ 46 | 47 | /* Begin PBXFrameworksBuildPhase section */ 48 | 97C146EB1CF9000F007C117D /* Frameworks */ = { 49 | isa = PBXFrameworksBuildPhase; 50 | buildActionMask = 2147483647; 51 | files = ( 52 | ); 53 | runOnlyForDeploymentPostprocessing = 0; 54 | }; 55 | /* End PBXFrameworksBuildPhase section */ 56 | 57 | /* Begin PBXGroup section */ 58 | 9740EEB11CF90186004384FC /* Flutter */ = { 59 | isa = PBXGroup; 60 | children = ( 61 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, 62 | 9740EEB21CF90195004384FC /* Debug.xcconfig */, 63 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, 64 | 9740EEB31CF90195004384FC /* Generated.xcconfig */, 65 | ); 66 | name = Flutter; 67 | sourceTree = ""; 68 | }; 69 | 97C146E51CF9000F007C117D = { 70 | isa = PBXGroup; 71 | children = ( 72 | 9740EEB11CF90186004384FC /* Flutter */, 73 | 97C146F01CF9000F007C117D /* Runner */, 74 | 97C146EF1CF9000F007C117D /* Products */, 75 | ); 76 | sourceTree = ""; 77 | }; 78 | 97C146EF1CF9000F007C117D /* Products */ = { 79 | isa = PBXGroup; 80 | children = ( 81 | 97C146EE1CF9000F007C117D /* Runner.app */, 82 | ); 83 | name = Products; 84 | sourceTree = ""; 85 | }; 86 | 97C146F01CF9000F007C117D /* Runner */ = { 87 | isa = PBXGroup; 88 | children = ( 89 | 97C146FA1CF9000F007C117D /* Main.storyboard */, 90 | 97C146FD1CF9000F007C117D /* Assets.xcassets */, 91 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, 92 | 97C147021CF9000F007C117D /* Info.plist */, 93 | 97C146F11CF9000F007C117D /* Supporting Files */, 94 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, 95 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, 96 | 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, 97 | 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, 98 | ); 99 | path = Runner; 100 | sourceTree = ""; 101 | }; 102 | 97C146F11CF9000F007C117D /* Supporting Files */ = { 103 | isa = PBXGroup; 104 | children = ( 105 | ); 106 | name = "Supporting Files"; 107 | sourceTree = ""; 108 | }; 109 | /* End PBXGroup section */ 110 | 111 | /* Begin PBXNativeTarget section */ 112 | 97C146ED1CF9000F007C117D /* Runner */ = { 113 | isa = PBXNativeTarget; 114 | buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; 115 | buildPhases = ( 116 | 9740EEB61CF901F6004384FC /* Run Script */, 117 | 97C146EA1CF9000F007C117D /* Sources */, 118 | 97C146EB1CF9000F007C117D /* Frameworks */, 119 | 97C146EC1CF9000F007C117D /* Resources */, 120 | 9705A1C41CF9048500538489 /* Embed Frameworks */, 121 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */, 122 | ); 123 | buildRules = ( 124 | ); 125 | dependencies = ( 126 | ); 127 | name = Runner; 128 | productName = Runner; 129 | productReference = 97C146EE1CF9000F007C117D /* Runner.app */; 130 | productType = "com.apple.product-type.application"; 131 | }; 132 | /* End PBXNativeTarget section */ 133 | 134 | /* Begin PBXProject section */ 135 | 97C146E61CF9000F007C117D /* Project object */ = { 136 | isa = PBXProject; 137 | attributes = { 138 | LastUpgradeCheck = 1510; 139 | ORGANIZATIONNAME = ""; 140 | TargetAttributes = { 141 | 97C146ED1CF9000F007C117D = { 142 | CreatedOnToolsVersion = 7.3.1; 143 | LastSwiftMigration = 1100; 144 | }; 145 | }; 146 | }; 147 | buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; 148 | compatibilityVersion = "Xcode 9.3"; 149 | developmentRegion = en; 150 | hasScannedForEncodings = 0; 151 | knownRegions = ( 152 | en, 153 | Base, 154 | ); 155 | mainGroup = 97C146E51CF9000F007C117D; 156 | productRefGroup = 97C146EF1CF9000F007C117D /* Products */; 157 | projectDirPath = ""; 158 | projectRoot = ""; 159 | targets = ( 160 | 97C146ED1CF9000F007C117D /* Runner */, 161 | ); 162 | }; 163 | /* End PBXProject section */ 164 | 165 | /* Begin PBXResourcesBuildPhase section */ 166 | 97C146EC1CF9000F007C117D /* Resources */ = { 167 | isa = PBXResourcesBuildPhase; 168 | buildActionMask = 2147483647; 169 | files = ( 170 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, 171 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, 172 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, 173 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, 174 | ); 175 | runOnlyForDeploymentPostprocessing = 0; 176 | }; 177 | /* End PBXResourcesBuildPhase section */ 178 | 179 | /* Begin PBXShellScriptBuildPhase section */ 180 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { 181 | isa = PBXShellScriptBuildPhase; 182 | alwaysOutOfDate = 1; 183 | buildActionMask = 2147483647; 184 | files = ( 185 | ); 186 | inputPaths = ( 187 | "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}", 188 | ); 189 | name = "Thin Binary"; 190 | outputPaths = ( 191 | ); 192 | runOnlyForDeploymentPostprocessing = 0; 193 | shellPath = /bin/sh; 194 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; 195 | }; 196 | 9740EEB61CF901F6004384FC /* Run Script */ = { 197 | isa = PBXShellScriptBuildPhase; 198 | alwaysOutOfDate = 1; 199 | buildActionMask = 2147483647; 200 | files = ( 201 | ); 202 | inputPaths = ( 203 | ); 204 | name = "Run Script"; 205 | outputPaths = ( 206 | ); 207 | runOnlyForDeploymentPostprocessing = 0; 208 | shellPath = /bin/sh; 209 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; 210 | }; 211 | /* End PBXShellScriptBuildPhase section */ 212 | 213 | /* Begin PBXSourcesBuildPhase section */ 214 | 97C146EA1CF9000F007C117D /* Sources */ = { 215 | isa = PBXSourcesBuildPhase; 216 | buildActionMask = 2147483647; 217 | files = ( 218 | 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, 219 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, 220 | ); 221 | runOnlyForDeploymentPostprocessing = 0; 222 | }; 223 | /* End PBXSourcesBuildPhase section */ 224 | 225 | /* Begin PBXVariantGroup section */ 226 | 97C146FA1CF9000F007C117D /* Main.storyboard */ = { 227 | isa = PBXVariantGroup; 228 | children = ( 229 | 97C146FB1CF9000F007C117D /* Base */, 230 | ); 231 | name = Main.storyboard; 232 | sourceTree = ""; 233 | }; 234 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { 235 | isa = PBXVariantGroup; 236 | children = ( 237 | 97C147001CF9000F007C117D /* Base */, 238 | ); 239 | name = LaunchScreen.storyboard; 240 | sourceTree = ""; 241 | }; 242 | /* End PBXVariantGroup section */ 243 | 244 | /* Begin XCBuildConfiguration section */ 245 | 249021D3217E4FDB00AE95B9 /* Profile */ = { 246 | isa = XCBuildConfiguration; 247 | buildSettings = { 248 | ALWAYS_SEARCH_USER_PATHS = NO; 249 | CLANG_ANALYZER_NONNULL = YES; 250 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 251 | CLANG_CXX_LIBRARY = "libc++"; 252 | CLANG_ENABLE_MODULES = YES; 253 | CLANG_ENABLE_OBJC_ARC = YES; 254 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 255 | CLANG_WARN_BOOL_CONVERSION = YES; 256 | CLANG_WARN_COMMA = YES; 257 | CLANG_WARN_CONSTANT_CONVERSION = YES; 258 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 259 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 260 | CLANG_WARN_EMPTY_BODY = YES; 261 | CLANG_WARN_ENUM_CONVERSION = YES; 262 | CLANG_WARN_INFINITE_RECURSION = YES; 263 | CLANG_WARN_INT_CONVERSION = YES; 264 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 265 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 266 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 267 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 268 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 269 | CLANG_WARN_STRICT_PROTOTYPES = YES; 270 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 271 | CLANG_WARN_UNREACHABLE_CODE = YES; 272 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 273 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 274 | COPY_PHASE_STRIP = NO; 275 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 276 | ENABLE_NS_ASSERTIONS = NO; 277 | ENABLE_STRICT_OBJC_MSGSEND = YES; 278 | GCC_C_LANGUAGE_STANDARD = gnu99; 279 | GCC_NO_COMMON_BLOCKS = YES; 280 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 281 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 282 | GCC_WARN_UNDECLARED_SELECTOR = YES; 283 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 284 | GCC_WARN_UNUSED_FUNCTION = YES; 285 | GCC_WARN_UNUSED_VARIABLE = YES; 286 | IPHONEOS_DEPLOYMENT_TARGET = 12.0; 287 | MTL_ENABLE_DEBUG_INFO = NO; 288 | SDKROOT = iphoneos; 289 | SUPPORTED_PLATFORMS = iphoneos; 290 | TARGETED_DEVICE_FAMILY = "1,2"; 291 | VALIDATE_PRODUCT = YES; 292 | }; 293 | name = Profile; 294 | }; 295 | 249021D4217E4FDB00AE95B9 /* Profile */ = { 296 | isa = XCBuildConfiguration; 297 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 298 | buildSettings = { 299 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 300 | CLANG_ENABLE_MODULES = YES; 301 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 302 | ENABLE_BITCODE = NO; 303 | FRAMEWORK_SEARCH_PATHS = ( 304 | "$(inherited)", 305 | "$(PROJECT_DIR)/Flutter", 306 | ); 307 | INFOPLIST_FILE = Runner/Info.plist; 308 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 309 | LIBRARY_SEARCH_PATHS = ( 310 | "$(inherited)", 311 | "$(PROJECT_DIR)/Flutter", 312 | ); 313 | PRODUCT_BUNDLE_IDENTIFIER = com.lanars.lanarsnavbarflutter; 314 | PRODUCT_NAME = "$(TARGET_NAME)"; 315 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; 316 | SWIFT_VERSION = 5.0; 317 | VERSIONING_SYSTEM = "apple-generic"; 318 | }; 319 | name = Profile; 320 | }; 321 | 97C147031CF9000F007C117D /* Debug */ = { 322 | isa = XCBuildConfiguration; 323 | buildSettings = { 324 | ALWAYS_SEARCH_USER_PATHS = NO; 325 | CLANG_ANALYZER_NONNULL = YES; 326 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 327 | CLANG_CXX_LIBRARY = "libc++"; 328 | CLANG_ENABLE_MODULES = YES; 329 | CLANG_ENABLE_OBJC_ARC = YES; 330 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 331 | CLANG_WARN_BOOL_CONVERSION = YES; 332 | CLANG_WARN_COMMA = YES; 333 | CLANG_WARN_CONSTANT_CONVERSION = YES; 334 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 335 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 336 | CLANG_WARN_EMPTY_BODY = YES; 337 | CLANG_WARN_ENUM_CONVERSION = YES; 338 | CLANG_WARN_INFINITE_RECURSION = YES; 339 | CLANG_WARN_INT_CONVERSION = YES; 340 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 341 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 342 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 343 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 344 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 345 | CLANG_WARN_STRICT_PROTOTYPES = YES; 346 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 347 | CLANG_WARN_UNREACHABLE_CODE = YES; 348 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 349 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 350 | COPY_PHASE_STRIP = NO; 351 | DEBUG_INFORMATION_FORMAT = dwarf; 352 | ENABLE_STRICT_OBJC_MSGSEND = YES; 353 | ENABLE_TESTABILITY = YES; 354 | GCC_C_LANGUAGE_STANDARD = gnu99; 355 | GCC_DYNAMIC_NO_PIC = NO; 356 | GCC_NO_COMMON_BLOCKS = YES; 357 | GCC_OPTIMIZATION_LEVEL = 0; 358 | GCC_PREPROCESSOR_DEFINITIONS = ( 359 | "DEBUG=1", 360 | "$(inherited)", 361 | ); 362 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 363 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 364 | GCC_WARN_UNDECLARED_SELECTOR = YES; 365 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 366 | GCC_WARN_UNUSED_FUNCTION = YES; 367 | GCC_WARN_UNUSED_VARIABLE = YES; 368 | IPHONEOS_DEPLOYMENT_TARGET = 12.0; 369 | MTL_ENABLE_DEBUG_INFO = YES; 370 | ONLY_ACTIVE_ARCH = YES; 371 | SDKROOT = iphoneos; 372 | TARGETED_DEVICE_FAMILY = "1,2"; 373 | }; 374 | name = Debug; 375 | }; 376 | 97C147041CF9000F007C117D /* Release */ = { 377 | isa = XCBuildConfiguration; 378 | buildSettings = { 379 | ALWAYS_SEARCH_USER_PATHS = NO; 380 | CLANG_ANALYZER_NONNULL = YES; 381 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 382 | CLANG_CXX_LIBRARY = "libc++"; 383 | CLANG_ENABLE_MODULES = YES; 384 | CLANG_ENABLE_OBJC_ARC = YES; 385 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 386 | CLANG_WARN_BOOL_CONVERSION = YES; 387 | CLANG_WARN_COMMA = YES; 388 | CLANG_WARN_CONSTANT_CONVERSION = YES; 389 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 390 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 391 | CLANG_WARN_EMPTY_BODY = YES; 392 | CLANG_WARN_ENUM_CONVERSION = YES; 393 | CLANG_WARN_INFINITE_RECURSION = YES; 394 | CLANG_WARN_INT_CONVERSION = YES; 395 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 396 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 397 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 398 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 399 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 400 | CLANG_WARN_STRICT_PROTOTYPES = YES; 401 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 402 | CLANG_WARN_UNREACHABLE_CODE = YES; 403 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 404 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 405 | COPY_PHASE_STRIP = NO; 406 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 407 | ENABLE_NS_ASSERTIONS = NO; 408 | ENABLE_STRICT_OBJC_MSGSEND = YES; 409 | GCC_C_LANGUAGE_STANDARD = gnu99; 410 | GCC_NO_COMMON_BLOCKS = YES; 411 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 412 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 413 | GCC_WARN_UNDECLARED_SELECTOR = YES; 414 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 415 | GCC_WARN_UNUSED_FUNCTION = YES; 416 | GCC_WARN_UNUSED_VARIABLE = YES; 417 | IPHONEOS_DEPLOYMENT_TARGET = 12.0; 418 | MTL_ENABLE_DEBUG_INFO = NO; 419 | SDKROOT = iphoneos; 420 | SUPPORTED_PLATFORMS = iphoneos; 421 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 422 | TARGETED_DEVICE_FAMILY = "1,2"; 423 | VALIDATE_PRODUCT = YES; 424 | }; 425 | name = Release; 426 | }; 427 | 97C147061CF9000F007C117D /* Debug */ = { 428 | isa = XCBuildConfiguration; 429 | baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; 430 | buildSettings = { 431 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 432 | CLANG_ENABLE_MODULES = YES; 433 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 434 | ENABLE_BITCODE = NO; 435 | FRAMEWORK_SEARCH_PATHS = ( 436 | "$(inherited)", 437 | "$(PROJECT_DIR)/Flutter", 438 | ); 439 | INFOPLIST_FILE = Runner/Info.plist; 440 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 441 | LIBRARY_SEARCH_PATHS = ( 442 | "$(inherited)", 443 | "$(PROJECT_DIR)/Flutter", 444 | ); 445 | PRODUCT_BUNDLE_IDENTIFIER = com.lanars.lanarsnavbarflutter; 446 | PRODUCT_NAME = "$(TARGET_NAME)"; 447 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; 448 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 449 | SWIFT_VERSION = 5.0; 450 | VERSIONING_SYSTEM = "apple-generic"; 451 | }; 452 | name = Debug; 453 | }; 454 | 97C147071CF9000F007C117D /* Release */ = { 455 | isa = XCBuildConfiguration; 456 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 457 | buildSettings = { 458 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 459 | CLANG_ENABLE_MODULES = YES; 460 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 461 | ENABLE_BITCODE = NO; 462 | FRAMEWORK_SEARCH_PATHS = ( 463 | "$(inherited)", 464 | "$(PROJECT_DIR)/Flutter", 465 | ); 466 | INFOPLIST_FILE = Runner/Info.plist; 467 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 468 | LIBRARY_SEARCH_PATHS = ( 469 | "$(inherited)", 470 | "$(PROJECT_DIR)/Flutter", 471 | ); 472 | PRODUCT_BUNDLE_IDENTIFIER = com.lanars.lanarsnavbarflutter; 473 | PRODUCT_NAME = "$(TARGET_NAME)"; 474 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; 475 | SWIFT_VERSION = 5.0; 476 | VERSIONING_SYSTEM = "apple-generic"; 477 | }; 478 | name = Release; 479 | }; 480 | /* End XCBuildConfiguration section */ 481 | 482 | /* Begin XCConfigurationList section */ 483 | 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { 484 | isa = XCConfigurationList; 485 | buildConfigurations = ( 486 | 97C147031CF9000F007C117D /* Debug */, 487 | 97C147041CF9000F007C117D /* Release */, 488 | 249021D3217E4FDB00AE95B9 /* Profile */, 489 | ); 490 | defaultConfigurationIsVisible = 0; 491 | defaultConfigurationName = Release; 492 | }; 493 | 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { 494 | isa = XCConfigurationList; 495 | buildConfigurations = ( 496 | 97C147061CF9000F007C117D /* Debug */, 497 | 97C147071CF9000F007C117D /* Release */, 498 | 249021D4217E4FDB00AE95B9 /* Profile */, 499 | ); 500 | defaultConfigurationIsVisible = 0; 501 | defaultConfigurationName = Release; 502 | }; 503 | /* End XCConfigurationList section */ 504 | }; 505 | rootObject = 97C146E61CF9000F007C117D /* Project object */; 506 | } 507 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /example/ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | import Flutter 3 | 4 | @main 5 | @objc class AppDelegate: FlutterAppDelegate { 6 | override func application( 7 | _ application: UIApplication, 8 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? 9 | ) -> Bool { 10 | GeneratedPluginRegistrant.register(with: self) 11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "20x20", 5 | "idiom" : "iphone", 6 | "filename" : "Icon-App-20x20@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "20x20", 11 | "idiom" : "iphone", 12 | "filename" : "Icon-App-20x20@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "Icon-App-29x29@1x.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "29x29", 23 | "idiom" : "iphone", 24 | "filename" : "Icon-App-29x29@2x.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "29x29", 29 | "idiom" : "iphone", 30 | "filename" : "Icon-App-29x29@3x.png", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "size" : "40x40", 35 | "idiom" : "iphone", 36 | "filename" : "Icon-App-40x40@2x.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "40x40", 41 | "idiom" : "iphone", 42 | "filename" : "Icon-App-40x40@3x.png", 43 | "scale" : "3x" 44 | }, 45 | { 46 | "size" : "60x60", 47 | "idiom" : "iphone", 48 | "filename" : "Icon-App-60x60@2x.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "60x60", 53 | "idiom" : "iphone", 54 | "filename" : "Icon-App-60x60@3x.png", 55 | "scale" : "3x" 56 | }, 57 | { 58 | "size" : "20x20", 59 | "idiom" : "ipad", 60 | "filename" : "Icon-App-20x20@1x.png", 61 | "scale" : "1x" 62 | }, 63 | { 64 | "size" : "20x20", 65 | "idiom" : "ipad", 66 | "filename" : "Icon-App-20x20@2x.png", 67 | "scale" : "2x" 68 | }, 69 | { 70 | "size" : "29x29", 71 | "idiom" : "ipad", 72 | "filename" : "Icon-App-29x29@1x.png", 73 | "scale" : "1x" 74 | }, 75 | { 76 | "size" : "29x29", 77 | "idiom" : "ipad", 78 | "filename" : "Icon-App-29x29@2x.png", 79 | "scale" : "2x" 80 | }, 81 | { 82 | "size" : "40x40", 83 | "idiom" : "ipad", 84 | "filename" : "Icon-App-40x40@1x.png", 85 | "scale" : "1x" 86 | }, 87 | { 88 | "size" : "40x40", 89 | "idiom" : "ipad", 90 | "filename" : "Icon-App-40x40@2x.png", 91 | "scale" : "2x" 92 | }, 93 | { 94 | "size" : "76x76", 95 | "idiom" : "ipad", 96 | "filename" : "Icon-App-76x76@1x.png", 97 | "scale" : "1x" 98 | }, 99 | { 100 | "size" : "76x76", 101 | "idiom" : "ipad", 102 | "filename" : "Icon-App-76x76@2x.png", 103 | "scale" : "2x" 104 | }, 105 | { 106 | "size" : "83.5x83.5", 107 | "idiom" : "ipad", 108 | "filename" : "Icon-App-83.5x83.5@2x.png", 109 | "scale" : "2x" 110 | }, 111 | { 112 | "size" : "1024x1024", 113 | "idiom" : "ios-marketing", 114 | "filename" : "Icon-App-1024x1024@1x.png", 115 | "scale" : "1x" 116 | } 117 | ], 118 | "info" : { 119 | "version" : 1, 120 | "author" : "xcode" 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LanarsInc/animated-bottom-navigation-bar-flutter/c27bf4f36be60b9d61da6efcae9908c4b2423613/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LanarsInc/animated-bottom-navigation-bar-flutter/c27bf4f36be60b9d61da6efcae9908c4b2423613/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LanarsInc/animated-bottom-navigation-bar-flutter/c27bf4f36be60b9d61da6efcae9908c4b2423613/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LanarsInc/animated-bottom-navigation-bar-flutter/c27bf4f36be60b9d61da6efcae9908c4b2423613/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LanarsInc/animated-bottom-navigation-bar-flutter/c27bf4f36be60b9d61da6efcae9908c4b2423613/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LanarsInc/animated-bottom-navigation-bar-flutter/c27bf4f36be60b9d61da6efcae9908c4b2423613/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LanarsInc/animated-bottom-navigation-bar-flutter/c27bf4f36be60b9d61da6efcae9908c4b2423613/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LanarsInc/animated-bottom-navigation-bar-flutter/c27bf4f36be60b9d61da6efcae9908c4b2423613/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LanarsInc/animated-bottom-navigation-bar-flutter/c27bf4f36be60b9d61da6efcae9908c4b2423613/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LanarsInc/animated-bottom-navigation-bar-flutter/c27bf4f36be60b9d61da6efcae9908c4b2423613/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LanarsInc/animated-bottom-navigation-bar-flutter/c27bf4f36be60b9d61da6efcae9908c4b2423613/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LanarsInc/animated-bottom-navigation-bar-flutter/c27bf4f36be60b9d61da6efcae9908c4b2423613/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LanarsInc/animated-bottom-navigation-bar-flutter/c27bf4f36be60b9d61da6efcae9908c4b2423613/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LanarsInc/animated-bottom-navigation-bar-flutter/c27bf4f36be60b9d61da6efcae9908c4b2423613/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LanarsInc/animated-bottom-navigation-bar-flutter/c27bf4f36be60b9d61da6efcae9908c4b2423613/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "LaunchImage.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "LaunchImage@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "LaunchImage@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LanarsInc/animated-bottom-navigation-bar-flutter/c27bf4f36be60b9d61da6efcae9908c4b2423613/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LanarsInc/animated-bottom-navigation-bar-flutter/c27bf4f36be60b9d61da6efcae9908c4b2423613/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LanarsInc/animated-bottom-navigation-bar-flutter/c27bf4f36be60b9d61da6efcae9908c4b2423613/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md: -------------------------------------------------------------------------------- 1 | # Launch Screen Assets 2 | 3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory. 4 | 5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. -------------------------------------------------------------------------------- /example/ios/Runner/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /example/ios/Runner/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /example/ios/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | lanarsnavbarflutter 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | $(FLUTTER_BUILD_NAME) 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(FLUTTER_BUILD_NUMBER) 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UISupportedInterfaceOrientations 30 | 31 | UIInterfaceOrientationPortrait 32 | UIInterfaceOrientationLandscapeLeft 33 | UIInterfaceOrientationLandscapeRight 34 | 35 | UISupportedInterfaceOrientations~ipad 36 | 37 | UIInterfaceOrientationPortrait 38 | UIInterfaceOrientationPortraitUpsideDown 39 | UIInterfaceOrientationLandscapeLeft 40 | UIInterfaceOrientationLandscapeRight 41 | 42 | UIViewControllerBasedStatusBarAppearance 43 | 44 | CADisableMinimumFrameDurationOnPhone 45 | 46 | UIApplicationSupportsIndirectInputEvents 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /example/ios/Runner/Runner-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | #import "GeneratedPluginRegistrant.h" 2 | -------------------------------------------------------------------------------- /example/lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | 3 | import 'package:animated_bottom_navigation_bar/animated_bottom_navigation_bar.dart'; 4 | import 'package:auto_size_text/auto_size_text.dart'; 5 | import 'package:circular_reveal_animation/circular_reveal_animation.dart'; 6 | import 'package:flutter/material.dart'; 7 | import 'package:flutter/rendering.dart'; 8 | import 'package:lanarsnavbarflutter/theme/app_theme.dart'; 9 | import 'package:lanarsnavbarflutter/theme/custom_colors_theme.dart'; 10 | 11 | void main() => runApp(MyApp()); 12 | 13 | class MyApp extends StatelessWidget { 14 | @override 15 | Widget build(BuildContext context) { 16 | return MaterialApp( 17 | debugShowCheckedModeBanner: false, 18 | title: 'Flutter Demo', 19 | theme: AppTheme.get(isLight: true), 20 | darkTheme: AppTheme.get(isLight: false), 21 | home: MyHomePage(title: 'Animated Navigation Bottom Bar'), 22 | ); 23 | } 24 | } 25 | 26 | class MyHomePage extends StatefulWidget { 27 | MyHomePage({Key? key, required this.title}) : super(key: key); 28 | 29 | final String title; 30 | 31 | @override 32 | _MyHomePageState createState() => _MyHomePageState(); 33 | } 34 | 35 | class _MyHomePageState extends State with TickerProviderStateMixin { 36 | final autoSizeGroup = AutoSizeGroup(); 37 | var _bottomNavIndex = 0; //default index of a first screen 38 | 39 | late AnimationController _fabAnimationController; 40 | late AnimationController _borderRadiusAnimationController; 41 | late Animation fabAnimation; 42 | late Animation borderRadiusAnimation; 43 | late CurvedAnimation fabCurve; 44 | late CurvedAnimation borderRadiusCurve; 45 | late AnimationController _hideBottomBarAnimationController; 46 | 47 | final iconList = [ 48 | Icons.brightness_5, 49 | Icons.brightness_4, 50 | Icons.brightness_6, 51 | Icons.brightness_7, 52 | ]; 53 | 54 | @override 55 | void initState() { 56 | super.initState(); 57 | 58 | _fabAnimationController = AnimationController( 59 | duration: Duration(milliseconds: 500), 60 | vsync: this, 61 | ); 62 | _borderRadiusAnimationController = AnimationController( 63 | duration: Duration(milliseconds: 500), 64 | vsync: this, 65 | ); 66 | fabCurve = CurvedAnimation( 67 | parent: _fabAnimationController, 68 | curve: Interval(0.5, 1.0, curve: Curves.fastOutSlowIn), 69 | ); 70 | borderRadiusCurve = CurvedAnimation( 71 | parent: _borderRadiusAnimationController, 72 | curve: Interval(0.5, 1.0, curve: Curves.fastOutSlowIn), 73 | ); 74 | 75 | fabAnimation = Tween(begin: 0, end: 1).animate(fabCurve); 76 | borderRadiusAnimation = Tween(begin: 0, end: 1).animate( 77 | borderRadiusCurve, 78 | ); 79 | 80 | _hideBottomBarAnimationController = AnimationController( 81 | duration: Duration(milliseconds: 200), 82 | vsync: this, 83 | ); 84 | 85 | Future.delayed( 86 | Duration(seconds: 1), 87 | () => _fabAnimationController.forward(), 88 | ); 89 | Future.delayed( 90 | Duration(seconds: 1), 91 | () => _borderRadiusAnimationController.forward(), 92 | ); 93 | } 94 | 95 | bool onScrollNotification(ScrollNotification notification) { 96 | if (notification is UserScrollNotification && 97 | notification.metrics.axis == Axis.vertical) { 98 | switch (notification.direction) { 99 | case ScrollDirection.forward: 100 | _hideBottomBarAnimationController.reverse(); 101 | _fabAnimationController.forward(from: 0); 102 | break; 103 | case ScrollDirection.reverse: 104 | _hideBottomBarAnimationController.forward(); 105 | _fabAnimationController.reverse(from: 1); 106 | break; 107 | case ScrollDirection.idle: 108 | break; 109 | } 110 | } 111 | return false; 112 | } 113 | 114 | @override 115 | Widget build(BuildContext context) { 116 | final colors = Theme.of(context).extension()!; 117 | return Scaffold( 118 | extendBody: true, 119 | appBar: AppBar( 120 | title: Text( 121 | widget.title, 122 | style: TextStyle(color: Colors.white), 123 | ), 124 | ), 125 | body: NotificationListener( 126 | onNotification: onScrollNotification, 127 | child: NavigationScreen(iconList[_bottomNavIndex]), 128 | ), 129 | floatingActionButton: FloatingActionButton( 130 | child: Icon( 131 | Icons.brightness_3, 132 | color: AppTheme.colorGray, 133 | ), 134 | onPressed: () { 135 | _fabAnimationController.reset(); 136 | _borderRadiusAnimationController.reset(); 137 | _borderRadiusAnimationController.forward(); 138 | _fabAnimationController.forward(); 139 | }, 140 | ), 141 | floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked, 142 | bottomNavigationBar: AnimatedBottomNavigationBar.builder( 143 | itemCount: iconList.length, 144 | tabBuilder: (int index, bool isActive) { 145 | final color = isActive 146 | ? colors.activeNavigationBarColor 147 | : colors.notActiveNavigationBarColor; 148 | return Column( 149 | mainAxisSize: MainAxisSize.min, 150 | mainAxisAlignment: MainAxisAlignment.center, 151 | children: [ 152 | Icon( 153 | iconList[index], 154 | size: 24, 155 | color: color, 156 | ), 157 | const SizedBox(height: 4), 158 | Padding( 159 | padding: const EdgeInsets.symmetric(horizontal: 8), 160 | child: AutoSizeText( 161 | "brightness $index", 162 | maxLines: 1, 163 | style: TextStyle(color: color), 164 | group: autoSizeGroup, 165 | ), 166 | ) 167 | ], 168 | ); 169 | }, 170 | backgroundColor: colors.bottomNavigationBarBackgroundColor, 171 | activeIndex: _bottomNavIndex, 172 | splashColor: colors.activeNavigationBarColor, 173 | notchAndCornersAnimation: borderRadiusAnimation, 174 | splashSpeedInMilliseconds: 300, 175 | notchSmoothness: NotchSmoothness.defaultEdge, 176 | gapLocation: GapLocation.center, 177 | leftCornerRadius: 32, 178 | rightCornerRadius: 32, 179 | onTap: (index) => setState(() => _bottomNavIndex = index), 180 | hideAnimationController: _hideBottomBarAnimationController, 181 | shadow: BoxShadow( 182 | offset: Offset(0, 1), 183 | blurRadius: 12, 184 | spreadRadius: 0.5, 185 | color: colors.activeNavigationBarColor, 186 | ), 187 | ), 188 | ); 189 | } 190 | } 191 | 192 | class NavigationScreen extends StatefulWidget { 193 | final IconData iconData; 194 | 195 | NavigationScreen(this.iconData) : super(); 196 | 197 | @override 198 | _NavigationScreenState createState() => _NavigationScreenState(); 199 | } 200 | 201 | class _NavigationScreenState extends State 202 | with TickerProviderStateMixin { 203 | late AnimationController _controller; 204 | late Animation animation; 205 | 206 | @override 207 | void didUpdateWidget(NavigationScreen oldWidget) { 208 | super.didUpdateWidget(oldWidget); 209 | if (oldWidget.iconData != widget.iconData) { 210 | _startAnimation(); 211 | } 212 | } 213 | 214 | @override 215 | void initState() { 216 | _controller = AnimationController( 217 | vsync: this, 218 | duration: Duration(milliseconds: 1000), 219 | ); 220 | animation = CurvedAnimation( 221 | parent: _controller, 222 | curve: Curves.easeIn, 223 | ); 224 | _controller.forward(); 225 | super.initState(); 226 | } 227 | 228 | _startAnimation() { 229 | _controller = AnimationController( 230 | vsync: this, 231 | duration: Duration(milliseconds: 1000), 232 | ); 233 | animation = CurvedAnimation( 234 | parent: _controller, 235 | curve: Curves.easeIn, 236 | ); 237 | _controller.forward(); 238 | } 239 | 240 | @override 241 | void dispose() { 242 | _controller.dispose(); 243 | super.dispose(); 244 | } 245 | 246 | @override 247 | Widget build(BuildContext context) { 248 | final colors = Theme.of(context).extension()!; 249 | return Container( 250 | color: Theme.of(context).colorScheme.background, 251 | child: ListView( 252 | children: [ 253 | SizedBox(height: 64), 254 | Center( 255 | child: CircularRevealAnimation( 256 | animation: animation, 257 | centerOffset: Offset(80, 80), 258 | maxRadius: MediaQuery.of(context).size.longestSide * 1.1, 259 | child: Icon( 260 | widget.iconData, 261 | color: colors.activeNavigationBarColor, 262 | size: 160, 263 | ), 264 | ), 265 | ), 266 | ], 267 | ), 268 | ); 269 | } 270 | } 271 | -------------------------------------------------------------------------------- /example/lib/theme/app_theme.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | import 'custom_colors_theme.dart'; 4 | 5 | class AppTheme { 6 | static HexColor colorOrange = HexColor('#FFA400'); 7 | static HexColor colorGray = HexColor('#373A36'); 8 | 9 | static ThemeData get({required bool isLight}) { 10 | final base = isLight ? ThemeData.light() : ThemeData.dark(); 11 | return base.copyWith( 12 | extensions: [ 13 | CustomColorsTheme( 14 | colorLabelColor: isLight ? Colors.grey : const Color(0xFF7A7FB0), 15 | bottomNavigationBarBackgroundColor: isLight ? Colors.blue : colorGray, 16 | activeNavigationBarColor: isLight ? Colors.yellow : colorOrange, 17 | notActiveNavigationBarColor: Colors.white, 18 | shadowNavigationBarColor: isLight ? Colors.blue : colorOrange, 19 | ) 20 | ], 21 | floatingActionButtonTheme: FloatingActionButtonThemeData( 22 | backgroundColor: isLight ? Colors.yellow : colorOrange, 23 | ), 24 | appBarTheme: AppBarTheme( 25 | backgroundColor: isLight ? Colors.blue : colorGray, 26 | ), 27 | colorScheme: base.colorScheme.copyWith( 28 | surface: isLight ? Colors.blue : colorGray, 29 | background: isLight ? Colors.white : colorGray, 30 | ), 31 | ); 32 | } 33 | } 34 | 35 | class HexColor extends Color { 36 | HexColor(final String hexColor) : super(_getColorFromHex(hexColor)); 37 | 38 | static int _getColorFromHex(String hexColor) { 39 | hexColor = hexColor.toUpperCase().replaceAll('#', ''); 40 | if (hexColor.length == 6) { 41 | hexColor = 'FF' + hexColor; 42 | } 43 | return int.parse(hexColor, radix: 16); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /example/lib/theme/custom_colors_theme.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | @immutable 4 | class CustomColorsTheme extends ThemeExtension { 5 | const CustomColorsTheme({ 6 | required this.bottomNavigationBarBackgroundColor, 7 | required this.colorLabelColor, 8 | required this.activeNavigationBarColor, 9 | required this.notActiveNavigationBarColor, 10 | required this.shadowNavigationBarColor, 11 | }); 12 | 13 | final Color bottomNavigationBarBackgroundColor; 14 | final Color colorLabelColor; 15 | final Color activeNavigationBarColor; 16 | final Color notActiveNavigationBarColor; 17 | final Color shadowNavigationBarColor; 18 | 19 | @override 20 | CustomColorsTheme copyWith({ 21 | Color? bottomNavigationBarBackgroundColor, 22 | Color? colorLabelColor, 23 | Color? activeNavigationBarColor, 24 | Color? notActiveNavigationBarColor, 25 | Color? shadowNavigationBarColor, 26 | }) { 27 | return CustomColorsTheme( 28 | bottomNavigationBarBackgroundColor: bottomNavigationBarBackgroundColor ?? 29 | this.bottomNavigationBarBackgroundColor, 30 | colorLabelColor: colorLabelColor ?? this.colorLabelColor, 31 | activeNavigationBarColor: 32 | activeNavigationBarColor ?? this.activeNavigationBarColor, 33 | notActiveNavigationBarColor: 34 | notActiveNavigationBarColor ?? this.notActiveNavigationBarColor, 35 | shadowNavigationBarColor: 36 | shadowNavigationBarColor ?? this.shadowNavigationBarColor, 37 | ); 38 | } 39 | 40 | @override 41 | CustomColorsTheme lerp( 42 | ThemeExtension? other, 43 | double t, 44 | ) { 45 | if (other is! CustomColorsTheme) { 46 | return this; 47 | } 48 | return CustomColorsTheme( 49 | bottomNavigationBarBackgroundColor: Color.lerp( 50 | bottomNavigationBarBackgroundColor, 51 | other.bottomNavigationBarBackgroundColor, 52 | t) ?? 53 | bottomNavigationBarBackgroundColor, 54 | colorLabelColor: Color.lerp(colorLabelColor, other.colorLabelColor, t) ?? 55 | colorLabelColor, 56 | activeNavigationBarColor: Color.lerp( 57 | activeNavigationBarColor, other.activeNavigationBarColor, t) ?? 58 | activeNavigationBarColor, 59 | notActiveNavigationBarColor: Color.lerp(notActiveNavigationBarColor, 60 | other.notActiveNavigationBarColor, t) ?? 61 | notActiveNavigationBarColor, 62 | shadowNavigationBarColor: Color.lerp( 63 | shadowNavigationBarColor, other.shadowNavigationBarColor, t) ?? 64 | shadowNavigationBarColor, 65 | ); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /example/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: lanarsnavbarflutter 2 | description: A new Flutter application. 3 | 4 | # The following line prevents the package from being accidentally published to 5 | # pub.dev using `pub publish`. This is preferred for private packages. 6 | publish_to: 'none' # Remove this line if you wish to publish to pub.dev 7 | 8 | # The following defines the version and build number for your application. 9 | # A version number is three numbers separated by dots, like 1.2.43 10 | # followed by an optional build number separated by a +. 11 | # Both the version and the builder number may be overridden in flutter 12 | # build by specifying --build-name and --build-number, respectively. 13 | # In Android, build-name is used as versionName while build-number used as versionCode. 14 | # Read more about Android versioning at https://developer.android.com/studio/publish/versioning 15 | # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. 16 | # Read more about iOS versioning at 17 | # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html 18 | version: 1.0.0+1 19 | 20 | environment: 21 | sdk: ">=2.12.0 <3.0.0" 22 | 23 | dependencies: 24 | flutter: 25 | sdk: flutter 26 | rxdart: ^0.26.0 27 | auto_size_text: ^3.0.0-nullsafety.0 28 | circular_reveal_animation: ^2.0.0 29 | animated_bottom_navigation_bar: 30 | path: ../ 31 | 32 | 33 | # The following adds the Cupertino Icons font to your application. 34 | # Use with the CupertinoIcons class for iOS style icons. 35 | cupertino_icons: 1.0.2 36 | font_awesome_flutter: 10.1.0 37 | 38 | dev_dependencies: 39 | flutter_test: 40 | sdk: flutter 41 | 42 | # For information on the generic Dart part of this file, see the 43 | # following page: https://dart.dev/tools/pub/pubspec 44 | 45 | # The following section is specific to Flutter. 46 | flutter: 47 | 48 | # The following line ensures that the Material Icons font is 49 | # included with your application, so that you can use the icons in 50 | # the material Icons class. 51 | uses-material-design: true 52 | 53 | # To add assets to your application, add an assets section, like this: 54 | # assets: 55 | # - images/a_dot_burr.jpeg 56 | # - images/a_dot_ham.jpeg 57 | 58 | # An image asset can refer to one or more resolution-specific "variants", see 59 | # https://flutter.dev/assets-and-images/#resolution-aware. 60 | 61 | # For details regarding adding assets from package dependencies, see 62 | # https://flutter.dev/assets-and-images/#from-packages 63 | 64 | # To add custom fonts to your application, add a fonts section here, 65 | # in this "flutter" section. Each entry in this list should have a 66 | # "family" key with the font family name, and a "fonts" key with a 67 | # list giving the asset and other descriptors for the font. For 68 | # example: 69 | # fonts: 70 | # - family: Schyler 71 | # fonts: 72 | # - asset: fonts/Schyler-Regular.ttf 73 | # - asset: fonts/Schyler-Italic.ttf 74 | # style: italic 75 | # - family: Trajan Pro 76 | # fonts: 77 | # - asset: fonts/TrajanPro.ttf 78 | # - asset: fonts/TrajanPro_Bold.ttf 79 | # weight: 700 80 | # 81 | # For details regarding fonts from package dependencies, 82 | # see https://flutter.dev/custom-fonts/#from-packages 83 | -------------------------------------------------------------------------------- /example/res/values/strings_en.arb: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /lib/animated_bottom_navigation_bar.dart: -------------------------------------------------------------------------------- 1 | library animated_bottom_navigation_bar; 2 | 3 | import 'dart:ui'; 4 | 5 | import 'package:animated_bottom_navigation_bar/src/around_custom_painter.dart'; 6 | import 'package:animated_bottom_navigation_bar/src/circular_notch_and_corner_clipper.dart'; 7 | import 'package:animated_bottom_navigation_bar/src/circular_notched_and_cornered_shape.dart'; 8 | import 'package:animated_bottom_navigation_bar/src/exceptions.dart'; 9 | import 'package:animated_bottom_navigation_bar/src/gap_item.dart'; 10 | import 'package:animated_bottom_navigation_bar/src/navigation_bar_item.dart'; 11 | import 'package:animated_bottom_navigation_bar/src/safe_area_values.dart'; 12 | import 'package:animated_bottom_navigation_bar/src/visible_animator.dart'; 13 | import 'package:flutter/foundation.dart'; 14 | import 'package:flutter/material.dart'; 15 | 16 | export 'package:animated_bottom_navigation_bar/src/safe_area_values.dart'; 17 | 18 | /// Signature for a function that creates a widget for a given index & state. 19 | /// Used by [AnimatedBottomNavigationBar.builder]. 20 | typedef IndexedWidgetBuilder = Widget Function(int index, bool isActive); 21 | 22 | class AnimatedBottomNavigationBar extends StatefulWidget { 23 | /// Widgets to render in the tab bar. 24 | final IndexedWidgetBuilder? tabBuilder; 25 | 26 | /// Total item count. 27 | final int? itemCount; 28 | 29 | /// Icon data to render in the tab bar. 30 | final List? icons; 31 | 32 | /// Handler which is passed every updated active index. 33 | final Function(int) onTap; 34 | 35 | /// Current index of selected tab bar item. 36 | final int activeIndex; 37 | 38 | /// Optional custom size for each tab bar icon. Default is 24. 39 | final double? iconSize; 40 | 41 | /// Optional custom tab bar height. Default is 56. 42 | final double? height; 43 | 44 | /// Optional custom notch margin for Floating. Default is 8. 45 | final double? notchMargin; 46 | 47 | /// Optional custom maximum spread radius for splash selection animation. Default is 24. 48 | final double splashRadius; 49 | 50 | /// Optional custom splash selection animation speed. Default is 300 milliseconds. 51 | final int? splashSpeedInMilliseconds; 52 | 53 | /// Optional custom tab bar top-left corner radius. Default is 0. 54 | final double? leftCornerRadius; 55 | 56 | /// Optional custom tab bar top-right corner radius. Useless with [GapLocation.end]. Default is 0. 57 | final double? rightCornerRadius; 58 | 59 | /// Optional custom tab bar background color. Default is [Colors.white]. 60 | final Color? backgroundColor; 61 | 62 | /// Optional custom splash selection animation color. Default is [Colors.purple]. 63 | final Color? splashColor; 64 | 65 | /// Optional custom currently selected tab bar [IconData] color. Default is [Colors.deepPurpleAccent] 66 | final Color? activeColor; 67 | 68 | /// Optional custom currently unselected tab bar [IconData] color. Default is [Colors.black] 69 | final Color? inactiveColor; 70 | 71 | /// Optional custom [Animation] to animate corners and notch appearing. 72 | final Animation? notchAndCornersAnimation; 73 | 74 | /// Optional custom type of notch. Default is [NotchSmoothness.defaultEdge]. 75 | final NotchSmoothness? notchSmoothness; 76 | 77 | /// Location of the free space between tab bar items for notch. 78 | /// Must have the same location if [FloatingActionButtonLocation.centerDocked] or [FloatingActionButtonLocation.endDocked]. 79 | /// Default is [GapLocation.end]. 80 | final GapLocation? gapLocation; 81 | 82 | /// Free space width between tab bar items. The preferred width is equal to total width of [FloatingActionButton] and double [notchMargin]. 83 | /// Default is 72. 84 | final double? gapWidth; 85 | 86 | /// Optional custom tab bar elevation. Default is 8. 87 | final double? elevation; 88 | 89 | /// Optional custom shadow around the navigation bar. 90 | final Shadow? shadow; 91 | 92 | /// Specifies whether to avoid system intrusions for specific sides 93 | final SafeAreaValues safeAreaValues; 94 | 95 | ///The [Curve] that the hide animation will follow. 96 | ///Defaults to [Curves.fastOutSlowIn], 97 | final Curve? hideAnimationCurve; 98 | 99 | /// Optional custom border color around the navigation bar. Default is [Colors.transparent]. 100 | final Color? borderColor; 101 | 102 | /// Optional custom border width around the navigation bar. Default is 2.0. 103 | final double? borderWidth; 104 | 105 | /// Optional hide bottom bar animation controller 106 | final AnimationController? hideAnimationController; 107 | 108 | /// Optional background gradient. 109 | /// 110 | /// If this is specified, [backgroundColor] has no effect. 111 | final Gradient? backgroundGradient; 112 | 113 | /// Whether blur effect should be applied. 114 | /// 115 | /// Makes sense only if [backgroundColor] opacity is < 1. 116 | final bool blurEffect; 117 | 118 | /// Filter to apply blurring effect. 119 | final ImageFilter? blurFilter; 120 | 121 | /// Optional scale effect factor. Default is 1. 122 | /// 123 | /// To disable scale effect set value of 0. 124 | final double scaleFactor; 125 | 126 | static const _defaultSplashRadius = 24.0; 127 | 128 | AnimatedBottomNavigationBar._internal( 129 | {Key? key, 130 | required this.activeIndex, 131 | required this.onTap, 132 | this.tabBuilder, 133 | this.itemCount, 134 | this.icons, 135 | this.height, 136 | this.splashRadius = _defaultSplashRadius, 137 | this.splashSpeedInMilliseconds, 138 | this.notchMargin, 139 | this.backgroundColor, 140 | this.splashColor, 141 | this.activeColor, 142 | this.inactiveColor, 143 | this.notchAndCornersAnimation, 144 | this.leftCornerRadius, 145 | this.rightCornerRadius, 146 | this.iconSize, 147 | this.notchSmoothness, 148 | this.gapLocation, 149 | this.gapWidth, 150 | this.elevation, 151 | this.shadow, 152 | this.borderColor, 153 | this.borderWidth, 154 | this.safeAreaValues = const SafeAreaValues(), 155 | this.hideAnimationCurve, 156 | this.hideAnimationController, 157 | this.backgroundGradient, 158 | this.blurEffect = false, 159 | this.blurFilter, 160 | this.scaleFactor = 1.0}) 161 | : assert(icons != null || itemCount != null), 162 | assert( 163 | ((itemCount ?? icons!.length) >= 2) && 164 | ((itemCount ?? icons!.length) <= 5), 165 | ), 166 | super(key: key) { 167 | if (gapLocation == GapLocation.end) { 168 | if (rightCornerRadius != 0) 169 | throw NonAppropriatePathException( 170 | 'RightCornerRadius along with ${GapLocation.end} or/and ${FloatingActionButtonLocation.endDocked} causes render issue => ' 171 | 'consider set rightCornerRadius to 0.'); 172 | } 173 | if (gapLocation == GapLocation.center) { 174 | final iconsCountIsOdd = (itemCount ?? icons!.length).isOdd; 175 | if (iconsCountIsOdd) 176 | throw NonAppropriatePathException( 177 | 'Odd count of icons along with $gapLocation causes render issue => ' 178 | 'consider set gapLocation to ${GapLocation.end}'); 179 | } 180 | } 181 | 182 | AnimatedBottomNavigationBar({ 183 | Key? key, 184 | required List icons, 185 | required int activeIndex, 186 | required Function(int) onTap, 187 | double? height, 188 | double? splashRadius, 189 | int? splashSpeedInMilliseconds, 190 | double? notchMargin, 191 | Color? backgroundColor, 192 | Color? splashColor, 193 | Color? activeColor, 194 | Color? inactiveColor, 195 | Animation? notchAndCornersAnimation, 196 | double? leftCornerRadius, 197 | double? rightCornerRadius, 198 | double? iconSize, 199 | NotchSmoothness? notchSmoothness, 200 | GapLocation? gapLocation, 201 | double? gapWidth, 202 | double? elevation, 203 | Shadow? shadow, 204 | Color? borderColor, 205 | double? borderWidth, 206 | SafeAreaValues safeAreaValues = const SafeAreaValues(), 207 | Curve? hideAnimationCurve, 208 | AnimationController? hideAnimationController, 209 | Gradient? backgroundGradient, 210 | ImageFilter? imageFilter, 211 | bool blurEffect = false, 212 | double scaleFactor = 1.0, 213 | }) : this._internal( 214 | key: key, 215 | icons: icons, 216 | activeIndex: activeIndex, 217 | onTap: onTap, 218 | height: height, 219 | splashRadius: splashRadius ?? _defaultSplashRadius, 220 | splashSpeedInMilliseconds: splashSpeedInMilliseconds, 221 | notchMargin: notchMargin, 222 | backgroundColor: backgroundColor, 223 | splashColor: splashColor, 224 | activeColor: activeColor, 225 | inactiveColor: inactiveColor, 226 | notchAndCornersAnimation: notchAndCornersAnimation, 227 | leftCornerRadius: leftCornerRadius ?? 0, 228 | rightCornerRadius: rightCornerRadius ?? 0, 229 | iconSize: iconSize, 230 | notchSmoothness: notchSmoothness, 231 | gapLocation: gapLocation ?? GapLocation.end, 232 | gapWidth: gapWidth, 233 | elevation: elevation, 234 | shadow: shadow, 235 | borderColor: borderColor, 236 | borderWidth: borderWidth, 237 | safeAreaValues: safeAreaValues, 238 | hideAnimationCurve: hideAnimationCurve, 239 | hideAnimationController: hideAnimationController, 240 | backgroundGradient: backgroundGradient, 241 | blurFilter: imageFilter, 242 | blurEffect: blurEffect, 243 | scaleFactor: scaleFactor, 244 | ); 245 | 246 | AnimatedBottomNavigationBar.builder({ 247 | Key? key, 248 | required int itemCount, 249 | required IndexedWidgetBuilder tabBuilder, 250 | required int activeIndex, 251 | required Function(int) onTap, 252 | double? height, 253 | double? splashRadius, 254 | int? splashSpeedInMilliseconds, 255 | double? notchMargin, 256 | Color? backgroundColor, 257 | Color? splashColor, 258 | Animation? notchAndCornersAnimation, 259 | double? leftCornerRadius, 260 | double? rightCornerRadius, 261 | NotchSmoothness? notchSmoothness, 262 | GapLocation? gapLocation, 263 | double? gapWidth, 264 | double? elevation, 265 | Shadow? shadow, 266 | Color? borderColor, 267 | double? borderWidth, 268 | SafeAreaValues safeAreaValues = const SafeAreaValues(), 269 | Curve? hideAnimationCurve, 270 | AnimationController? hideAnimationController, 271 | Gradient? backgroundGradient, 272 | bool blurEffect = false, 273 | ImageFilter? imageFilter, 274 | double scaleFactor = 1.0, 275 | }) : this._internal( 276 | key: key, 277 | tabBuilder: tabBuilder, 278 | itemCount: itemCount, 279 | activeIndex: activeIndex, 280 | onTap: onTap, 281 | height: height, 282 | splashRadius: splashRadius ?? _defaultSplashRadius, 283 | splashSpeedInMilliseconds: splashSpeedInMilliseconds, 284 | notchMargin: notchMargin, 285 | backgroundColor: backgroundColor, 286 | splashColor: splashColor, 287 | notchAndCornersAnimation: notchAndCornersAnimation, 288 | leftCornerRadius: leftCornerRadius ?? 0, 289 | rightCornerRadius: rightCornerRadius ?? 0, 290 | notchSmoothness: notchSmoothness, 291 | gapLocation: gapLocation ?? GapLocation.end, 292 | gapWidth: gapWidth, 293 | elevation: elevation, 294 | shadow: shadow, 295 | borderColor: borderColor, 296 | borderWidth: borderWidth, 297 | safeAreaValues: safeAreaValues, 298 | hideAnimationCurve: hideAnimationCurve, 299 | hideAnimationController: hideAnimationController, 300 | backgroundGradient: backgroundGradient, 301 | blurEffect: blurEffect, 302 | blurFilter: imageFilter, 303 | scaleFactor: scaleFactor, 304 | ); 305 | 306 | @override 307 | _AnimatedBottomNavigationBarState createState() => 308 | _AnimatedBottomNavigationBarState(); 309 | } 310 | 311 | class _AnimatedBottomNavigationBarState 312 | extends State with TickerProviderStateMixin { 313 | late ValueListenable geometryListenable; 314 | 315 | late final AnimationController _bubbleController; 316 | 317 | double _bubbleRadius = 0; 318 | double _iconScale = 1; 319 | 320 | @override 321 | void initState() { 322 | super.initState(); 323 | _bubbleController = AnimationController( 324 | duration: Duration(milliseconds: widget.splashSpeedInMilliseconds ?? 300), 325 | vsync: this, 326 | ); 327 | 328 | final bubbleCurve = CurvedAnimation( 329 | parent: _bubbleController, 330 | curve: Curves.linear, 331 | ); 332 | 333 | Tween(begin: 0, end: 1).animate(bubbleCurve) 334 | ..addListener(() { 335 | setState(() { 336 | _bubbleRadius = widget.splashRadius * bubbleCurve.value; 337 | if (_bubbleRadius == widget.splashRadius) { 338 | _bubbleRadius = 0; 339 | } 340 | 341 | if (bubbleCurve.value < 0.5) { 342 | _iconScale = 1 + bubbleCurve.value * widget.scaleFactor; 343 | } else { 344 | _iconScale = 345 | 1 + widget.scaleFactor - bubbleCurve.value * widget.scaleFactor; 346 | } 347 | }); 348 | }); 349 | } 350 | 351 | @override 352 | void didChangeDependencies() { 353 | super.didChangeDependencies(); 354 | geometryListenable = Scaffold.geometryOf(context); 355 | 356 | widget.notchAndCornersAnimation?..addListener(() => setState(() {})); 357 | } 358 | 359 | @override 360 | void didUpdateWidget(AnimatedBottomNavigationBar oldWidget) { 361 | super.didUpdateWidget(oldWidget); 362 | if (widget.activeIndex != oldWidget.activeIndex) { 363 | _startBubbleAnimation(); 364 | } 365 | } 366 | 367 | _startBubbleAnimation() { 368 | // Stop animation if it's currently running 369 | if (_bubbleController.isAnimating) { 370 | _bubbleController.reset(); 371 | } 372 | _bubbleController.forward(from: 0); 373 | } 374 | 375 | @override 376 | void dispose() { 377 | _bubbleController.dispose(); 378 | super.dispose(); 379 | } 380 | 381 | @override 382 | Widget build(BuildContext context) { 383 | final clipper = CircularNotchedAndCorneredRectangleClipper( 384 | shape: CircularNotchedAndCorneredRectangle( 385 | animation: widget.notchAndCornersAnimation, 386 | notchSmoothness: widget.notchSmoothness ?? NotchSmoothness.defaultEdge, 387 | gapLocation: widget.gapLocation ?? GapLocation.end, 388 | leftCornerRadius: widget.leftCornerRadius ?? 0.0, 389 | rightCornerRadius: widget.rightCornerRadius ?? 0.0, 390 | ), 391 | geometry: geometryListenable, 392 | notchMargin: widget.notchMargin ?? 8, 393 | ); 394 | 395 | return PhysicalShape( 396 | elevation: widget.elevation ?? 8, 397 | color: Colors.transparent, 398 | clipper: clipper, 399 | child: AroundCustomPainter( 400 | clipper: clipper, 401 | shadow: widget.shadow, 402 | borderColor: widget.borderColor ?? Colors.transparent, 403 | borderWidth: widget.borderWidth ?? 2, 404 | child: widget.hideAnimationController != null 405 | ? VisibleAnimator( 406 | showController: widget.hideAnimationController!, 407 | curve: widget.hideAnimationCurve ?? Curves.fastOutSlowIn, 408 | child: _buildBottomBar(context), 409 | ) 410 | : _buildBottomBar(context), 411 | ), 412 | ); 413 | } 414 | 415 | Widget _buildBottomBar(BuildContext context) { 416 | final backgroundColor = widget.backgroundColor ?? Colors.white; 417 | final bottomBarBackgroundColor = widget.backgroundGradient != null 418 | ? Colors.transparent 419 | : backgroundColor; 420 | 421 | return Material( 422 | clipBehavior: Clip.antiAlias, 423 | color: bottomBarBackgroundColor, 424 | child: DecoratedBox( 425 | decoration: BoxDecoration(gradient: widget.backgroundGradient), 426 | child: SafeArea( 427 | top: widget.safeAreaValues.top, 428 | bottom: widget.safeAreaValues.bottom, 429 | left: widget.safeAreaValues.left, 430 | right: widget.safeAreaValues.right, 431 | child: widget.blurEffect 432 | ? ClipRect( 433 | child: BackdropFilter( 434 | filter: widget.blurFilter ?? 435 | ImageFilter.blur(sigmaX: 5, sigmaY: 10), 436 | child: _buildBody(context), 437 | ), 438 | ) 439 | : _buildBody(context), 440 | ), 441 | ), 442 | ); 443 | } 444 | 445 | Widget _buildBody(BuildContext context) { 446 | final bottomPadding = 447 | widget.safeAreaValues.bottom ? 0 : MediaQuery.paddingOf(context).bottom; 448 | return Container( 449 | height: (widget.height ?? kBottomNavigationBarHeight) + bottomPadding, 450 | decoration: BoxDecoration( 451 | color: widget.backgroundColor ?? Colors.white, 452 | gradient: widget.backgroundGradient, 453 | ), 454 | child: Row( 455 | mainAxisAlignment: MainAxisAlignment.start, 456 | mainAxisSize: MainAxisSize.max, 457 | children: _buildItems(), 458 | ), 459 | ); 460 | } 461 | 462 | List _buildItems() { 463 | final gapWidth = widget.gapWidth ?? 72; 464 | final gapItemWidth = widget.notchAndCornersAnimation != null 465 | ? gapWidth * widget.notchAndCornersAnimation!.value 466 | : gapWidth; 467 | final itemCount = widget.itemCount ?? widget.icons!.length; 468 | 469 | final items = []; 470 | for (var i = 0; i < itemCount; i++) { 471 | final isActive = i == widget.activeIndex; 472 | 473 | if (widget.gapLocation == GapLocation.center && i == itemCount / 2) { 474 | items.add(GapItem(width: gapItemWidth)); 475 | } 476 | 477 | items.add( 478 | NavigationBarItem( 479 | isActive: isActive, 480 | bubbleRadius: _bubbleRadius, 481 | maxBubbleRadius: widget.splashRadius, 482 | bubbleColor: widget.splashColor, 483 | activeColor: widget.activeColor, 484 | inactiveColor: widget.inactiveColor, 485 | child: widget.tabBuilder?.call(i, isActive), 486 | iconData: widget.icons?.elementAt(i), 487 | iconScale: _iconScale, 488 | iconSize: widget.iconSize, 489 | onTap: () => widget.onTap(i), 490 | ), 491 | ); 492 | 493 | if (widget.gapLocation == GapLocation.end && i == itemCount - 1) { 494 | items.add(GapItem(width: gapItemWidth)); 495 | } 496 | } 497 | return items; 498 | } 499 | } 500 | 501 | enum NotchSmoothness { 502 | sharpEdge, 503 | defaultEdge, 504 | softEdge, 505 | smoothEdge, 506 | verySmoothEdge 507 | } 508 | 509 | enum GapLocation { none, center, end } 510 | -------------------------------------------------------------------------------- /lib/src/around_custom_painter.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | @immutable 4 | class AroundCustomPainter extends StatelessWidget { 5 | final CustomClipper clipper; 6 | 7 | final Shadow? shadow; 8 | 9 | final double borderWidth; 10 | final Color borderColor; 11 | 12 | final Widget child; 13 | 14 | AroundCustomPainter({ 15 | required this.clipper, 16 | required this.borderWidth, 17 | required this.borderColor, 18 | required this.child, 19 | this.shadow, 20 | }); 21 | 22 | @override 23 | Widget build(BuildContext context) { 24 | return CustomPaint( 25 | key: UniqueKey(), 26 | painter: _AroundCustomPainter( 27 | clipper: this.clipper, 28 | shadow: this.shadow, 29 | borderColor: this.borderColor, 30 | borderWidth: this.borderWidth, 31 | ), 32 | child: ClipPath(child: child, clipper: this.clipper), 33 | ); 34 | } 35 | } 36 | 37 | class _AroundCustomPainter extends CustomPainter { 38 | final CustomClipper clipper; 39 | 40 | final Shadow? shadow; 41 | final double borderWidth; 42 | final Color borderColor; 43 | 44 | _AroundCustomPainter({ 45 | required this.borderColor, 46 | required this.borderWidth, 47 | required this.clipper, 48 | this.shadow, 49 | }); 50 | 51 | @override 52 | void paint(Canvas canvas, Size size) { 53 | final clipPath = clipper.getClip(size); 54 | 55 | final borderPaint = Paint() 56 | ..color = borderColor 57 | ..strokeCap = StrokeCap.square 58 | ..style = PaintingStyle.stroke 59 | ..strokeWidth = borderWidth; 60 | final shadowPaint = shadow?.toPaint(); 61 | 62 | if (size.height != 0) { 63 | if (borderPaint.color.value != Colors.transparent.value) { 64 | canvas.drawPath(clipPath, borderPaint); 65 | } 66 | if (shadow != null && shadow!.color.value != Colors.transparent.value) { 67 | canvas.drawPath(clipPath.shift(shadow!.offset), shadowPaint!); 68 | } 69 | } 70 | } 71 | 72 | @override 73 | bool shouldRepaint(CustomPainter oldDelegate) => true; 74 | } 75 | -------------------------------------------------------------------------------- /lib/src/bubble_selection_painter.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class BubblePainter extends CustomPainter { 4 | final double bubbleRadius; 5 | final double maxBubbleRadius; 6 | final Color? bubbleColor; 7 | final Color? endColor; 8 | 9 | BubblePainter({ 10 | required this.bubbleRadius, 11 | required this.maxBubbleRadius, 12 | this.bubbleColor = Colors.purple, 13 | }) : endColor = Color.lerp(bubbleColor, Colors.white, 0.8), 14 | super(); 15 | 16 | @override 17 | void paint(Canvas canvas, Size size) { 18 | if (bubbleRadius == maxBubbleRadius) return; 19 | 20 | var animationProgress = bubbleRadius / maxBubbleRadius; 21 | 22 | double strokeWidth = bubbleRadius < maxBubbleRadius * 0.5 23 | ? bubbleRadius 24 | : maxBubbleRadius - bubbleRadius; 25 | 26 | final paint = Paint() 27 | ..color = Color.lerp(bubbleColor, endColor, animationProgress)! 28 | ..strokeWidth = strokeWidth 29 | ..style = PaintingStyle.stroke; 30 | 31 | canvas.drawCircle( 32 | Offset(size.width / 2, size.height / 2), bubbleRadius, paint); 33 | } 34 | 35 | @override 36 | bool shouldRepaint(CustomPainter oldDelegate) => true; 37 | } 38 | -------------------------------------------------------------------------------- /lib/src/circular_notch_and_corner_clipper.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/foundation.dart'; 2 | import 'package:flutter/material.dart'; 3 | 4 | class CircularNotchedAndCorneredRectangleClipper extends CustomClipper { 5 | final ValueListenable geometry; 6 | final NotchedShape shape; 7 | final double notchMargin; 8 | 9 | CircularNotchedAndCorneredRectangleClipper({ 10 | required this.geometry, 11 | required this.shape, 12 | required this.notchMargin, 13 | }) : super(reclip: geometry); 14 | 15 | @override 16 | Path getClip(Size size) { 17 | final Rect? button = geometry.value.floatingActionButtonArea?.translate( 18 | 0.0, 19 | geometry.value.bottomNavigationBarTop! * -1.0, 20 | ); 21 | 22 | return shape.getOuterPath(Offset.zero & size, button?.inflate(notchMargin)); 23 | } 24 | 25 | @override 26 | bool shouldReclip(CircularNotchedAndCorneredRectangleClipper oldClipper) { 27 | return oldClipper.geometry != geometry || 28 | oldClipper.shape != shape || 29 | oldClipper.notchMargin != notchMargin; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /lib/src/circular_notched_and_cornered_shape.dart: -------------------------------------------------------------------------------- 1 | import 'dart:math' as math; 2 | 3 | import 'package:animated_bottom_navigation_bar/animated_bottom_navigation_bar.dart'; 4 | import 'package:flutter/animation.dart'; 5 | import 'package:flutter/painting.dart'; 6 | 7 | import 'exceptions.dart'; 8 | 9 | class CircularNotchedAndCorneredRectangle extends NotchedShape { 10 | /// Creates a [CircularNotchedAndCorneredRectangle]. 11 | /// 12 | /// The same object can be used to create multiple shapes. 13 | final Animation? animation; 14 | final NotchSmoothness notchSmoothness; 15 | final GapLocation gapLocation; 16 | final double leftCornerRadius; 17 | final double rightCornerRadius; 18 | 19 | CircularNotchedAndCorneredRectangle({ 20 | required this.notchSmoothness, 21 | required this.gapLocation, 22 | required this.leftCornerRadius, 23 | required this.rightCornerRadius, 24 | this.animation, 25 | }); 26 | 27 | /// Creates a [Path] that describes a rectangle with a smooth circular notch. 28 | /// 29 | /// `host` is the bounding box for the returned shape. Conceptually this is 30 | /// the rectangle to which the notch will be applied. 31 | /// 32 | /// `guest` is the bounding box of a circle that the notch accommodates. All 33 | /// points in the circle bounded by `guest` will be outside of the returned 34 | /// path. 35 | /// 36 | /// The notch is curve that smoothly connects the host's top edge and 37 | /// the guest circle. 38 | @override 39 | Path getOuterPath(Rect host, Rect? guest) { 40 | if (guest == null || !host.overlaps(guest)) { 41 | if (this.rightCornerRadius > 0 || this.leftCornerRadius > 0) { 42 | double leftCornerRadius = 43 | this.leftCornerRadius * (animation?.value ?? 1); 44 | double rightCornerRadius = 45 | this.rightCornerRadius * (animation?.value ?? 1); 46 | return Path() 47 | ..moveTo(host.left, host.bottom) 48 | ..lineTo(host.left, host.top + leftCornerRadius) 49 | ..arcToPoint( 50 | Offset(host.left + leftCornerRadius, host.top), 51 | radius: Radius.circular(leftCornerRadius), 52 | clockwise: true, 53 | ) 54 | ..lineTo(host.right - rightCornerRadius, host.top) 55 | ..arcToPoint( 56 | Offset(host.right, host.top + rightCornerRadius), 57 | radius: Radius.circular(rightCornerRadius), 58 | clockwise: true, 59 | ) 60 | ..lineTo(host.right, host.bottom) 61 | ..lineTo(host.left, host.bottom) 62 | ..close(); 63 | } 64 | return Path()..addRect(host); 65 | } 66 | 67 | final guestCenterDx = guest.center.dx.toInt(); 68 | final halfOfHostWidth = host.width ~/ 2; 69 | 70 | if (guestCenterDx == halfOfHostWidth) { 71 | if (gapLocation == GapLocation.end) 72 | throw GapLocationException( 73 | 'Wrong gap location in $AnimatedBottomNavigationBar towards FloatingActionButtonLocation => ' 74 | 'consider use ${GapLocation.center} instead of $gapLocation or change FloatingActionButtonLocation'); 75 | } 76 | 77 | if (guestCenterDx != halfOfHostWidth) { 78 | if (gapLocation == GapLocation.center) 79 | throw GapLocationException( 80 | 'Wrong gap location in $AnimatedBottomNavigationBar towards FloatingActionButtonLocation => ' 81 | 'consider use ${GapLocation.end} instead of $gapLocation or change FloatingActionButtonLocation'); 82 | } 83 | 84 | // The guest's shape is a circle bounded by the guest rectangle. 85 | // So the guest's radius is half the guest width. 86 | double notchRadius = guest.width / 2 * (animation?.value ?? 1); 87 | double leftCornerRadius = this.leftCornerRadius * (animation?.value ?? 1); 88 | double rightCornerRadius = this.rightCornerRadius * (animation?.value ?? 1); 89 | 90 | // We build a path for the notch from 3 segments: 91 | // Segment A - a Bezier curve from the host's top edge to segment B. 92 | // Segment B - an arc with radius notchRadius. 93 | // Segment C - a Bezier curve from segment B back to the host's top edge. 94 | // 95 | // A detailed explanation and the derivation of the formulas below is 96 | // available at: https://goo.gl/Ufzrqn 97 | 98 | final double s1 = notchSmoothness.s1; 99 | final double s2 = notchSmoothness.s2; 100 | 101 | double r = notchRadius; 102 | double a = -1.0 * r - s2; 103 | double b = host.top - guest.center.dy; 104 | 105 | double n2 = math.sqrt(b * b * r * r * (a * a + b * b - r * r)); 106 | double p2xA = ((a * r * r) - n2) / (a * a + b * b); 107 | double p2xB = ((a * r * r) + n2) / (a * a + b * b); 108 | double p2yA = math.sqrt(r * r - p2xA * p2xA); 109 | double p2yB = math.sqrt(r * r - p2xB * p2xB); 110 | 111 | List p = List.filled(6, Offset.zero, growable: true); 112 | 113 | // p0, p1, and p2 are the control points for segment A. 114 | p[0] = Offset(a - s1, b); 115 | p[1] = Offset(a, b); 116 | double cmp = b < 0 ? -1.0 : 1.0; 117 | p[2] = cmp * p2yA > cmp * p2yB ? Offset(p2xA, p2yA) : Offset(p2xB, p2yB); 118 | 119 | // p3, p4, and p5 are the control points for segment B, which is a mirror 120 | // of segment A around the y axis. 121 | p[3] = Offset(-1.0 * p[2].dx, p[2].dy); 122 | p[4] = Offset(-1.0 * p[1].dx, p[1].dy); 123 | p[5] = Offset(-1.0 * p[0].dx, p[0].dy); 124 | 125 | // translate all points back to the absolute coordinate system. 126 | for (int i = 0; i < p.length; i += 1) p[i] += guest.center; 127 | 128 | return Path() 129 | ..moveTo(host.left, host.bottom) 130 | ..lineTo(host.left, host.top + leftCornerRadius) 131 | ..arcToPoint( 132 | Offset(host.left + leftCornerRadius, host.top), 133 | radius: Radius.circular(leftCornerRadius), 134 | clockwise: true, 135 | ) 136 | ..lineTo(p[0].dx, p[0].dy) 137 | ..quadraticBezierTo(p[1].dx, p[1].dy, p[2].dx, p[2].dy) 138 | ..arcToPoint( 139 | p[3], 140 | radius: Radius.circular(notchRadius), 141 | clockwise: false, 142 | ) 143 | ..quadraticBezierTo(p[4].dx, p[4].dy, p[5].dx, p[5].dy) 144 | ..lineTo(host.right - rightCornerRadius, host.top) 145 | ..arcToPoint( 146 | Offset(host.right, host.top + rightCornerRadius), 147 | radius: Radius.circular(rightCornerRadius), 148 | clockwise: true, 149 | ) 150 | ..lineTo(host.right, host.bottom) 151 | ..lineTo(host.left, host.bottom) 152 | ..close(); 153 | } 154 | } 155 | 156 | extension on NotchSmoothness? { 157 | static const curveS1 = { 158 | NotchSmoothness.sharpEdge: 0.0, 159 | NotchSmoothness.defaultEdge: 15.0, 160 | NotchSmoothness.softEdge: 20.0, 161 | NotchSmoothness.smoothEdge: 30.0, 162 | NotchSmoothness.verySmoothEdge: 40.0, 163 | }; 164 | 165 | static const curveS2 = { 166 | NotchSmoothness.sharpEdge: 0.1, 167 | NotchSmoothness.defaultEdge: 1.0, 168 | NotchSmoothness.softEdge: 5.0, 169 | NotchSmoothness.smoothEdge: 15.0, 170 | NotchSmoothness.verySmoothEdge: 25.0, 171 | }; 172 | 173 | double get s1 => curveS1[this] ?? 15.0; 174 | 175 | double get s2 => curveS2[this] ?? 1.0; 176 | } 177 | -------------------------------------------------------------------------------- /lib/src/exceptions.dart: -------------------------------------------------------------------------------- 1 | class GapLocationException implements Exception { 2 | final String _cause; 3 | 4 | GapLocationException(this._cause) : super(); 5 | 6 | @override 7 | String toString() => _cause; 8 | } 9 | 10 | class NonAppropriatePathException implements Exception { 11 | final String _cause; 12 | 13 | NonAppropriatePathException(this._cause) : super(); 14 | 15 | @override 16 | String toString() => _cause; 17 | } 18 | 19 | class IllegalFloatingActionButtonSizeException implements Exception { 20 | String _cause; 21 | 22 | IllegalFloatingActionButtonSizeException(this._cause) : super(); 23 | 24 | @override 25 | String toString() => _cause; 26 | } 27 | -------------------------------------------------------------------------------- /lib/src/gap_item.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class GapItem extends StatelessWidget { 4 | final double width; 5 | 6 | GapItem({required this.width}); 7 | 8 | @override 9 | Widget build(BuildContext context) => Container(width: width); 10 | } 11 | -------------------------------------------------------------------------------- /lib/src/navigation_bar_item.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:animated_bottom_navigation_bar/src/bubble_selection_painter.dart'; 3 | import 'package:animated_bottom_navigation_bar/src/tab_item.dart'; 4 | 5 | class NavigationBarItem extends StatelessWidget { 6 | final bool isActive; 7 | final double bubbleRadius; 8 | final double maxBubbleRadius; 9 | final Color? bubbleColor; 10 | final Color? activeColor; 11 | final Color? inactiveColor; 12 | final IconData? iconData; 13 | final double iconScale; 14 | final double? iconSize; 15 | final VoidCallback onTap; 16 | final Widget? child; 17 | 18 | NavigationBarItem({ 19 | required this.isActive, 20 | required this.bubbleRadius, 21 | required this.maxBubbleRadius, 22 | required this.bubbleColor, 23 | required this.activeColor, 24 | required this.inactiveColor, 25 | required this.iconData, 26 | required this.iconScale, 27 | required this.iconSize, 28 | required this.onTap, 29 | this.child, 30 | }); 31 | 32 | @override 33 | Widget build(BuildContext context) { 34 | return Expanded( 35 | child: SizedBox.expand( 36 | child: CustomPaint( 37 | painter: BubblePainter( 38 | bubbleRadius: isActive ? bubbleRadius : 0, 39 | bubbleColor: bubbleColor, 40 | maxBubbleRadius: maxBubbleRadius, 41 | ), 42 | child: InkWell( 43 | child: Transform.scale( 44 | scale: isActive ? iconScale : 1, 45 | child: TabItem( 46 | isActive: isActive, 47 | iconData: iconData, 48 | iconSize: iconSize, 49 | activeColor: activeColor, 50 | inactiveColor: inactiveColor, 51 | child: child, 52 | ), 53 | ), 54 | splashColor: Colors.transparent, 55 | focusColor: Colors.transparent, 56 | highlightColor: Colors.transparent, 57 | hoverColor: Colors.transparent, 58 | onTap: onTap, 59 | ), 60 | ), 61 | ), 62 | ); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /lib/src/safe_area_values.dart: -------------------------------------------------------------------------------- 1 | /// An immutable set of values, specifying whether to avoid system intrusions for specific sides 2 | class SafeAreaValues { 3 | final bool left; 4 | final bool top; 5 | final bool right; 6 | final bool bottom; 7 | 8 | const SafeAreaValues({ 9 | this.left = true, 10 | this.top = true, 11 | this.right = true, 12 | this.bottom = true, 13 | }); 14 | } 15 | -------------------------------------------------------------------------------- /lib/src/tab_item.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class TabItem extends StatelessWidget { 4 | final IconData? iconData; 5 | final double? iconSize; 6 | final bool isActive; 7 | final Color? activeColor; 8 | final Color? inactiveColor; 9 | final Widget? child; 10 | 11 | const TabItem({ 12 | Key? key, 13 | required this.isActive, 14 | this.iconData, 15 | this.iconSize = 24, 16 | this.activeColor = Colors.deepPurpleAccent, 17 | this.inactiveColor = Colors.black, 18 | this.child, 19 | }) : super(key: key); 20 | 21 | @override 22 | Widget build(BuildContext context) => child ?? _buildDefaultTab(); 23 | 24 | Widget _buildDefaultTab() { 25 | return Icon( 26 | iconData, 27 | color: isActive ? activeColor : inactiveColor, 28 | size: iconSize, 29 | ); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /lib/src/visible_animator.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/widgets.dart'; 2 | 3 | class VisibleAnimator extends StatefulWidget { 4 | const VisibleAnimator({ 5 | Key? key, 6 | required this.child, 7 | required this.showController, 8 | required this.curve, 9 | }) : super(key: key); 10 | 11 | final Widget child; 12 | final Curve curve; 13 | 14 | final AnimationController showController; 15 | 16 | @override 17 | State createState() => _VisibleAnimatorState(); 18 | } 19 | 20 | class _VisibleAnimatorState extends State { 21 | late Animation _animation; 22 | 23 | @override 24 | void initState() { 25 | super.initState(); 26 | _animation = Tween(begin: 1, end: 0).animate( 27 | CurvedAnimation(parent: widget.showController, curve: widget.curve), 28 | ); 29 | } 30 | 31 | @override 32 | Widget build(BuildContext context) { 33 | return SizeTransition( 34 | axisAlignment: -1, 35 | sizeFactor: _animation, 36 | child: widget.child, 37 | ); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: animated_bottom_navigation_bar 2 | description: Animated Bottom Navigation Bar Widget implementation inspired by https://dribbble.com/shots/7134849-Simple-Tab-Bar-Animation 3 | version: 1.4.0 4 | homepage: https://github.com/LanarsInc/animated-bottom-navigation-bar-flutter 5 | 6 | environment: 7 | sdk: '>=3.0.0 <4.0.0' 8 | flutter: ">=3.16.0" 9 | 10 | dependencies: 11 | flutter: 12 | sdk: flutter 13 | 14 | dev_dependencies: 15 | flutter_test: 16 | sdk: flutter 17 | 18 | flutter: 19 | -------------------------------------------------------------------------------- /test/animatedbottomnavigationbar_test.dart: -------------------------------------------------------------------------------- 1 | void main() {} 2 | --------------------------------------------------------------------------------