ResponsiveKit Flutter 📱💻
A powerful and type-safe Flutter package for building responsive UIs that adapt seamlessly across different device types and screen sizes.
Overview
ResponsiveKit Flutter provides a comprehensive solution for creating responsive applications with:
- Type-safe device detection using sealed classes and pattern matching
- Customizable breakpoints for different device categories
- Declarative widgets for responsive layouts and visibility
- Inherited widget architecture for efficient context propagation
- Zero dependencies beyond Flutter SDK
Features
✨ Device Type Detection
- Mobile, Small/Medium/Large Tablet, Desktop, and Watch support
- Smart device categorization based on screen dimensions and aspect ratios
- Type-safe pattern matching with sealed classes
🎯 Responsive Widgets
ResponsiveBuilder- Build different layouts for different devicesResponsiveVisibility- Show/hide widgets based on device typeResponsiveKit- Inherited widget for configuration and data access
🔧 Customizable Breakpoints
- Default Material Design inspired breakpoints
- Easy customization for your specific needs
- Watch device detection with aspect ratio analysis
📦 Developer Experience
- Comprehensive type safety with sealed classes
- Pattern matching for clean, readable code
- Rich debugging information with diagnostics
Installation
Add this to your pubspec.yaml:
dependencies:
responsive_kit_flutter: ^0.0.1
Then run:
flutter pub get
Quick Start
1. Wrap your Widget with ResponsiveKit
NOTEYou can still callResponsiveKit.of(context)even if you don't wrap your widget tree withResponsiveKit. When no ancestorResponsiveKitis present, the API will provide sensible default breakpoints and device-type values. Wrap withResponsiveKitonly when you need custom breakpoints or configuration.
class MyWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ResponsiveKit(
data: ResponsiveBreakpoints(
mobileMaxWidth: 600, // Default: 600
smallTabletMaxWidth: 768, // Default: 768
mediumTabletMaxWidth: 1024, // Default: 1024
largeTabletMaxWidth: 1366, // Default: 1366
watchMaxWidth: 300, // Default: 300
watchMaxHeight: 300, // Default: 300
),
child: Widget(),
);
}
}
2. Build responsive layouts
class MyHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: ResponsiveBuilder(
mobile: (context) => _buildMobileLayout(),
tablet: (context) => _buildTabletLayout(),
desktop: (context) => _buildDesktopLayout(),
fallback: (context) => _buildMobileLayout(), // Default fallback
),
);
}
Widget _buildMobileLayout() {
return Column(
children: [
_buildHeader(),
Expanded(child: _buildContent()),
],
);
}
Widget _buildTabletLayout() {
return Row(
children: [
SizedBox(width: 300, child: _buildSidebar()),
Expanded(child: _buildContent()),
],
);
}
Widget _buildDesktopLayout() {
return Row(
children: [
SizedBox(width: 250, child: _buildSidebar()),
Expanded(child: _buildContent()),
SizedBox(width: 300, child: _buildRightPanel()),
],
);
}
}
3. Control widget visibility
class AdaptiveNavigation extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Column(
children: [
// Show hamburger menu only on mobile
ResponsiveVisibility.mobile(
builder: (context) => IconButton(
icon: Icon(Icons.menu),
onPressed: () => _openDrawer(),
),
),
// Show navigation tabs on tablets and larger
ResponsiveVisibility(
showOnMobile: false,
builder: (context) => _buildNavigationTabs(),
),
// Show breadcrumbs only on desktop
ResponsiveVisibility.desktop(
builder: (context) => _buildBreadcrumbs(),
),
],
);
}
}
Advanced Usage
Pattern Matching with Device Types
class AdaptiveContent extends StatelessWidget {
@override
Widget build(BuildContext context) {
final deviceType = ResponsiveKit.deviceTypeOf(context);
return deviceType.when(
mobile: () => _buildSingleColumn(),
smallTablet: () => _buildTwoColumns(),
mediumTablet: () => _buildTwoColumns(),
largeTablet: () => _buildThreeColumns(),
desktop: () => _buildFourColumns(),
watch: () => _buildMinimal(),
);
}
}
Accessing Responsive Data
class ResponsiveText extends StatelessWidget {
@override
Widget build(BuildContext context) {
final responsive = ResponsiveKit.of(context);
return Text(
'Hello World',
style: TextStyle(
fontSize: responsive.deviceType.isMobile ? 16 : 20,
fontWeight: responsive.deviceType.isDesktop
? FontWeight.bold
: FontWeight.normal,
),
);
}
}
Custom Breakpoints
class CustomResponsiveApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ResponsiveKit(
data: const ResponsiveBreakpoints(
mobileMaxWidth: 480, // Smaller mobile breakpoint
smallTabletMaxWidth: 600, // Custom small tablet range
mediumTabletMaxWidth: 900, // Custom medium tablet range
largeTabletMaxWidth: 1200, // Custom large tablet range
watchMaxWidth: 250, // Smaller watch screens
watchMaxHeight: 300,
),
child: MaterialApp(/* ... */),
);
}
}
Device Categories and Properties
class AdaptiveFeatures extends StatelessWidget {
@override
Widget build(BuildContext context) {
final deviceType = ResponsiveKit.deviceTypeOf(context);
return Column(
children: [
if (deviceType.isTablet)
_buildTabletSpecificFeature(),
if (deviceType.isTabletOrLarger)
_buildLargeScreenFeature(),
if (deviceType.isHandheld)
_buildTouchOptimizedControls(),
if (deviceType.supportsHover)
_buildHoverEffects(),
if (deviceType.hasLimitedSpace)
_buildCompactLayout(),
],
);
}
}
Device Type Categories
| Device Type | Screen Width Range | Characteristics |
|---|---|---|
| Watch | ≤ 300px (square aspect ratio) | Minimal UI, essential info only |
| Mobile | ≤ 600px | Single column, touch-first |
| Small Tablet | 601px - 768px | Two columns possible |
| Medium Tablet | 769px - 1024px | Multi-column layouts |
| Large Tablet | 1025px - 1366px | Desktop-like features |
| Desktop | > 1366px | Full feature set, hover support |
Device Properties
Each device type provides boolean properties for easy categorization:
final deviceType = ResponsiveKit.deviceTypeOf(context);
// Direct type checks
deviceType.isMobile // true for Mobile devices
deviceType.isSmallTablet // true for SmallTablet devices
deviceType.isDesktop // true for Desktop devices
// Category checks
deviceType.isTablet // true for any tablet size
deviceType.isTabletOrLarger // true for tablets and desktop
deviceType.isMobileOrTablet // true for mobile and tablets
deviceType.isHandheld // true for mobile, tablets, and watch
deviceType.isLargeScreen // true for large tablets and desktop
// Capability checks
deviceType.hasLimitedSpace // true for mobile and watch
deviceType.supportsHover // true for desktop
deviceType.prefersTouchInput // true for mobile, tablets, and watch
Best Practices
1. Design Mobile-First
Start with mobile layouts and progressively enhance for larger screens.
ResponsiveBuilder(
mobile: (context) => _mobileLayout(),
tablet: (context) => _enhancedTabletLayout(),
desktop: (context) => _fullFeaturedDesktopLayout(),
)
2. Use Semantic Breakpoints
Choose breakpoints based on your content, not specific devices.
3. Optimize Performance
ResponsiveKit uses InheritedWidget for efficient rebuilds.
4. Test Across Devices
Use Flutter's device preview or responsive design mode to test your layouts.
5. Consider Accessibility
Ensure touch targets are appropriately sized for different devices.
API Reference
ResponsiveKit
The main inherited widget that provides responsive data to descendants.
ResponsiveKit(
data: ResponsiveBreakpoints(), // Optional custom breakpoints
child: Widget, // Your app widget tree
)
ResponsiveBuilder
Builds different widgets based on device type.
ResponsiveBuilder(
mobile: (context) => Widget, // Mobile-specific widget
smallTablet: (context) => Widget, // Small tablet widget
mediumTablet: (context) => Widget, // Medium tablet widget
largeTablet: (context) => Widget, // Large tablet widget
tablet: (context) => Widget, // Fallback for all tablets
desktop: (context) => Widget, // Desktop widget
watch: (context) => Widget, // Watch widget
fallback: (context) => Widget, // Default fallback
)
ResponsiveVisibility
Controls widget visibility based on device type.
ResponsiveVisibility(
showOnMobile: bool, // Show on mobile (default: true)
showOnSmallTablet: bool, // Show on small tablet (default: true)
showOnMediumTablet: bool, // Show on medium tablet (default: true)
showOnLargeTablet: bool, // Show on large tablet (default: true)
showOnDesktop: bool, // Show on desktop (default: true)
showOnWatch: bool, // Show on watch (default: true)
builder: (context) => Widget, // Widget to show
replacementBuilder: (context) => Widget, // Widget when hidden
)
License
This project is licensed under the MIT License - see the LICENSE file for details.
Changelog
See CHANGELOG.md for a detailed list of changes and version history.
Made with ❤️ for the Flutter community