adaptive_flex_layout 1.0.1
adaptive_flex_layout: ^1.0.1 copied to clipboard
A lightweight, responsive flex grid layout system for Flutter inspired by Bootstrap. Supports customizable breakpoints, offset columns, and responsive values.
example/lib/main.dart
import 'package:adaptive_flex_layout/adaptive_flex_layout.dart';
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Adaptive Flex Layout Demo',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.indigo),
useMaterial3: true,
),
home: const DashboardPage(),
);
}
}
class DashboardPage extends StatelessWidget {
const DashboardPage({super.key});
@override
Widget build(BuildContext context) {
// Resolve dynamic responsive padding and font sizing
final EdgeInsets padding = responsive<EdgeInsets>(
context,
defaultValue: const EdgeInsets.all(12.0),
md: const EdgeInsets.all(20.0),
lg: const EdgeInsets.all(32.0),
);
final double titleFontSize = responsive<double>(
context,
defaultValue: 20.0,
md: 28.0,
xl: 36.0,
);
return Scaffold(
appBar: AppBar(
title: const Text('Adaptive Grid Dashboard'),
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
),
body: SafeArea(
child: SingleChildScrollView(
child: AdaptiveFlexGrid(
padding: padding,
child: AdaptiveFlexRow(
gutter: 16.0,
verticalGutter: 16.0,
children: [
// Title Banner Card (Always 12/12 columns - full width)
AdaptiveFlexCol(
xs: 12,
child: Card(
color: Theme.of(context).colorScheme.primaryContainer,
child: Padding(
padding: const EdgeInsets.all(24.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Welcome to the Grid!',
style: TextStyle(
fontSize: titleFontSize,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 8.0),
Text(
'Current Breakpoint: ${context.flexBreakpoint.name.toUpperCase()}',
style: Theme.of(context).textTheme.titleMedium,
),
const SizedBox(height: 4.0),
Text(
'Width: ${context.screenWidth.toStringAsFixed(1)}px',
style: Theme.of(context).textTheme.bodyMedium,
),
],
),
),
),
),
// Responsive Cards that wrap (xs: 12, md: 6, lg: 3)
// Stacks vertically on mobile (12 cols), 2-per-row on tablet (6 cols), 4-per-row on desktop (3 cols)
for (int i = 1; i <= 4; i++)
AdaptiveFlexCol(
xs: 12,
md: 6,
lg: 3,
child: _InfoCard(
title: 'Metric $i',
value: '${i * 25}%',
icon: Icons.analytics,
color: Colors.blueAccent.shade100,
),
),
// Main Content area (xs: 12, lg: 8)
AdaptiveFlexCol(
xs: 12,
lg: 8,
child: Card(
child: Padding(
padding: const EdgeInsets.all(20.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Main Content Section',
style: Theme.of(context).textTheme.titleLarge,
),
const SizedBox(height: 12.0),
const Text(
'On mobile (XS/SM) and tablet (MD), this card takes the full row width (12/12 columns). '
'On desktop displays (LG and up), it wraps down to occupy 8 out of 12 columns, '
'allowing the sidebar widget to sit adjacent to it.',
),
const SizedBox(height: 12.0),
Container(
height: 120.0,
color: Colors.grey.shade100,
child: const Center(
child: Text('Interactive Graph / Chart Mock'),
),
),
],
),
),
),
),
// Sidebar Area (xs: 12, lg: 4)
AdaptiveFlexCol(
xs: 12,
lg: 4,
child: Card(
child: Padding(
padding: const EdgeInsets.all(20.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Sidebar Widgets',
style: Theme.of(context).textTheme.titleLarge,
),
const SizedBox(height: 12.0),
const ListTile(
leading: Icon(Icons.notifications),
title: Text('New Alert'),
subtitle: Text('2 minutes ago'),
),
const Divider(),
const ListTile(
leading: Icon(Icons.update),
title: Text('System Update'),
subtitle: Text('1 hour ago'),
),
],
),
),
),
),
// Demo of column offsets (xs: 12, md: 6 with offset 3)
// On mobile it takes full width. On tablet/desktop it takes 6 columns and centers itself via a 3-column offset.
AdaptiveFlexCol(
xs: 12,
md: 6,
offsetMd: 3,
child: Card(
color: Colors.amber.shade50,
child: const Padding(
padding: EdgeInsets.all(20.0),
child: Center(
child: Text(
'Centered column on tablet/desktop via offset',
textAlign: TextAlign.center,
style: TextStyle(fontWeight: FontWeight.w500),
),
),
),
),
),
// Demo of span: 0 (Hidden on mobile, shown on tablet/desktop)
AdaptiveFlexCol(
xs: 0,
md: 12,
child: Card(
color: Colors.red.shade50,
child: const Padding(
padding: EdgeInsets.all(16.0),
child: Center(
child: Text(
'📢 Hidden on mobile (< 768px), visible on tablet & desktop',
style: TextStyle(
color: Colors.red,
fontWeight: FontWeight.bold,
),
),
),
),
),
),
],
),
),
),
),
);
}
}
class _InfoCard extends StatelessWidget {
const _InfoCard({
required this.title,
required this.value,
required this.icon,
required this.color,
});
final String title;
final String value;
final IconData icon;
final Color color;
@override
Widget build(BuildContext context) {
return Card(
color: color,
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 20.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
title,
style: const TextStyle(
fontSize: 14.0,
fontWeight: FontWeight.w500,
),
),
const SizedBox(height: 6.0),
Text(
value,
style: const TextStyle(
fontSize: 24.0,
fontWeight: FontWeight.bold,
),
),
],
),
Icon(icon, size: 36.0, color: Colors.black54),
],
),
),
);
}
}