motionx 0.1.1
motionx: ^0.1.1 copied to clipboard
A modern, highly customizable Flutter bottom navigation bar with floating indicators, smooth animations, badges, PageView synchronization, and extensible APIs.
MotionX #
A high-performance, fluid, and customizable navigation bar framework for Flutter featuring unified indicator physics, smooth Bezier notch cutouts, and flexible badge architecture.
Overview #
MotionX is designed to modernize bottom navigation in Flutter applications. Standard navigation components often suffer from rigid layouts, limited indicator shapes, or abrupt state transitions. MotionX addresses these limitations with a single frame-synchronized rendering architecture that computes floating indicator translation and background notch cutout geometry continuously from a single offset driver (animationOffset).
Key Architectural Pillars:
- Modern Design Language: Built ground-up to support elevated floating circles, background capsules, top pill bars, bottom underline strips, and custom geometry.
- Continuous Frame Synchronization: Synchronizes floating indicators and background notch cutouts frame-by-frame during user drag gestures and programmatic animations.
- Granular Customization: Complete control over shapes, proportional scaling, depth, Bezier shoulder radii, haptics, and padding.
- Flexible Badge Engine: Positioning system supporting preset anchors, pixel-precise offsets, follow-motion toggles, and customizable container/content metrics.
- Decoupled Controller Architecture: First-class integration with
PageControllerandTabControllerfor synchronizedPageViewdragging without layout recalculations. - Production Accessibility: Complete Right-to-Left (RTL) localization support, screen-reader semantics tags, and Material 3 compliance.
Preview #
[MotionX Preview]
Features #
- ✅ Floating Indicators: Elevated circular FAB, background capsule card, top accent pill, and bottom underline strip.
- ✅ Proportional
indicatorSizeScaling: Automatically scales widths, heights, and thickness across all built-in indicator shapes. - ✅ 2D Bezier Notch Geometry: Smooth Bezier cutouts (
SmoothNotchShape) and classic circular arc cutouts (ClassicNotchShape) with customizable cradle depth. - ✅ Persistent Docked Cutout: Background notch cutout remains permanently visible framing the active indicator at rest, during dragging, and after settling.
- ✅ Flexible Badge Positioning: Position badges using preset alignment anchors (
topRight,topLeft,bottomRight,bottomLeft,topCenter) or customOffset(dx, dy)vectors. - ✅ Decoupled Badge Opacity: Badges remain 100% visible on selected and unselected tabs with optional
followIndicatormotion lift. - ✅
PageView&TabControllerSync: Single continuous animation value binding for gesture dragging without position jumps. - ✅ Navigation Guards (
onTabWillChange): Asynchronous interceptors for tab switching validation (e.g. form confirmation modals). - ✅ Right-to-Left (RTL) Support: Automatic directionality inversion for internationalized applications.
- ✅ Accessible Semantics: Accessible button semantics, selected state flags, and custom semantic labels.
Installation #
Add motionx to your pubspec.yaml dependencies:
dependencies:
motionx: ^0.1.0
Then run:
flutter pub get
Quick Start #
import 'package:flutter/material.dart';
import 'package:motionx/motionx.dart';
class QuickStartExample extends StatefulWidget {
const QuickStartExample({super.key});
@override
State<QuickStartExample> createState() => _QuickStartExampleState();
}
class _QuickStartExampleState extends State<QuickStartExample> {
int _currentIndex = 0;
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Text('Active Tab Index: $_currentIndex'),
),
bottomNavigationBar: MotionXNavigationBar(
index: _currentIndex,
onTabSelected: (index) => setState(() => _currentIndex = index),
items: const [
MotionXItem(label: 'Explore', icon: Icon(Icons.explore_outlined)),
MotionXItem(label: 'Messages', icon: Icon(Icons.chat_bubble_outline)),
MotionXItem(label: 'Settings', icon: Icon(Icons.settings_outlined)),
],
),
);
}
}
Basic Usage #
A complete, production-ready implementation showcasing custom colors, active icons, badges, and smooth notch cutout styling:
import 'package:flutter/material.dart';
import 'package:motionx/motionx.dart';
class BasicUsageExample extends StatefulWidget {
const BasicUsageExample({super.key});
@override
State<BasicUsageExample> createState() => _BasicUsageExampleState();
}
class _BasicUsageExampleState extends State<BasicUsageExample> {
int _selectedIndex = 0;
@override
Widget build(BuildContext context) {
return Scaffold(
bottomNavigationBar: MotionXNavigationBar(
index: _selectedIndex,
onTabSelected: (index) => setState(() => _selectedIndex = index),
height: 65.0,
enableHaptics: true,
useSafeArea: true,
animationDuration: const Duration(milliseconds: 350),
animationCurve: Curves.easeOutCubic,
indicatorStyle: const MotionXIndicatorStyle(
shape: MotionXIndicatorShape.floatingCircle,
size: 56.0,
color: Color(0xFF6366F1),
shadows: [
BoxShadow(
color: Color(0x406366F1),
blurRadius: 12.0,
offset: Offset(0, 4),
),
],
),
notchStyle: const MotionXNotchStyle(
enabled: true,
depth: 0.5,
cornerRadius: 14.0,
shape: SmoothNotchShape(cornerRadius: 14.0),
),
items: const [
MotionXItem(
label: 'Explore',
icon: Icon(Icons.explore_outlined),
activeIcon: Icon(Icons.explore),
),
MotionXItem(
label: 'Messages',
icon: Icon(Icons.chat_bubble_outline),
activeIcon: Icon(Icons.chat_bubble),
badge: MotionXBadge(
text: '8',
badgeSize: 20.0,
position: MotionXBadgePosition.topRight,
),
),
MotionXItem(
label: 'Updates',
icon: Icon(Icons.notifications_outlined),
activeIcon: Icon(Icons.notifications),
badge: MotionXBadge.dot(
color: Colors.amber,
size: 10.0,
),
),
MotionXItem(
label: 'Settings',
icon: Icon(Icons.settings_outlined),
activeIcon: Icon(Icons.settings),
),
],
),
);
}
}
PageView Synchronization #
Connect MotionXNavigationBar to a PageController using MotionXController. The floating indicator and background notch follow swipe gestures in real time without lag or layout recalculations.
import 'package:flutter/material.dart';
import 'package:motionx/motionx.dart';
class PageViewSyncExample extends StatefulWidget {
const PageViewSyncExample({super.key});
@override
State<PageViewSyncExample> createState() => _PageViewSyncExampleState();
}
class _PageViewSyncExampleState extends State<PageViewSyncExample> {
late final MotionXController _navController;
late final PageController _pageController;
@override
void initState() {
super.initState();
_navController = MotionXController.create(initialIndex: 0);
_pageController = PageController(initialPage: 0);
_navController.attachPageController(_pageController);
}
@override
void dispose() {
_pageController.dispose();
_navController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: PageView(
controller: _pageController,
children: const [
Center(child: Text('Explore Page')),
Center(child: Text('Messages Page')),
Center(child: Text('Settings Page')),
],
),
bottomNavigationBar: MotionXNavigationBar(
controller: _navController,
items: const [
MotionXItem(label: 'Explore', icon: Icon(Icons.explore)),
MotionXItem(label: 'Messages', icon: Icon(Icons.chat_bubble)),
MotionXItem(label: 'Settings', icon: Icon(Icons.settings)),
],
),
);
}
}
Badge Examples #
MotionX includes a flexible badge engine supporting numeric text, dot indicators, custom alignment anchors, pixel nudges, and sizing parameters.
1. Dot Badge #
MotionXBadge.dot(
color: Colors.red,
size: 10.0,
position: MotionXBadgePosition.topRight,
)
2. Number Badge #
MotionXBadge(
text: '12',
backgroundColor: const Color(0xFFFF3B30),
textColor: Colors.white,
badgeSize: 20.0,
contentSize: 11.0,
)
3. Text Badge with Outline Border #
MotionXBadge(
text: 'NEW',
backgroundColor: const Color(0xFF10B981),
badgeSize: 22.0,
contentSize: 10.0,
padding: const EdgeInsets.symmetric(horizontal: 6.0, vertical: 2.0),
border: Border.all(color: Colors.white, width: 1.5),
)
4. Custom Position & Offset #
MotionXBadge(
text: '5',
position: MotionXBadgePosition(
alignment: Alignment.topRight,
offset: Offset(8.0, -2.0),
),
followIndicator: true, // Badge translates with icon lift animation
)
Indicator Styles #
MotionX provides 4 built-in indicator shapes and supports custom vector paths via customPainter:
1. Floating Circle (Default) #
Elevated circular indicator designed to sit above a docked 2D background notch cutout.
MotionXIndicatorStyle(
shape: MotionXIndicatorShape.floatingCircle,
size: 56.0,
color: Color(0xFF6366F1),
)
2. Capsule #
Stadium highlight card centered behind active tab content inside the navigation bar container.
MotionXIndicatorStyle(
shape: MotionXIndicatorShape.capsule,
size: 56.0,
color: Color(0xFF10B981),
)
3. Pill #
Compact floating bar positioned at the top edge of the navigation bar container.
MotionXIndicatorStyle(
shape: MotionXIndicatorShape.pill,
size: 56.0,
color: Color(0xFFEC4899),
)
4. Underline #
Sleek active strip positioned at the bottom edge of the navigation bar container.
MotionXIndicatorStyle(
shape: MotionXIndicatorShape.underline,
size: 56.0,
color: Color(0xFFF59E0B),
)
5. Custom Vector Painter #
Supply a custom CustomPainter to render arbitrary indicator geometry (e.g., diamonds, custom polygons).
MotionXIndicatorStyle(
shape: MotionXIndicatorShape.custom,
size: 56.0,
color: Colors.purple,
customPainter: MyCustomDiamondPainter(),
)
Notch Styles #
The background notch path is driven by strategy implementations of MotionXNotchShape.
Smooth Bezier Notch (SmoothNotchShape) #
Renders continuous Bezier curves for organic shoulder transitions:
MotionXNotchStyle(
enabled: true,
depth: 0.5,
cornerRadius: 14.0,
shape: SmoothNotchShape(cornerRadius: 14.0),
)
Classic Circular Arc Notch (ClassicNotchShape) #
Renders classic circular arc geometry:
MotionXNotchStyle(
enabled: true,
depth: 0.5,
shape: ClassicNotchShape(),
)
Customization Reference #
| Configuration Area | Parameter | Description |
|---|---|---|
| Bar Container | height |
Overall navigation bar height (defaults to 65.0). |
backgroundColor |
Background bar color (defaults to Theme.of(context).cardColor). |
|
useSafeArea |
Integrates SafeArea for devices with home indicator bars. |
|
| Indicator Style | shape |
floatingCircle, capsule, pill, underline, custom. |
size |
Base indicator size scaling width, height, and thickness proportionally. | |
color |
Active indicator fill color. | |
shadows |
List of BoxShadow objects for elevation rendering. |
|
| Notch Style | enabled |
Enables or disables background notch path geometry. |
depth |
Cradle depth ratio ($0.0 \to 1.0$). | |
shape |
SmoothNotchShape or ClassicNotchShape. |
|
| Interactions | enableHaptics |
Enables tactile feedback on tab selection. |
onTabWillChange |
Asynchronous interceptor returning bool to approve or cancel tab transitions. |
Interactive Example App #
The MotionX repository includes a full-featured Showcase Studio application in example/lib/main.dart.
The showcase app allows developers to interactively tweak indicator shapes, sizes, notch depths, Bezier radii, haptics, RTL directionality, and badge metrics in real time while generating ready-to-use Dart code snippets.
To run the showcase app locally:
cd example
flutter run
Accessibility & Localization #
- Screen-Reader Semantics: Every tab slot is wrapped in a
Semanticswidget marked withbutton: true, selected flags, and configurablesemanticLabelvalues. - Material 3 Palette: Fully compatible with Flutter
ColorSchemedynamic light and dark themes. - RTL Support: Calculates effective layout offsets based on active
Directionality, reversing gesture and animation vectors seamlessly for Right-to-Left locales.
Rendering Performance Architecture #
MotionX is designed for high performance:
- Single Continuous Animation Value: Both floating indicators and background notch cutouts derive 2D coordinates from a single
animationOffsetvalue inMotionXController. - Canvas-Level Painting: Background paths and notch cutouts are painted at the canvas level inside
CustomPainterwithout instantiating extra layout widgets. - No Layout Recalculation: Indicator motion during
PageViewdrags interpolates coordinates mathematically without triggering layout passes.
Roadmap #
Planned features for future releases:
- ❌ AGSL / SkSL Shaders: Liquid metal and chromatic aberration shader effects for floating indicators.
- ❌ Vertical Navigation Rail: Adaptive layout adapter for desktop and tablet form factors.
- ❌ Badge Entry Animations: Scale and bounce entry physics for dynamic badge updates.
Contributing #
Contributions are welcome! Please feel free to submit issues, feature requests, or pull requests on GitHub.
- Fork the Repository
- Create a Feature Branch (
git checkout -b feature/amazing-feature) - Commit Changes (
git commit -m 'Add amazing feature') - Push to Branch (
git push origin feature/amazing-feature) - Open a Pull Request
License #
This project is licensed under the MIT License - see the LICENSE file for details.