├── .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 | [](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 | [](https://pub.dev/packages/animated_bottom_navigation_bar)
6 |
7 | [](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 |
--------------------------------------------------------------------------------