responsive_metrics 0.0.3
responsive_metrics: ^0.0.3 copied to clipboard
A lightweight, dependency-free responsive design toolkit for Flutter — pixel scaling, breakpoint checks, and per-device values.
responsive_metrics #
A lightweight, dependency-free responsive design toolkit for Flutter.
No context needed for pixel scaling, simple breakpoint checks for layout
decisions, and a small RV helper for values that genuinely differ per
device class.
Install #
dependencies:
responsive_metrics: ^0.0.3
Setup #
Initialize ScreenScaler once, inside your MaterialApp builder, so it
stays up to date across window resizes:
import 'package:responsive_metrics/responsive_metrics.dart';
MaterialApp(
builder: (context, child) {
ScreenScaler.instance.init(MediaQuery.sizeOf(context));
return child!;
},
home: const HomePage(),
);
Turning scaling off #
Some apps target known, fixed hardware (a POS app on a specific tablet,
say) and want zero proportional scaling — just fixed values plus RV/
pick() breakpoint-tier values. Pass scalingEnabled: false to make
.w .h .sp .r return raw, unscaled values everywhere, mobile
included:
ScreenScaler.instance.init(
MediaQuery.sizeOf(context),
scalingEnabled: false,
);
Or keep mobile scaling (where screen size varies the most) but turn it off just for tablet/desktop, where a fixed layout is usually the better fit:
ScreenScaler.instance.init(
MediaQuery.sizeOf(context),
scaleTablet: false,
scaleDesktop: false,
);
All three flags default to true — existing scaling behavior — so
nothing changes unless you opt out. They only need to be passed once
(e.g. alongside your other startup config); omit them on later
resize-triggered init() calls to keep whatever was configured.
Usage #
1. Pixel scaling — .w .h .sp .r #
Use these for any concrete pixel value. No BuildContext required.
| Extension | Use for |
|---|---|
.w |
width, horizontal padding, margin, icon size |
.h |
height, vertical padding, vertical spacing |
.sp |
fontSize only |
.r |
BorderRadius, circular radius |
SizedBox(width: 24.w, height: 16.h)
Padding(padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 8.h))
Icon(Icons.home, size: 24.w)
Text('Hello', style: TextStyle(fontSize: 16.sp))
BorderRadius.circular(12.r)
2. Breakpoint checks — context.isMobile / isTablet / isDesktop #
Use these for layout decisions, not pixel values.
if (context.isDesktop) const SideNavBar(),
if (context.isMobile) const BottomNavBar(),
Flex(
direction: context.isDesktop ? Axis.horizontal : Axis.vertical,
children: [...],
)
3. context.pick() — different values per device class #
GridView(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: context.pick(mobile: 2, tablet: 3, desktop: 4),
),
)
4. RV — reusable, per-device-class constants #
Use RV when a design value is genuinely different per breakpoint — not
just scaled. If it's just scaling, use .w/.sp/.r directly instead.
class AppFontSize {
static const headerTitle = 22.0; // scales normally, no RV needed
static const cancelHeaderTitle = RV(mobile: 22.0, tablet: 30.0);
}
Text(
'Cancel',
style: TextStyle(fontSize: AppFontSize.cancelHeaderTitle.sp(context)),
)
RV exposes .value(context), .w(context), .h(context), .r(context),
.sp(context), and .size(context).
A slightly larger example — a card whose padding is deliberately roomier on tablet/desktop, not just scaled up:
class AppSpacing {
static const cardPadding = RV(mobile: 12.0, tablet: 20.0, desktop: 28.0);
}
Container(
padding: EdgeInsets.all(AppSpacing.cardPadding.w(context)),
child: Text(
'Card title',
style: TextStyle(fontSize: AppFontSize.cardTitle.sp(context)),
),
)
See example/lib/main.dart (the "See RV example" button) for a full
runnable version of this.
Breakpoints #
Matches Material Design 3:
- Mobile → width < 600
- Tablet → width >= 600 && width < 1200
- Desktop → width >= 1200
Rule of thumb #
- Pixel size / spacing / font / radius →
.w.h.sp.r - Layout decision (show/hide, columns, direction) →
context.isX/context.pick() - A value that's genuinely different (not scaled) per breakpoint →
RV