ResponsiveAdaptiveManager
A comprehensive Flutter package for responsive and adaptive UI management that works seamlessly across mobile, tablet, desktop, and web platforms.
Features
π― Cross-Platform Support: Works on iOS, Android, Web, Windows, macOS, and Linux π± Device Detection: Automatic device type and platform detection π Responsive Calculations: Intelligent scaling for fonts, spacing, and dimensions π¨ Adaptive Layouts: Dynamic layout switching based on screen size π Configurable Baselines: Choose optimal baseline dimensions for your design system βΏ Accessibility: Built-in accessibility support and system integration β‘ Performance: Efficient caching and optimized calculations π§ Customizable: Extensive configuration options and breakpoint customization π Debug Support: Comprehensive debugging and visualization tools
Installation
Add this package to your pubspec.yaml
:
dependencies:
responsive_adaptive: ^x.y.z
flutter_shared_utilities: ^x.y.z
Then run:
flutter pub get
Quick Start
1. Initialize the Manager
import 'package:flutter/material.dart';
import 'package:responsive_adaptive/responsive_adaptive.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
// Initialize with platform-optimized baseline (recommended)
final manager = await ResponsiveAdaptiveManager.create(
ResponsiveSettings(
config: ResponsiveConfig.materialDesign(), // Android/Material baseline
// Or use: ResponsiveConfig.cupertino() for iOS
// Or use: ResponsiveConfig.webOptimized() for web/desktop
),
);
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Responsive Demo',
home: ResponsiveExample(),
);
}
}
2. Update Device Info in Your Widget
class ResponsiveExample extends StatefulWidget {
@override
_ResponsiveExampleState createState() => _ResponsiveExampleState();
}
class _ResponsiveExampleState extends State<ResponsiveExample> {
final ResponsiveAdaptiveManager _manager = ResponsiveAdaptiveManager.instance;
@override
void didChangeDependencies() {
super.didChangeDependencies();
_updateDeviceInfo();
}
void _updateDeviceInfo() {
final MediaQueryData mediaQuery = MediaQuery.of(context);
final DeviceInfo deviceInfo = DeviceInfo.fromMediaQuery(
mediaQuery,
_determineDeviceType(mediaQuery.size),
PlatformType.current,
);
_manager.updateDeviceInfo(deviceInfo);
}
DeviceType _determineDeviceType(Size size) {
final double shortestSide = math.min(size.width, size.height);
if (shortestSide < 600) return DeviceType.mobile;
if (shortestSide < 1024) return DeviceType.tablet;
return DeviceType.desktop;
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Responsive Demo'),
),
body: ResponsiveLayoutExample(),
);
}
}
3. Use Responsive Calculations
class ResponsiveLayoutExample extends StatelessWidget {
final ResponsiveAdaptiveManager _manager = ResponsiveAdaptiveManager.instance;
@override
Widget build(BuildContext context) {
return Padding(
padding: EdgeInsets.all(_manager.responsiveSpacing(16.0)),
child: Column(
children: [
// Responsive text
Text(
'Hello, Responsive World!',
style: TextStyle(
fontSize: _manager.responsiveFontSize(24.0),
),
),
SizedBox(height: _manager.responsiveSpacing(20.0)),
// Adaptive layout based on screen size
_manager.buildResponsive(
context: context,
extraSmall: (context) => _buildMobileLayout(),
small: (context) => _buildMobileLayout(),
medium: (context) => _buildTabletLayout(),
large: (context) => _buildDesktopLayout(),
extraLarge: (context) => _buildDesktopLayout(),
),
SizedBox(height: _manager.responsiveSpacing(20.0)),
// Responsive container
Container(
width: _manager.responsiveWidth(200.0),
height: _manager.responsiveHeight(100.0),
decoration: BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.circular(
_manager.responsiveBorderRadius(8.0),
),
),
child: Center(
child: Text(
'${_manager.getCurrentDeviceType().displayName}',
style: TextStyle(
color: Colors.white,
fontSize: _manager.responsiveFontSize(16.0),
),
),
),
),
],
),
);
}
Widget _buildMobileLayout() {
return Column(
children: [
_buildCard('Mobile Layout'),
_buildCard('Single Column'),
],
);
}
Widget _buildTabletLayout() {
return Row(
children: [
Expanded(child: _buildCard('Tablet Layout')),
SizedBox(width: _manager.responsiveSpacing(16.0)),
Expanded(child: _buildCard('Two Columns')),
],
);
}
Widget _buildDesktopLayout() {
return Row(
children: [
Expanded(child: _buildCard('Desktop Layout')),
SizedBox(width: _manager.responsiveSpacing(16.0)),
Expanded(child: _buildCard('Three')),
SizedBox(width: _manager.responsiveSpacing(16.0)),
Expanded(child: _buildCard('Columns')),
],
);
}
Widget _buildCard(String title) {
return Container(
padding: EdgeInsets.all(_manager.responsiveSpacing(16.0)),
decoration: BoxDecoration(
color: Colors.grey[100],
borderRadius: BorderRadius.circular(
_manager.responsiveBorderRadius(8.0),
),
),
child: Text(
title,
style: TextStyle(
fontSize: _manager.responsiveFontSize(14.0),
fontWeight: FontWeight.bold,
),
),
);
}
}
Baseline Configurations
Choose the optimal baseline dimensions for your design system:
Platform-Optimized Baselines
// Material Design 3 (recommended for Android/cross-platform)
ResponsiveConfig.materialDesign() // 360x800 baseline
// iOS/Cupertino Design
ResponsiveConfig.cupertino() // 375x812 baseline
// Web/Desktop Optimized
ResponsiveConfig.webOptimized() // 1920x1080 baseline
// Android-First
ResponsiveConfig.androidFirst() // 360x640 baseline
Custom Baseline
final customConfig = ResponsiveConfig(
baselineScreenWidth: 768.0, // Custom width baseline
baselineScreenHeight: 1024.0, // Custom height baseline
// ... other config options
);
final manager = await ResponsiveAdaptiveManager.create(
ResponsiveSettings(config: customConfig),
);
Why Baselines Matter
Different baselines produce different scaling results:
Example: 16px font on 414px wide screen
- iOS baseline (375px):
16 Γ (414Γ·375) = 17.7px
- Material baseline (360px):
16 Γ (414Γ·360) = 18.4px
- Web baseline (1920px):
16 Γ (414Γ·1920) = 3.5px
Choose based on your primary platform:
- π± Mobile-first β
ResponsiveConfig.materialDesign()
- π iOS-first β
ResponsiveConfig.cupertino()
- π Web/Desktop β
ResponsiveConfig.webOptimized()
- π€ Android-first β
ResponsiveConfig.androidFirst()
Advanced Usage
Custom Breakpoints
// Create custom breakpoints
final customBreakpoints = AdaptiveBreakpoints(
extraSmall: 320.0,
small: 480.0,
medium: 768.0,
large: 1024.0,
extraLarge: 1440.0,
customBreakpoints: {
'ultraWide': 2560.0,
'compact': 360.0,
},
);
// Use in settings
final settings = ResponsiveSettings(
breakpoints: customBreakpoints,
enableResponsiveAnimations: true,
enableResponsiveTypography: true,
);
await ResponsiveAdaptiveManager.instance.initialize(settings);
Platform-Specific Configurations
// Complete configuration with baseline optimization
final settings = ResponsiveSettings(
config: ResponsiveConfig.materialDesign().copyWith(
textScaleFactor: 1.0,
spacingScaleFactor: 1.0,
minFontSize: 12.0,
maxFontSize: 72.0,
// Baseline dimensions are set by materialDesign() factory
// baselineScreenWidth: 360.0,
// baselineScreenHeight: 800.0,
),
deviceScalingFactors: {
DeviceType.mobile: 0.9,
DeviceType.tablet: 1.0,
DeviceType.desktop: 1.1,
},
platformScalingFactors: {
PlatformType.iOS: 1.0,
PlatformType.android: 1.0,
PlatformType.web: 1.1,
PlatformType.windows: 1.2,
},
);
// Dynamic baseline selection based on platform
ResponsiveSettings getPlatformOptimizedSettings() {
if (Platform.isIOS) {
return ResponsiveSettings(config: ResponsiveConfig.cupertino());
} else if (Platform.isAndroid) {
return ResponsiveSettings(config: ResponsiveConfig.materialDesign());
} else {
return ResponsiveSettings(config: ResponsiveConfig.webOptimized());
}
}
Accessibility Support
// The manager automatically respects system accessibility settings
final accessibleFontSize = _manager.accessibleFontSize(16.0);
final accessibleSpacing = _manager.accessibleSpacing(12.0);
// Check for accessibility features
if (_manager.hasAccessibilityFeatures) {
// Adjust UI for accessibility
}
// Ensure minimum touch target size
final buttonSize = math.max(
48.0,
_manager.minTouchTargetSize,
);
Percentage-Based Layouts
Widget build(BuildContext context) {
return Container(
width: _manager.widthPercent(80), // 80% of screen width
height: _manager.heightPercent(60), // 60% of screen height
child: Column(
children: [
Container(
width: _manager.safeWidthPercent(100), // 100% of safe area width
height: _manager.safeHeightPercent(30), // 30% of safe area height
color: Colors.blue,
),
],
),
);
}
Adaptive Values
// Different values for different screen sizes
final columns = _manager.adaptiveValue<int>(
extraSmall: 1,
small: 1,
medium: 2,
large: 3,
extraLarge: 4,
fallback: 1,
);
// Device-type based values
final columnCount = _manager.adaptiveColumnCount(
mobile: 1,
tablet: 2,
desktop: 3,
fallback: 1,
);
Animation Support
// Responsive animation duration
AnimatedContainer(
duration: _manager.responsiveAnimationDuration(
Duration(milliseconds: 300),
),
curve: _manager.responsiveAnimationCurve,
// ... other properties
)
// Check if animations should be enabled
if (_manager.shouldEnableAnimations) {
// Perform animation
}
API Reference
Core Classes
ResponsiveAdaptiveManager
Main manager class implementing IResponsiveAdaptiveManager
.
ResponsiveSettings
Configuration model extending BaseDataModel
.
AdaptiveBreakpoints
Breakpoint definitions extending BaseDataModel
.
DeviceInfo
Device information model extending BaseDataModel
.
ResponsiveConfig
Responsive configuration extending BaseDataModel
with configurable baseline dimensions.
Factory Constructors:
ResponsiveConfig.materialDesign()
- Material Design 3 baseline (360x800)ResponsiveConfig.cupertino()
- iOS/Cupertino baseline (375x812)ResponsiveConfig.androidFirst()
- Android-first baseline (360x640)ResponsiveConfig.webOptimized()
- Web/desktop baseline (1920x1080)
BaselineExamples
Utility class for baseline configuration examples and comparisons.
Key Methods
Device Detection
getCurrentDeviceType()
- Get current device typegetCurrentPlatformType()
- Get current platform typegetCurrentScreenSize()
- Get current screen size categorygetCurrentOrientation()
- Get current orientation
Responsive Calculations
responsiveWidth(double)
- Calculate responsive widthresponsiveHeight(double)
- Calculate responsive heightresponsiveFontSize(double)
- Calculate responsive font sizeresponsiveSpacing(double)
- Calculate responsive spacingresponsivePadding(EdgeInsets)
- Calculate responsive paddingresponsiveMargin(EdgeInsets)
- Calculate responsive margin
Percentage-Based
widthPercent(double)
- Get width as percentage of screenheightPercent(double)
- Get height as percentage of screensafeWidthPercent(double)
- Get safe area width percentagesafeHeightPercent(double)
- Get safe area height percentage
Layout Helpers
shouldUseSingleColumn
- Check if single column layout should be usedshouldShowBottomNavigation
- Check if bottom navigation should be shownshouldShowNavigationDrawer
- Check if navigation drawer should be shown
Adaptive Values
adaptiveValue<T>()
- Get adaptive value based on screen sizeadaptiveColumnCount()
- Get adaptive column countadaptiveAspectRatio()
- Get adaptive aspect ratio
Device Types
DeviceType.mobile
- Mobile phonesDeviceType.tablet
- TabletsDeviceType.desktop
- Desktop computersDeviceType.ultraWide
- Ultra-wide displaysDeviceType.foldable
- Foldable devicesDeviceType.watch
- Watch displaysDeviceType.tv
- TV displays
Screen Sizes
ScreenSize.extraSmall
- Extra small screens (β€320px)ScreenSize.small
- Small screens (β€480px)ScreenSize.medium
- Medium screens (β€768px)ScreenSize.large
- Large screens (β€1024px)ScreenSize.extraLarge
- Extra large screens (>1024px)
Platform Types
PlatformType.iOS
- iOS devicesPlatformType.android
- Android devicesPlatformType.web
- Web browsersPlatformType.windows
- Windows desktopPlatformType.macOS
- macOS desktopPlatformType.linux
- Linux desktopPlatformType.fuchsia
- Fuchsia OS
Performance
The package includes several performance optimizations:
- Caching: Responsive calculations are cached to avoid repeated computations
- Lazy Loading: Device information is only updated when necessary
- Efficient Listeners: Event listeners are managed efficiently
- Memory Management: Automatic cache cleanup when limits are reached
Debug Mode
Enable debug mode for development:
ResponsiveAdaptiveManager.instance.enableDebugMode();
// Get debug information
final debugInfo = ResponsiveAdaptiveManager.instance.getDebugInfo();
print(debugInfo);
// Check cache statistics
final cacheStats = ResponsiveAdaptiveManager.instance.getCacheStats();
print('Cache hits: ${cacheStats['hits']}');
print('Cache misses: ${cacheStats['misses']}');
Baseline Comparison Tool
Use the baseline comparison utility to visualize how different baselines affect your UI:
import 'package:responsive_adaptive/responsive_adaptive.dart';
// Import the example utilities (available in example app)
import 'package:responsive_adaptive_example/utils/baseline_examples.dart';
// In your example/demo app
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
// Your app content
YourAppContent(),
// Baseline comparison widget
BaselineExamples.buildComparisonWidget(),
],
),
);
}
// Get best practice baseline for your app type
final settings = BaselineExamples.getBestPracticeBaseline(
appType: 'android-first', // or 'ios-first', 'web', 'tablet', etc.
);
final manager = await ResponsiveAdaptiveManager.create(settings);
Contributing
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature
) - Commit your changes (
git commit -m 'Add some amazing feature'
) - Push to the 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.
Support
For issues and feature requests, please visit the GitHub repository.
Changelog
See CHANGELOG.md for version history and updates.
Libraries
- responsive_adaptive
- A comprehensive Flutter package for responsive and adaptive UI management