flutter_adaptive_grid_layout 0.0.1
flutter_adaptive_grid_layout: ^0.0.1 copied to clipboard
A Flutter package for declarative and flexible adaptive grid layouts for complex UIs.
Flutter Adaptive Grid Layout #
A Flutter package for building declarative, responsive, and adaptive grid layouts inspired by CSS Grid Layout. Simplify complex UI adaptation across different screen sizes with intuitive ASCII-art-like templates.
🌟 Features #
flutter_adaptive_grid_layout
aims to streamline the development of adaptive user interfaces by providing a powerful and declarative way to define your layouts.
- Declarative Templates: Define your grid structure using an intuitive ASCII-art-like string similar to CSS Grid's
grid-template-areas
. - Breakpoint-Based Adaptation: Easily define different layouts for
compact
,medium
,expanded
, andlarge
screen sizes, reacting toMediaQuery
changes. - Flexible & Fixed Sizing: Control row and column dimensions with
FlexSize.flex()
for proportional scaling orFlexSize.fixed()
for precise pixel sizes.FlexSize.content()
allows for content-driven sizing (though with currentStack
-based implementation, it behaves as flexible filler). - Named Regions: Assign meaningful names to grid areas and map your Flutter widgets directly to these regions.
- Simplified Responsive Design: Reduce complex conditional
build
logic, leading to cleaner and more maintainable UI code.
🚀 Getting Started #
Installation #
Add flutter_adaptive_grid_layout
to your pubspec.yaml
file:
YAML
dependencies:
flutter:
sdk: flutter
flutter_adaptive_grid_layout: ^0.0.1 # Use the latest version from pub.dev
Then, run flutter pub get
to fetch the package.
Basic Usage #
Wrap your adaptive layout with AdaptiveLayoutSizeProvider
and use AdaptiveGridLayout
to define your responsive structure.
Dart
import 'package:flutter/material.dart';
import 'package:flutter_adaptive_grid_layout/flutter_adaptive_grid_layout.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
// Determine the current screen size based on breakpoints
final currentLayoutSize = AdaptiveBreakpoints.materialDesign.fromWidth(
MediaQuery.of(context).size.width,
);
return Scaffold(
appBar: AppBar(
title: const Text('Adaptive Dashboard (Resize Window)'),
),
body: AdaptiveLayoutSizeProvider(
size: currentLayoutSize,
breakpoints: AdaptiveBreakpoints.materialDesign,
child: AdaptiveGridLayout(
breakpoints: AdaptiveBreakpoints.materialDesign,
layoutTemplates: {
// Define your layout for compact screens (e.g., mobile portrait)
AdaptiveLayoutSize.compact: AdaptiveGridTemplate(
size: AdaptiveLayoutSize.compact,
template: [
"header",
"content",
"sidebar", // Sidebar stacks below content
"footer",
],
columnSizes: [FlexSize.flex(1)], // Single column
rowSizes: [FlexSize.content(), FlexSize.flex(1), FlexSize.content(), FlexSize.content()],
),
// Define your layout for medium screens (e.g., tablets, mobile landscape)
AdaptiveLayoutSize.medium: AdaptiveGridTemplate(
size: AdaptiveLayoutSize.medium,
template: [
"header header",
"sidebar content",
"footer footer",
],
columnSizes: [FlexSize.fixed(200), FlexSize.flex(1)], // Fixed 200px sidebar, rest for content
rowSizes: [FlexSize.content(), FlexSize.flex(1), FlexSize.content()],
),
// Define your layout for expanded screens (e.g., small desktops)
AdaptiveLayoutSize.expanded: AdaptiveGridTemplate(
size: AdaptiveLayoutSize.expanded,
template: [
"header header header",
"nav content details",
"footer footer footer",
],
columnSizes: [FlexSize.fixed(150), FlexSize.flex(2), FlexSize.flex(1)], // Nav fixed, content gets 2x flex, details 1x
rowSizes: [FlexSize.content(), FlexSize.flex(1), FlexSize.content()],
),
// Define your layout for large screens (e.g., large desktops)
AdaptiveLayoutSize.large: AdaptiveGridTemplate(
size: AdaptiveLayoutSize.large,
template: [
"header header header header",
"nav content details ads",
"footer footer footer footer",
],
columnSizes: [FlexSize.fixed(150), FlexSize.flex(2), FlexSize.flex(1), FlexSize.fixed(100)], // Even more columns
rowSizes: [FlexSize.content(), FlexSize.flex(1), FlexSize.content()],
),
},
// Provide your actual widgets for each named region
children: {
'header': Container(
color: Colors.red[100],
padding: const EdgeInsets.all(8.0),
child: const Center(child: Text('App Header', style: TextStyle(fontSize: 20))),
),
'sidebar': Container(
color: Colors.green[100],
padding: const EdgeInsets.all(8.0),
child: const Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('Sidebar Nav'),
ListTile(title: Text('Item 1')),
ListTile(title: Text('Item 2')),
],
),
),
'nav': Container(
color: Colors.purple[100],
padding: const EdgeInsets.all(8.0),
child: const Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('Main Nav'),
ListTile(title: Text('Dashboard')),
ListTile(title: Text('Settings')),
],
),
),
'content': Container(
color: Colors.blue[100],
padding: const EdgeInsets.all(8.0),
child: const Center(child: Text('Main Content Area\n(Try resizing the window!)', textAlign: TextAlign.center, style: TextStyle(fontSize: 18))),
),
'details': Container(
color: Colors.orange[100],
padding: const EdgeInsets.all(8.0),
child: const Center(child: Text('Details Panel')),
),
'ads': Container(
color: Colors.yellow[100],
padding: const EdgeInsets.all(8.0),
child: const Center(child: Text('Advertisements')),
),
'footer': Container(
color: Colors.grey[300],
padding: const EdgeInsets.all(8.0),
child: const Center(child: Text('App Footer')),
),
},
),
),
);
}
}
Understanding the Template (AdaptiveGridTemplate
) #
The template
property in AdaptiveGridTemplate
is a List<String>
, where each string represents a row. Words in the string represent named areas, and .
represents an empty cell. Repeating a name spans that area across multiple columns.
Example template
:
Dart
[
"header header",
"sidebar content",
"footer footer",
]
This defines a 3-row, 2-column grid where:
- The
header
spans the first row across both columns. sidebar
is in(1,0)
andcontent
in(1,1)
.footer
spans the third row across both columns.
Sizing Rows and Columns (FlexSize
) #
columnSizes
and rowSizes
define how the grid tracks (rows/columns) are sized:
FlexSize.flex(factor)
: Takes a proportional amount of available space.factor
defaults to 1.0. (e.g.,FlexSize.flex(2)
takes twice the space ofFlexSize.flex(1)
).FlexSize.fixed(pixels)
: Takes a fixed size in logical pixels. (e.g.,FlexSize.fixed(200)
for a 200px wide sidebar).FlexSize.content()
: Aims to size based on the intrinsic content. (Current implementation is a basic approximation using available flexible space; for precise content-based sizing, a customRenderObjectWidget
would be ideal).FlexSize.auto()
: Similar toFlexSize.content()
, often implying minimal space or filling remaining space.
🖼️ Screenshots #
See flutter_adaptive_grid_layout
in action across different screen sizes:
Compact Layout (e.g., Mobile Portrait) #
On smaller screens, the sidebar moves below the main content, optimizing for vertical space.
Medium Layout (e.g., Tablet / Desktop Narrow) #
This layout provides a sidebar on the left and main content on the right, suitable for moderate screen widths.
Expanded Layout (e.g., Small Laptops) #
This layout provides a sidebar on the left and main content on the centre and details on the right.
Large Layout (e.g., Desktop Wide) #
For expansive screens, additional panels (like details and ads) appear, utilizing the extra horizontal space.
⚙️ Advanced Usage & Notes #
- Custom Breakpoints: You can define your own
AdaptiveBreakpoints
instance instead of usingAdaptiveBreakpoints.materialDesign
if your app requires different size thresholds. - Performance: For extremely complex grids or highly dynamic content, consider that the current
Stack
andPositioned
based implementation is a basic approximation. For true CSS Grid-like intrinsic sizing and advanced performance, a customRenderObjectWidget
orCustomMultiChildLayout
would be a more robust (and complex) solution.
🤝 Contributing #
Contributions are welcome! If you find a bug or have a feature request, please open an issue or submit a pull request on GitHub.
📄 License #
This package is licensed under the MIT License. See the LICENSE
file for more details.