The Responsive Challenge
Flutter's promise is "one codebase, every platform." But that doesn't mean one layout. A phone layout shoved onto a tablet looks terrible. Here's how I handle responsive design.
MediaQuery vs LayoutBuilder
MediaQuery gives you the full screen dimensions — useful for top-level layout decisions. LayoutBuilder gives you the available space for a specific widget — better for component-level responsiveness.
I use MediaQuery for deciding "phone vs tablet vs desktop" and LayoutBuilder for "how much space does this card have?"
The Breakpoint System
I define breakpoints as constants and use them consistently:
- Mobile: < 600px
- Tablet: 600px - 1024px
- Desktop: > 1024px
Adaptive Widgets Pattern
Create wrapper widgets that render different layouts based on screen size. For example, a ProductGrid might show 2 columns on mobile, 3 on tablet, and 4 on desktop.
Flexible Spacing
Never hardcode margins and padding. Use percentages or responsive scale factors that adapt to screen size. MediaQuery.of(context).size.width * 0.05 gives you 5% screen width padding.
Text Scaling
Account for system text scaling settings. Test your UI with both 0.8x and 1.5x text scale to ensure nothing breaks.
Platform-Specific Patterns
Use the platform to decide between Material and Cupertino widgets. Users expect platform-native interactions — a DatePicker should look like iOS on iOS and Material on Android.
Key Takeaway
Responsive design isn't an afterthought — it's a core architectural decision. Build it into your widget tree from day one, not as a retrofit.