fixed_responsive 1.0.2
fixed_responsive: ^1.0.2 copied to clipboard
A mobile-first scaling extension that calculates sizes based on the shortest screen side, preventing layout breaks on rotation while scaling perfectly for tablets.
import 'package:flutter/material.dart';
import 'package:fixed_responsive/fixed_responsive.dart';
void main() {
runApp(
const MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Fixed Responsive Example',
home: ShowcaseScreen(),
),
);
}
class ShowcaseScreen extends StatelessWidget {
const ShowcaseScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: const Color(0xFFF4F7FC),
appBar: AppBar(
backgroundColor: Colors.white,
elevation: 0,
title: Text(
'Package Dashboard',
style: TextStyle(
color: Colors.black87,
fontSize: 22.fsp, // Scales beautifully
fontWeight: FontWeight.bold,
),
),
),
body: SingleChildScrollView(
padding: EdgeInsets.all(20.fw), // Scales padding perfectly
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// 1. THE HERO CARD (Proves font and padding scale safely)
Container(
width: double.infinity,
padding: EdgeInsets.all(24.fw),
decoration: BoxDecoration(
gradient: const LinearGradient(
colors: [Color(0xFF3B82F6), Color(0xFF2563EB)],
begin: Alignment.topLeft,
end: Alignment.bottomRight,
),
borderRadius: BorderRadius.circular(20.fw),
boxShadow: [
BoxShadow(
color: Colors.blue.withValues(alpha: 0.3),
blurRadius: 15,
offset: Offset(0, 8.fw),
),
],
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Current Scale Multiplier',
style: TextStyle(
color: Colors.white70,
fontSize: 16.fsp,
fontWeight: FontWeight.w600,
),
),
SizedBox(height: 8.fw),
Text(
// Dynamically shows the user how the package is calculating!
'${1.fw.toStringAsFixed(2)}x',
style: TextStyle(
color: Colors.white,
fontSize: 40.fsp,
fontWeight: FontWeight.bold,
),
),
SizedBox(height: 8.fw),
Text(
'Rotate your phone. This number will not change. Open on a tablet, and it will increase!',
style: TextStyle(
color: Colors.white.withValues(alpha: 0.9),
fontSize: 14.fsp,
height: 1.4,
),
),
],
),
),
SizedBox(height: 30.fw),
Text(
'Live Statistics',
style: TextStyle(
fontSize: 18.fsp,
fontWeight: FontWeight.bold,
color: Colors.black87,
),
),
SizedBox(height: 16.fw),
// 2. BULLETPROOF WRAP LAYOUT (Never overflows)
Wrap(
spacing: 16.fw,
runSpacing: 16.fw,
children: [
_buildStatCard(
'Total Users',
'14.2k',
Icons.people_alt_rounded,
Colors.green,
),
_buildStatCard(
'Pub Points',
'160',
Icons.workspace_premium_rounded,
Colors.orange,
),
_buildStatCard(
'Crash Rate',
'0.0%',
Icons.health_and_safety_rounded,
Colors.purple,
),
],
),
],
),
),
);
}
// A fixed-width card that wraps cleanly
Widget _buildStatCard(
String title,
String value,
IconData icon,
MaterialColor color,
) {
return Container(
width: 160.fw, // Fixed width based on our package
padding: EdgeInsets.all(16.fw),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(20.fw),
boxShadow: [
BoxShadow(
color: Colors.black.withValues(alpha: 0.05),
blurRadius: 10,
offset: Offset(0, 4.fw),
),
],
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
padding: EdgeInsets.all(8.fw),
decoration: BoxDecoration(
color: color.shade50,
shape: BoxShape.circle,
),
child: Icon(icon, color: color.shade600, size: 24.fsp),
),
SizedBox(height: 16.fw),
Text(
value,
style: TextStyle(
fontSize: 24.fsp,
fontWeight: FontWeight.bold,
color: Colors.black87,
),
),
SizedBox(height: 4.fw),
Text(
title,
style: TextStyle(
fontSize: 13.fsp,
color: Colors.grey.shade600,
fontWeight: FontWeight.w500,
),
),
],
),
);
}
}