responsive_wrapper 1.0.2
responsive_wrapper: ^1.0.2 copied to clipboard
A Flutter package for building responsive UIs that adapt to different screen sizes, device types, and orientations with automatic detection.
Responsive Wrapper #
A comprehensive Flutter package for building responsive UIs that adapt to different screen sizes, device types, and orientations. This package provides a clean and flexible API for creating responsive layouts with automatic device detection and orientation handling.
Features #
- Device Type Detection: Automatically detects phone, tablet, and desktop devices
- Orientation Support: Handle portrait and landscape orientations with different layouts
- Custom Breakpoints: Configure your own breakpoints for device type detection
- Parameterized Widgets: Pass data and state to your responsive layouts
- Pre-builders: Wrap responsive content with state management, themes, and more
- Responsive Values: Define different values for different device types and orientations
- Easy to Use: Simple API with comprehensive documentation and examples
Getting Started #
Add this to your package's pubspec.yaml file:
dependencies:
responsive_wrapper: ^1.0.2
Then run:
flutter pub get
Usage #
Basic Responsive Wrapper #
The simplest way to create responsive layouts:
import 'package:responsive_wrapper/responsive_wrapper.dart';
ResponsiveWrapper(
builder: (context, screenInfo) {
return Container(
padding: EdgeInsets.all(
screenInfo.isPhone ? 16.0 : 24.0,
),
child: Text(
'Device: ${screenInfo.deviceType.name}',
style: TextStyle(
fontSize: screenInfo.isPhone ? 16.0 : 20.0,
),
),
);
},
)
Responsive Layout #
Define different layouts for different device types:
import 'package:responsive_wrapper/layout.dart';
ResponsiveLayout(
phone: (context) => PhoneLayout(),
tablet: (context) => TabletLayout(),
desktop: (context) => DesktopLayout(),
)
Orientation-Aware Layouts #
Handle different orientations with specific layouts:
import 'package:responsive_wrapper/orientation_layout.dart';
ResponsiveOrientationLayout(
phonePortrait: (context) => PhonePortraitLayout(),
phoneLandscape: (context) => PhoneLandscapeLayout(),
tabletPortrait: (context) => TabletPortraitLayout(),
tabletLandscape: (context) => TabletLandscapeLayout(),
desktop: (context) => DesktopLayout(),
)
Parameterized Widgets #
Pass data to your responsive layouts:
ResponsiveWrapperWith<UserData>(
initialParam: userData,
builder: (context, screenInfo, userData) {
return UserProfile(user: userData);
},
)
Responsive Values #
Define different values for different device types and orientations:
final fontSize = ResponsiveOrientationValue<double>(
phonePortrait: 16.0,
phoneLandscape: 14.0,
tabletPortrait: 20.0,
tabletLandscape: 18.0,
desktop: 24.0,
).getValue(context);
Custom Breakpoints #
Configure your own breakpoints:
ResponsiveWrapper(
breakpoints: const ResponsiveBreakpoints(
phone: 480, // Custom phone breakpoint
tablet: 800, // Custom tablet breakpoint
),
builder: (context, screenInfo) {
// Your responsive content
},
)
Pre-builders #
Pre-builders allow you to wrap responsive content with additional functionality like state management, themes, or other wrapper widgets. They are executed before the main responsive builder and can provide context, state, or styling to your responsive layouts.
Basic Pre-builder
ResponsiveWrapper(
preBuilder: (context, child) => Container(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [Colors.blue.shade100, Colors.purple.shade100],
begin: Alignment.topLeft,
end: Alignment.bottomRight,
),
),
child: child,
),
builder: (context, screenInfo) {
return Text('Responsive content with gradient background');
},
)
State Management with Pre-builder
ResponsiveWrapper(
preBuilder: (context, child) => BlocBuilder<AppCubit, AppState>(
builder: (context, state) {
return state.isLoading
? CircularProgressIndicator()
: child;
},
),
builder: (context, screenInfo) {
return Text('Content that depends on app state');
},
)
Theme and Styling Wrappers
ResponsiveWrapper(
preBuilder: (context, child) => Theme(
data: Theme.of(context).copyWith(
cardTheme: CardTheme(
elevation: 8,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16),
),
),
),
child: Card(child: child),
),
builder: (context, screenInfo) {
return Padding(
padding: EdgeInsets.all(screenInfo.isPhone ? 16.0 : 24.0),
child: Text('Themed responsive content'),
);
},
)
Parameterized Pre-builder
For widgets that need to pass parameters to responsive layouts:
ResponsiveLayoutWith<String>(
preBuilder: (context, childBuilder) {
// Pre-builder can determine what parameter to pass
final user = UserService.getCurrentUser();
final userName = user?.name ?? 'Guest';
return Container(
decoration: BoxDecoration(
border: Border.all(color: Colors.blue),
borderRadius: BorderRadius.circular(8),
),
child: childBuilder(userName), // Pass parameter to child
);
},
phone: (context, userName) => Text('Hello $userName on phone!'),
tablet: (context, userName) => Text('Hello $userName on tablet!'),
desktop: (context, userName) => Text('Hello $userName on desktop!'),
)
Common Pre-builder Patterns
1. Loading States:
ResponsiveWrapper(
preBuilder: (context, child) => FutureBuilder<Data>(
future: dataService.fetchData(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return Center(child: CircularProgressIndicator());
}
if (snapshot.hasError) {
return Center(child: Text('Error: ${snapshot.error}'));
}
return child;
},
),
builder: (context, screenInfo) => DataWidget(data: snapshot.data),
)
2. Authentication Wrappers:
ResponsiveWrapper(
preBuilder: (context, child) => Consumer<AuthProvider>(
builder: (context, auth, child) {
if (!auth.isAuthenticated) {
return LoginScreen();
}
return child;
},
),
builder: (context, screenInfo) => AuthenticatedContent(),
)
3. Error Boundaries:
ResponsiveWrapper(
preBuilder: (context, child) => ErrorBoundary(
onError: (error, stackTrace) => ErrorScreen(error: error),
child: child,
),
builder: (context, screenInfo) => RiskyWidget(),
)
4. Analytics and Tracking:
ResponsiveWrapper(
preBuilder: (context, child) => AnalyticsWrapper(
screenName: 'responsive_screen',
properties: {
'device_type': screenInfo.deviceType.name,
'orientation': screenInfo.orientation.name,
},
child: child,
),
builder: (context, screenInfo) => TrackedContent(),
)
Understanding Pre-builders #
Pre-builders are a powerful feature that allows you to wrap your responsive content with additional functionality. They are executed before the main responsive builder and provide a way to inject state, context, or styling into your responsive layouts.
How Pre-builders Work #
- Execution Order: Pre-builder runs first, then the main responsive builder
- Child Parameter: The pre-builder receives the responsive widget as a
childparameter - Flexibility: You can conditionally render, wrap, or transform the child widget
- Parameterized Pre-builders: For
ResponsiveWrapperWithandResponsiveLayoutWith, pre-builders receive achildBuilderfunction that can be called with different parameters
When to Use Pre-builders #
- State Management: Wrap responsive content with BLoC, Provider, or other state management solutions
- Loading States: Show loading indicators while data is being fetched
- Authentication: Check user authentication before showing content
- Theming: Apply consistent styling or themes across responsive layouts
- Error Handling: Implement error boundaries or fallback UI
- Analytics: Track screen views and user interactions
- Data Fetching: Load data that multiple responsive layouts need
Pre-builder vs Regular Builder #
| Aspect | Pre-builder | Regular Builder |
|---|---|---|
| Purpose | Wrap/enhance responsive content | Build responsive content |
| Execution | Runs first | Runs after pre-builder |
| Access to | Context only | Context + ScreenInfo |
| Use Case | State, theming, loading | Device-specific layouts |
| Child | Receives built widget | Builds the widget |
API Reference #
Core Classes #
ResponsiveWrapper: Main responsive wrapper widgetResponsiveWrapperWith<T>: Parameterized responsive wrapperResponsiveLayout: Device-specific layout wrapperResponsiveLayoutWith<T>: Parameterized layout wrapperResponsiveOrientationLayout: Orientation-aware layout wrapperResponsiveOrientationLayoutWith<T>: Parameterized orientation layout wrapper
Utility Classes #
ResponsiveBreakpoints: Breakpoint configurationScreenInfo: Screen information data classResponsiveValue<T>: Responsive value utilityResponsiveOrientationValue<T>: Orientation-aware value utilityDeviceType: Device type enumeration
Builder Types #
ResponsiveBuilder: Basic responsive builder functionResponsivePreBuilder: Pre-builder wrapper functionResponsiveLayoutBuilder: Layout builder functionResponsiveBuilderWith<T>: Parameterized builder functionResponsivePreBuilderWith<T>: Parameterized pre-builder functionResponsiveOrientationLayoutBuilder: Orientation layout builder function
Real-World Examples #
Complete App with Pre-builders #
Here's a comprehensive example showing how to build a responsive app with pre-builders:
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: ResponsiveLayoutWith<UserData>(
preBuilder: (context, childBuilder) {
return BlocBuilder<AuthCubit, AuthState>(
builder: (context, authState) {
if (authState.isLoading) {
return LoadingScreen();
}
if (!authState.isAuthenticated) {
return LoginScreen();
}
// User is authenticated, get user data
return FutureBuilder<UserData>(
future: UserService.getUserData(authState.userId),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return LoadingScreen();
}
if (snapshot.hasError) {
return ErrorScreen(error: snapshot.error);
}
// Pass user data to responsive layouts
return childBuilder(snapshot.data!);
},
);
},
);
},
phone: (context, userData) => PhoneDashboard(userData: userData),
tablet: (context, userData) => TabletDashboard(userData: userData),
desktop: (context, userData) => DesktopDashboard(userData: userData),
),
);
}
}
E-commerce Product Page #
class ProductPage extends StatelessWidget {
final String productId;
@override
Widget build(BuildContext context) {
return ResponsiveWrapper(
preBuilder: (context, child) => BlocBuilder<ProductCubit, ProductState>(
builder: (context, state) {
if (state.isLoading) {
return Center(child: CircularProgressIndicator());
}
if (state.hasError) {
return ErrorWidget(state.error);
}
return child;
},
),
builder: (context, screenInfo) {
return screenInfo.isPhone
? PhoneProductLayout(productId: productId)
: screenInfo.isTablet
? TabletProductLayout(productId: productId)
: DesktopProductLayout(productId: productId);
},
);
}
}
Settings Screen with Theme Management #
class SettingsScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ResponsiveWrapper(
preBuilder: (context, child) => Consumer<ThemeProvider>(
builder: (context, themeProvider, child) {
return Theme(
data: themeProvider.currentTheme,
child: Container(
decoration: BoxDecoration(
gradient: themeProvider.isDarkMode
? LinearGradient(colors: [Colors.grey[900]!, Colors.grey[800]!])
: LinearGradient(colors: [Colors.blue[50]!, Colors.white]),
),
child: child,
),
);
},
),
builder: (context, screenInfo) {
return screenInfo.isPhone
? PhoneSettingsLayout()
: TabletSettingsLayout();
},
);
}
}
Contributing #
Contributions are welcome! Please feel free to submit a Pull Request.
License #
This project is licensed under the MIT License - see the LICENSE file for details.