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.
import 'package:flutter/material.dart';
import 'package:responsive_wrapper/responsive_wrapper.dart';
void main() {
runApp(const ResponsiveWrapperExampleApp());
}
/// A comprehensive example app demonstrating all features of the responsive_wrapper package.
class ResponsiveWrapperExampleApp extends StatelessWidget {
const ResponsiveWrapperExampleApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Responsive Wrapper Examples',
theme: ThemeData(primarySwatch: Colors.blue, useMaterial3: true),
home: const ResponsiveWrapperExampleHome(),
);
}
}
/// The main example page that demonstrates different responsive wrapper features.
class ResponsiveWrapperExampleHome extends StatefulWidget {
const ResponsiveWrapperExampleHome({super.key});
@override
State<ResponsiveWrapperExampleHome> createState() =>
_ResponsiveWrapperExampleHomeState();
}
class _ResponsiveWrapperExampleHomeState
extends State<ResponsiveWrapperExampleHome> {
int _selectedExample = 0;
String _userName = 'John Doe';
int _counter = 0;
final List<String> _examples = [
'Basic ResponsiveWrapper',
'ResponsiveWrapper with PreBuilder',
'ResponsiveWrapperWith (Parameterized)',
'ResponsiveLayout',
'ResponsiveLayoutWith (Parameterized)',
'ResponsiveOrientationLayout',
'ResponsiveOrientationLayoutWith (Parameterized)',
'ResponsiveOrientationValue',
'Custom Breakpoints',
'Orientation Handling',
];
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Responsive Wrapper Examples'),
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
),
body: Column(
children: [
// Example selector
Container(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'Select Example:',
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
),
const SizedBox(height: 8),
DropdownButton<int>(
value: _selectedExample,
isExpanded: true,
items: _examples.asMap().entries.map((entry) {
return DropdownMenuItem<int>(
value: entry.key,
child: Text(entry.value),
);
}).toList(),
onChanged: (value) {
setState(() {
_selectedExample = value!;
});
},
),
],
),
),
// Example content
Expanded(child: _buildExampleContent()),
],
),
);
}
Widget _buildExampleContent() {
switch (_selectedExample) {
case 0:
return _buildBasicResponsiveWrapper();
case 1:
return _buildResponsiveWrapperWithPreBuilder();
case 2:
return _buildResponsiveWrapperWith();
case 3:
return _buildResponsiveLayout();
case 4:
return _buildResponsiveLayoutWith();
case 5:
return _buildResponsiveOrientationLayout();
case 6:
return _buildResponsiveOrientationLayoutWith();
case 7:
return _buildResponsiveOrientationValue();
case 8:
return _buildCustomBreakpoints();
case 9:
return _buildOrientationHandling();
default:
return const Center(child: Text('Select an example'));
}
}
/// Example 1: Basic ResponsiveWrapper
Widget _buildBasicResponsiveWrapper() {
return ResponsiveWrapper(
builder: (context, screenInfo) {
return Container(
padding: EdgeInsets.all(screenInfo.isPhone ? 16.0 : 24.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
screenInfo.isPhone
? Icons.phone_android
: screenInfo.isTablet
? Icons.tablet
: Icons.desktop_windows,
size: screenInfo.isPhone ? 48.0 : 64.0,
color: screenInfo.isPhone
? Colors.blue
: screenInfo.isTablet
? Colors.green
: Colors.orange,
),
const SizedBox(height: 16),
Text(
'Device Type: ${screenInfo.deviceType.name}',
style: TextStyle(
fontSize: screenInfo.isPhone ? 18.0 : 24.0,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 8),
Text(
'Screen Size: ${screenInfo.width.toInt()} x ${screenInfo.height.toInt()}',
style: TextStyle(fontSize: screenInfo.isPhone ? 14.0 : 16.0),
),
const SizedBox(height: 8),
Text(
'Orientation: ${screenInfo.orientation.name}',
style: TextStyle(fontSize: screenInfo.isPhone ? 14.0 : 16.0),
),
],
),
);
},
);
}
/// Example 2: ResponsiveWrapper with PreBuilder
Widget _buildResponsiveWrapperWithPreBuilder() {
return 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 Container(
padding: EdgeInsets.all(screenInfo.isPhone ? 16.0 : 24.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'With PreBuilder',
style: TextStyle(
fontSize: screenInfo.isPhone ? 20.0 : 28.0,
fontWeight: FontWeight.bold,
color: Colors.blue.shade800,
),
),
const SizedBox(height: 16),
Text(
'This example shows how to wrap responsive content with additional widgets.',
textAlign: TextAlign.center,
style: TextStyle(fontSize: screenInfo.isPhone ? 14.0 : 16.0),
),
],
),
);
},
);
}
/// Example 3: ResponsiveWrapperWith (Parameterized)
Widget _buildResponsiveWrapperWith() {
return ResponsiveWrapperWith<String>(
initialParam: _userName,
builder: (context, screenInfo, userName) {
return Container(
padding: EdgeInsets.all(screenInfo.isPhone ? 16.0 : 24.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'Hello, $userName!',
style: TextStyle(
fontSize: screenInfo.isPhone ? 20.0 : 28.0,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 16),
Text(
'This is a parameterized responsive wrapper.',
textAlign: TextAlign.center,
style: TextStyle(fontSize: screenInfo.isPhone ? 14.0 : 16.0),
),
const SizedBox(height: 16),
ElevatedButton(
onPressed: () {
setState(() {
_userName = _userName == 'John Doe'
? 'Jane Smith'
: 'John Doe';
});
},
child: const Text('Change Name'),
),
],
),
);
},
);
}
/// Example 4: ResponsiveLayout
Widget _buildResponsiveLayout() {
return ResponsiveLayout(
phone: (context) => _buildPhoneLayout(),
tablet: (context) => _buildTabletLayout(),
desktop: (context) => _buildDesktopLayout(),
);
}
/// Example 5: ResponsiveLayoutWith (Parameterized)
Widget _buildResponsiveLayoutWith() {
return ResponsiveLayoutWith<int>(
initialParam: _counter,
phone: (context, counter) => _buildPhoneLayoutWithCounter(counter),
tablet: (context, counter) => _buildTabletLayoutWithCounter(counter),
desktop: (context, counter) => _buildDesktopLayoutWithCounter(counter),
);
}
/// Example 6: ResponsiveOrientationLayout
Widget _buildResponsiveOrientationLayout() {
return ResponsiveOrientationLayout(
phonePortrait: (context) => _buildPhonePortraitLayout(),
phoneLandscape: (context) => _buildPhoneLandscapeLayout(),
tabletPortrait: (context) => _buildTabletPortraitLayout(),
tabletLandscape: (context) => _buildTabletLandscapeLayout(),
desktop: (context) => _buildDesktopLayout(),
);
}
/// Example 7: ResponsiveOrientationLayoutWith (Parameterized)
Widget _buildResponsiveOrientationLayoutWith() {
return ResponsiveOrientationLayoutWith<String>(
initialParam: _userName,
phonePortrait: (context, userName) =>
_buildPhonePortraitLayoutWithUser(userName),
phoneLandscape: (context, userName) =>
_buildPhoneLandscapeLayoutWithUser(userName),
tabletPortrait: (context, userName) =>
_buildTabletPortraitLayoutWithUser(userName),
tabletLandscape: (context, userName) =>
_buildTabletLandscapeLayoutWithUser(userName),
desktop: (context, userName) => _buildDesktopLayoutWithUser(userName),
);
}
/// Example 8: ResponsiveOrientationValue
Widget _buildResponsiveOrientationValue() {
return ResponsiveWrapper(
builder: (context, screenInfo) {
final fontSize = ResponsiveOrientationValue<double>(
phonePortrait: 16.0,
phoneLandscape: 14.0,
tabletPortrait: 20.0,
tabletLandscape: 18.0,
desktop: 24.0,
).getValue(context);
final padding = ResponsiveOrientationValue<EdgeInsets>(
phonePortrait: const EdgeInsets.all(16.0),
phoneLandscape: const EdgeInsets.symmetric(
horizontal: 24.0,
vertical: 12.0,
),
tabletPortrait: const EdgeInsets.all(24.0),
tabletLandscape: const EdgeInsets.all(20.0),
desktop: const EdgeInsets.all(32.0),
).getValue(context);
return Container(
padding: padding,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'Responsive Values',
style: TextStyle(
fontSize: fontSize,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 16),
Text(
'Font Size: ${fontSize.toInt()}px',
style: TextStyle(fontSize: fontSize * 0.8),
),
const SizedBox(height: 8),
Text(
'Padding: ${padding.left.toInt()}px',
style: TextStyle(fontSize: fontSize * 0.8),
),
],
),
);
},
);
}
/// Example 9: Custom Breakpoints
Widget _buildCustomBreakpoints() {
return ResponsiveWrapper(
breakpoints: const ResponsiveBreakpoints(
phone: 480, // Custom phone breakpoint
tablet: 800, // Custom tablet breakpoint
),
builder: (context, screenInfo) {
return Container(
padding: const EdgeInsets.all(16),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'Custom Breakpoints',
style: TextStyle(
fontSize: screenInfo.isPhone ? 18.0 : 24.0,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 16),
Text(
'Phone: < 480px\nTablet: 480px - 800px\nDesktop: > 800px',
textAlign: TextAlign.center,
style: TextStyle(fontSize: screenInfo.isPhone ? 14.0 : 16.0),
),
const SizedBox(height: 16),
Text(
'Current: ${screenInfo.deviceType.name} (${screenInfo.width.toInt()}px)',
style: TextStyle(
fontSize: screenInfo.isPhone ? 14.0 : 16.0,
color: Colors.blue,
),
),
],
),
);
},
);
}
/// Example 10: Orientation Handling
Widget _buildOrientationHandling() {
return ResponsiveWrapper(
treatLandscapePhoneAsTablet: true,
treatPortraitTabletAsPhone: true,
builder: (context, screenInfo) {
return Container(
padding: const EdgeInsets.all(16),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'Orientation Handling',
style: TextStyle(
fontSize: screenInfo.isPhone ? 18.0 : 24.0,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 16),
Text(
'Landscape phones treated as tablets\nPortrait tablets treated as phones',
textAlign: TextAlign.center,
style: TextStyle(fontSize: screenInfo.isPhone ? 14.0 : 16.0),
),
const SizedBox(height: 16),
Text(
'Device Type: ${screenInfo.deviceType.name}',
style: TextStyle(
fontSize: screenInfo.isPhone ? 14.0 : 16.0,
color: Colors.green,
),
),
const SizedBox(height: 8),
Text(
'Orientation: ${screenInfo.orientation.name}',
style: TextStyle(
fontSize: screenInfo.isPhone ? 14.0 : 16.0,
color: Colors.blue,
),
),
],
),
);
},
);
}
// Layout builders for different device types
Widget _buildPhoneLayout() {
return Container(
padding: const EdgeInsets.all(16),
child: const Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.phone_android, size: 48, color: Colors.blue),
SizedBox(height: 16),
Text(
'Phone Layout',
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
),
SizedBox(height: 8),
Text('Optimized for small screens'),
],
),
);
}
Widget _buildTabletLayout() {
return Container(
padding: const EdgeInsets.all(24),
child: const Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.tablet, size: 64, color: Colors.green),
SizedBox(height: 16),
Text(
'Tablet Layout',
style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
),
SizedBox(height: 8),
Text('Optimized for medium screens'),
],
),
);
}
Widget _buildDesktopLayout() {
return Container(
padding: const EdgeInsets.all(32),
child: const Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.desktop_windows, size: 80, color: Colors.orange),
SizedBox(height: 16),
Text(
'Desktop Layout',
style: TextStyle(fontSize: 28, fontWeight: FontWeight.bold),
),
SizedBox(height: 8),
Text('Optimized for large screens'),
],
),
);
}
// Layout builders with counter parameter
Widget _buildPhoneLayoutWithCounter(int counter) {
return Container(
padding: const EdgeInsets.all(16),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Icon(Icons.phone_android, size: 48, color: Colors.blue),
const SizedBox(height: 16),
const Text(
'Phone Layout',
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
),
const SizedBox(height: 8),
Text('Counter: $counter'),
const SizedBox(height: 16),
ElevatedButton(
onPressed: () => setState(() => _counter++),
child: const Text('Increment'),
),
],
),
);
}
Widget _buildTabletLayoutWithCounter(int counter) {
return Container(
padding: const EdgeInsets.all(24),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Icon(Icons.tablet, size: 64, color: Colors.green),
const SizedBox(height: 16),
const Text(
'Tablet Layout',
style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
),
const SizedBox(height: 8),
Text('Counter: $counter'),
const SizedBox(height: 16),
ElevatedButton(
onPressed: () => setState(() => _counter++),
child: const Text('Increment'),
),
],
),
);
}
Widget _buildDesktopLayoutWithCounter(int counter) {
return Container(
padding: const EdgeInsets.all(32),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Icon(Icons.desktop_windows, size: 80, color: Colors.orange),
const SizedBox(height: 16),
const Text(
'Desktop Layout',
style: TextStyle(fontSize: 28, fontWeight: FontWeight.bold),
),
const SizedBox(height: 8),
Text('Counter: $counter'),
const SizedBox(height: 16),
ElevatedButton(
onPressed: () => setState(() => _counter++),
child: const Text('Increment'),
),
],
),
);
}
// Orientation-specific layout builders
Widget _buildPhonePortraitLayout() {
return Container(
padding: const EdgeInsets.all(16),
child: const Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.phone_android, size: 48, color: Colors.blue),
SizedBox(height: 16),
Text(
'Phone Portrait',
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
),
SizedBox(height: 8),
Text('Vertical layout for phones'),
],
),
);
}
Widget _buildPhoneLandscapeLayout() {
return Container(
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 12),
child: const Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.phone_android, size: 48, color: Colors.blue),
SizedBox(width: 16),
Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Phone Landscape',
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
),
SizedBox(height: 4),
Text('Horizontal layout for phones'),
],
),
],
),
);
}
Widget _buildTabletPortraitLayout() {
return Container(
padding: const EdgeInsets.all(24),
child: const Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.tablet, size: 64, color: Colors.green),
SizedBox(height: 16),
Text(
'Tablet Portrait',
style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
),
SizedBox(height: 8),
Text('Vertical layout for tablets'),
],
),
);
}
Widget _buildTabletLandscapeLayout() {
return Container(
padding: const EdgeInsets.all(20),
child: const Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.tablet, size: 64, color: Colors.green),
SizedBox(width: 20),
Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Tablet Landscape',
style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
),
SizedBox(height: 8),
Text('Horizontal layout for tablets'),
],
),
],
),
);
}
// Orientation-specific layout builders with user parameter
Widget _buildPhonePortraitLayoutWithUser(String userName) {
return Container(
padding: const EdgeInsets.all(16),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Icon(Icons.phone_android, size: 48, color: Colors.blue),
const SizedBox(height: 16),
Text(
'Hello $userName!',
style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
),
const SizedBox(height: 8),
const Text('Phone Portrait Layout'),
],
),
);
}
Widget _buildPhoneLandscapeLayoutWithUser(String userName) {
return Container(
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 12),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Icon(Icons.phone_android, size: 48, color: Colors.blue),
const SizedBox(width: 16),
Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Hello $userName!',
style: const TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 4),
const Text('Phone Landscape Layout'),
],
),
],
),
);
}
Widget _buildTabletPortraitLayoutWithUser(String userName) {
return Container(
padding: const EdgeInsets.all(24),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Icon(Icons.tablet, size: 64, color: Colors.green),
const SizedBox(height: 16),
Text(
'Hello $userName!',
style: const TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
),
const SizedBox(height: 8),
const Text('Tablet Portrait Layout'),
],
),
);
}
Widget _buildTabletLandscapeLayoutWithUser(String userName) {
return Container(
padding: const EdgeInsets.all(20),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Icon(Icons.tablet, size: 64, color: Colors.green),
const SizedBox(width: 20),
Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Hello $userName!',
style: const TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 8),
const Text('Tablet Landscape Layout'),
],
),
],
),
);
}
Widget _buildDesktopLayoutWithUser(String userName) {
return Container(
padding: const EdgeInsets.all(32),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Icon(Icons.desktop_windows, size: 80, color: Colors.orange),
const SizedBox(height: 16),
Text(
'Hello $userName!',
style: const TextStyle(fontSize: 28, fontWeight: FontWeight.bold),
),
const SizedBox(height: 8),
const Text('Desktop Layout'),
],
),
);
}
}