{"id":37770524,"url":"https://github.com/fluttercandies/flexbox_layout","last_synced_at":"2026-01-25T10:13:31.480Z","repository":{"id":332506181,"uuid":"1134016905","full_name":"fluttercandies/flexbox_layout","owner":"fluttercandies","description":"A Flutter library for CSS Flexbox layout. ","archived":false,"fork":false,"pushed_at":"2026-01-19T05:23:56.000Z","size":9383,"stargazers_count":8,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-01-19T17:58:07.026Z","etag":null,"topics":["beautiful","flexbox","flutter","google-photos","grid-layout"],"latest_commit_sha":null,"homepage":"","language":"Dart","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/fluttercandies.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-01-14T06:05:15.000Z","updated_at":"2026-01-19T05:17:10.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/fluttercandies/flexbox_layout","commit_stats":null,"previous_names":["fluttercandies/flexbox"],"tags_count":5,"template":false,"template_full_name":null,"purl":"pkg:github/fluttercandies/flexbox_layout","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fluttercandies%2Fflexbox_layout","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fluttercandies%2Fflexbox_layout/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fluttercandies%2Fflexbox_layout/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fluttercandies%2Fflexbox_layout/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/fluttercandies","download_url":"https://codeload.github.com/fluttercandies/flexbox_layout/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fluttercandies%2Fflexbox_layout/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28604712,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-20T12:01:53.233Z","status":"ssl_error","status_checked_at":"2026-01-20T12:01:46.545Z","response_time":117,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["beautiful","flexbox","flutter","google-photos","grid-layout"],"created_at":"2026-01-16T14:52:26.693Z","updated_at":"2026-01-20T14:01:03.884Z","avatar_url":"https://github.com/fluttercandies.png","language":"Dart","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Flexbox\n\n[中文文档](README_zh_CN.md) | English\n\n\u003cdiv align=\"center\"\u003e\n  \u003cimg src=\"statics/logo.png\" alt=\"Flexbox Logo\" width=\"120\" height=\"120\"\u003e\n\u003c/div\u003e\n\nA Flutter library for CSS Flexbox layout. This package provides widgets for creating layouts using the CSS Flexbox layout model, bringing the power and flexibility of flexbox to Flutter.\n\n[![Pub Version](https://img.shields.io/pub/v/flexbox_layout)](https://pub.dev/packages/flexbox_layout)\n[![Publisher](https://img.shields.io/pub/publisher/flexbox_layout)](https://pub.dev/packages/flexbox_layout)\n[![Likes](https://img.shields.io/pub/likes/flexbox_layout)](https://pub.dev/packages/flexbox_layout/score)\n[![Popularity](https://img.shields.io/pub/popularity/flexbox_layout)](https://pub.dev/packages/flexbox_layout/score)\n[![Pub Dev](https://img.shields.io/badge/dart-docs-blue.svg)](https://pub.dev/documentation/flexbox_layout/latest/)\n[![Live Demo](https://img.shields.io/badge/Live%20Demo-GitHub%20Pages-blue)](https://fluttercandies.github.io/flexbox_layout/)\n\n## Live Demo\n\nTry out the interactive demo: **[https://fluttercandies.github.io/flexbox_layout/](https://fluttercandies.github.io/flexbox_layout/)**\n\n## Screenshots\n\n| | |\n|:---:|:---:|\n| ![Basic Flexbox](statics/01.png) | ![FlexboxList](statics/02.png) |\n| ![Dynamic Gallery](statics/03.png) | ![Sliver Dynamic](statics/04.png) |\n\n## Features\n\n- **Flexbox Widget**: Similar to Flutter's `Wrap` but with full flexbox layout support including `flex-grow`, `flex-shrink`, `justify-content`, `align-items`, and more.\n- **FlexItem Widget**: Wrap children with flex item properties like `order`, `flexGrow`, `flexShrink`, `alignSelf`, and `flexBasisPercent`.\n- **SliverFlexbox**: A sliver version for use in `CustomScrollView` with item recycling and viewport-based rendering.\n- **FlexboxList**: A convenience widget similar to `GridView` but with flexbox layout capabilities.\n- **DynamicFlexbox**: Dynamic flexbox layout that automatically adjusts item sizes based on aspect ratios.\n- **DimensionResolver**: Utilities for asynchronously resolving dimensions (e.g., image sizes).\n\n## Installation\n\nAdd this to your package's `pubspec.yaml` file:\n\n```yaml\ndependencies:\n  flexbox_layout: any\n```\n\n## Usage\n\n### Basic Flexbox\n\n```dart\nimport 'package:flexbox_layout/flexbox_layout.dart';\n\nFlexbox(\n  flexDirection: FlexDirection.row,\n  flexWrap: FlexWrap.wrap,\n  justifyContent: JustifyContent.spaceBetween,\n  alignItems: AlignItems.center,\n  mainAxisSpacing: 8,\n  crossAxisSpacing: 8,\n  children: [\n    FlexItem(\n      flexGrow: 1,\n      child: Container(width: 100, height: 100, color: Colors.red),\n    ),\n    FlexItem(\n      flexGrow: 2,\n      child: Container(width: 100, height: 100, color: Colors.blue),\n    ),\n    FlexItem(\n      flexGrow: 1,\n      alignSelf: AlignSelf.flexEnd,\n      child: Container(width: 100, height: 100, color: Colors.green),\n    ),\n  ],\n)\n```\n\n### FlexboxList\n\n```dart\nFlexboxList.count(\n  crossAxisCount: 3,\n  mainAxisSpacing: 8,\n  crossAxisSpacing: 8,\n  padding: const EdgeInsets.all(8),\n  children: List.generate(\n    100,\n    (index) =\u003e Card(\n      child: Center(child: Text('Item $index')),\n    ),\n  ),\n)\n```\n\n### FlexboxList with Max Extent\n\n```dart\nFlexboxList.extent(\n  maxCrossAxisExtent: 200, // Maximum width per item\n  mainAxisSpacing: 8,\n  crossAxisSpacing: 8,\n  children: List.generate(\n    100,\n    (index) =\u003e Card(child: Center(child: Text('Item $index'))),\n  ),\n)\n```\n\n### SliverFlexbox in CustomScrollView\n\n```dart\nCustomScrollView(\n  slivers: [\n    SliverAppBar(title: Text('Flexbox')),\n    SliverFlexbox(\n      delegate: SliverChildBuilderDelegate(\n        (context, index) =\u003e Card(child: Text('Item $index')),\n        childCount: 100,\n      ),\n      flexboxDelegate: SliverFlexboxDelegateWithFixedCrossAxisCount(\n        crossAxisCount: 3,\n        mainAxisSpacing: 8,\n        crossAxisSpacing: 8,\n      ),\n    ),\n  ],\n)\n```\n\n### DynamicFlexboxList for Image Galleries\n\n**Just works!** Images are automatically measured and arranged to fill each row.\n\n```dart\nDynamicFlexboxList(\n  targetRowHeight: 200,\n  mainAxisSpacing: 4,\n  crossAxisSpacing: 4,\n  itemBuilder: (context, index) {\n    return Image.network(images[index].url, fit: BoxFit.cover);\n  },\n  itemCount: images.length,\n)\n```\n\n### SliverDynamicFlexbox with Aspect Ratios\n\n```dart\nCustomScrollView(\n  slivers: [\n    SliverDynamicFlexbox(\n      flexboxDelegate: SliverDynamicFlexboxDelegate(\n        targetRowHeight: 200,\n        mainAxisSpacing: 4,\n        crossAxisSpacing: 4,\n      ),\n      childDelegate: SliverChildBuilderDelegate(\n        (context, index) =\u003e Image.network(images[index].url),\n        childCount: images.length,\n      ),\n    ),\n  ],\n)\n```\n\n### Using DimensionResolver for Pre-loading Image Sizes\n\n```dart\nclass _GalleryState extends State\u003c_Gallery\u003e with DimensionResolverMixin {\n  final List\u003cString\u003e imageUrls = [...];\n\n  @override\n  void initState() {\n    super.initState();\n    // Pre-load all image dimensions\n    for (int i = 0; i \u003c imageUrls.length; i++) {\n      resolveImageDimension(NetworkImage(imageUrls[i]), key: i);\n    }\n  }\n\n  @override\n  Widget build(BuildContext context) {\n    return SliverFlexboxDelegateWithDynamicAspectRatios(\n      childCount: imageUrls.length,\n      aspectRatioProvider: getAspectRatio, // From mixin\n      defaultAspectRatio: 1.0,\n      // ...\n    );\n  }\n}\n```\n\n### Using DynamicFlexItem for Problematic Widgets\n\n**When to use**: If your child uses `Stack` with `StackFit.expand` or other widgets that don't handle unbounded constraints well during intrinsic size measurement.\n\n```dart\nSliverDynamicFlexbox(\n  flexboxDelegate: SliverDynamicFlexboxDelegate(...),\n  childDelegate: SliverChildBuilderDelegate(\n    (context, index) =\u003e DynamicFlexItem(\n      child: Stack(\n        fit: StackFit.expand,\n        children: [\n          Image.network(images[index], fit: BoxFit.cover),\n          Positioned(bottom: 8, left: 8, child: Text('Label')),\n        ],\n      ),\n    ),\n    childCount: images.length,\n  ),\n)\n```\n\n**Note**: For simple `Image` widgets, you don't need `DynamicFlexItem` - use them directly.\n\n### Scalable Flexbox with Pinch-to-Zoom\n\n**Google Photos style** pinch-to-zoom experience for your flexbox galleries:\n\n```dart\nclass _ScalableGalleryState extends State\u003c_ScalableGallery\u003e\n    with SingleTickerProviderStateMixin {\n  late final controller = FlexboxScaleController(\n    initialExtent: 150.0,\n    minExtent: 80.0,\n    maxExtent: 300.0,\n    snapPoints: [80, 120, 160, 200, 250, 300],\n    gridModeThreshold: 250.0, // Switch to 1:1 grid when zoomed out\n  );\n\n  @override\n  void initState() {\n    super.initState();\n    controller.attachTickerProvider(this);\n  }\n\n  @override\n  void dispose() {\n    controller.dispose();\n    super.dispose();\n  }\n\n  @override\n  Widget build(BuildContext context) {\n    return GestureDetector(\n      onScaleStart: controller.onScaleStart,\n      onScaleUpdate: controller.onScaleUpdate,\n      onScaleEnd: controller.onScaleEnd,\n      onDoubleTap: controller.onDoubleTap,\n      child: CustomScrollView(\n        slivers: [\n          SliverScalableFlexbox(\n            controller: controller,\n            mainAxisSpacing: 2.0,\n            crossAxisSpacing: 2.0,\n            delegate: SliverChildBuilderDelegate(\n              (context, index) =\u003e Image.network(images[index].url, fit: BoxFit.cover),\n              childCount: images.length,\n            ),\n          ),\n        ],\n      ),\n    );\n  }\n}\n```\n\n**Key features:**\n- **Responsive scaling**: Follows pinch gestures in real-time\n- **Smooth snap animation**: Snaps to predefined points with spring physics\n- **Mode switching**: Automatically switches between 1:1 grid and aspect ratio modes\n- **Velocity-based momentum**: Continues motion based on gesture velocity\n\n## API Reference\n\n### Enums\n\n| Enum | Values | Description |\n|------|--------|-------------|\n| `FlexDirection` | `row`, `rowReverse`, `column`, `columnReverse` | Direction of the main axis |\n| `FlexWrap` | `noWrap`, `wrap`, `wrapReverse` | Whether items wrap to multiple lines |\n| `JustifyContent` | `flexStart`, `flexEnd`, `center`, `spaceBetween`, `spaceAround`, `spaceEvenly` | Alignment along the main axis |\n| `AlignItems` | `flexStart`, `flexEnd`, `center`, `baseline`, `stretch` | Alignment along the cross axis |\n| `AlignSelf` | `auto`, `flexStart`, `flexEnd`, `center`, `baseline`, `stretch` | Override parent's `AlignItems` |\n| `AlignContent` | `flexStart`, `flexEnd`, `center`, `spaceBetween`, `spaceAround`, `stretch` | Alignment of flex lines |\n| `FlexboxScaleMode` | `grid1x1`, `aspectRatio` | Display mode for scalable flexbox |\n\n### FlexItem Properties\n\n| Property | Type | Default | Description |\n|----------|------|---------|-------------|\n| `order` | `int` | `1` | Order of the item in the flex container |\n| `flexGrow` | `double` | `0.0` | How much the item should grow relative to others |\n| `flexShrink` | `double` | `1.0` | How much the item should shrink relative to others |\n| `alignSelf` | `AlignSelf` | `auto` | Cross-axis alignment override |\n| `flexBasisPercent` | `double` | `-1.0` | Initial size as a percentage (0.0-1.0) of parent |\n| `minWidth` | `double?` | `null` | Minimum width constraint |\n| `minHeight` | `double?` | `null` | Minimum height constraint |\n| `maxWidth` | `double?` | `null` | Maximum width constraint |\n| `maxHeight` | `double?` | `null` | Maximum height constraint |\n| `wrapBefore` | `bool` | `false` | Force a wrap before this item |\n\n### Available Widgets\n\n| Widget | Description |\n|--------|-------------|\n| `Flexbox` | Basic flexbox layout widget (non-scrolling) |\n| `FlexItem` | Wrapper for children with flex properties |\n| `FlexboxList` | Scrollable list with flexbox layout |\n| `SliverFlexbox` | Sliver version for CustomScrollView |\n| `DynamicFlexboxList` | Auto-sizing flexbox list (measures children) |\n| `SliverDynamicFlexbox` | Dynamic sliver for CustomScrollView |\n| `DynamicFlexItem` | Wrapper for children with unbounded constraint issues |\n| `SliverScalableFlexbox` | Scalable sliver with pinch-to-zoom support (Google Photos style) |\n\n### Dimension Resolution Utilities\n\n| Class/Type | Description |\n|------------|-------------|\n| `DimensionResolver` | Async dimension resolver for images and custom content |\n| `DimensionResolverMixin` | Mixin for easy dimension resolution in State classes |\n| `BatchDimensionResolver` | Batch dimension resolution with progress tracking |\n| `ItemDimension` | Immutable class representing width/height with aspect ratio support |\n| `ImageProviderDimensionExtension` | Extension to get dimensions from ImageProvider |\n\n### Scale Controller\n\n| Class/Type | Description |\n|------------|-------------|\n| `FlexboxScaleController` | Controller for scalable flexbox with pinch-to-zoom (Google Photos style) |\n| `FlexboxScaleMode` | Display mode enum (`grid1x1`, `aspectRatio`) |\n\n### Available Delegates\n\n| Delegate | Description |\n|----------|-------------|\n| `SliverFlexboxDelegateWithFixedCrossAxisCount` | Grid-like layout with fixed items per row/column |\n| `SliverFlexboxDelegateWithMaxCrossAxisExtent` | Responsive layout with max item size |\n| `SliverFlexboxDelegateWithAspectRatios` | Variable aspect ratios (pre-known) |\n| `SliverFlexboxDelegateWithDynamicAspectRatios` | Dynamic aspect ratios via callback |\n| `SliverFlexboxDelegateWithFlexValues` | Custom flex grow values per item |\n| `SliverFlexboxDelegateWithBuilder` | Fully customizable via builder callback |\n| `SliverFlexboxDelegateWithDirectExtent` | Direct extent control with smooth transitions (for pinch-to-zoom) |\n\n### SliverDynamicFlexboxDelegate Options\n\n| Property | Type | Default | Description |\n|----------|------|---------|-------------|\n| `targetRowHeight` | `double` | `200.0` | Target height for each row |\n| `mainAxisSpacing` | `double` | `0.0` | Spacing between rows |\n| `crossAxisSpacing` | `double` | `0.0` | Spacing between items in a row |\n| `minRowFillFactor` | `double` | `0.8` | Min fill ratio for last row (0.0-1.0) |\n| `defaultAspectRatio` | `double` | `1.0` | Fallback aspect ratio when not measured |\n| `debounceDuration` | `Duration` | `150ms` | Delay before applying size updates |\n| `aspectRatioChangeThreshold` | `double` | `0.01` | Min change (1%) to trigger layout update |\n| `crossAxisExtentChangeThreshold` | `double` | `1.0` | Min viewport width change to clear cache |\n| `aspectRatioGetter` | `function?` | `null` | Optional callback to provide aspect ratios |\n\n## Architecture\n\n### Component Hierarchy\n\n```\nFlexbox (RenderObjectWidget)\n├── RenderFlexbox (RenderObject)\n│   └── FlexboxParentData\n│       └── FlexItemData\n│\nFlexItem (ParentDataWidget)\n└── applies FlexItemData to children\n\nFlexboxList (StatelessWidget)\n└── CustomScrollView\n    └── SliverFlexbox\n        └── RenderSliverFlexbox\n            └── SliverFlexboxParentData\n\nDynamicFlexboxList (StatelessWidget)\n└── CustomScrollView\n    └── SliverDynamicFlexbox\n        └── RenderSliverDynamicFlexbox\n            └── SliverDynamicFlexboxParentData\n```\n\n### Layout Algorithm\n\n1. **Measure children** and determine their intrinsic sizes\n2. **Group into flex lines** based on flexWrap and available space\n3. **Distribute free space** using flexGrow/flexShrink ratios\n4. **Apply alignment** (justify-content, align-items, align-content)\n5. **Position children** with proper offsets\n\n## Example\n\nSee the [example](example/) directory for a complete sample app demonstrating all features:\n\n- Basic Flexbox usage\n- FlexboxList with fixed cross axis count\n- DynamicFlexbox with aspect ratio based layout\n- Network Image Gallery\n- Interactive Playground\n\n## Contributing\n\nContributions are welcome! Please feel free to submit a Pull Request.\n\n## License\n\nThis project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.\n\nCopyright (c) 2026 iota9star\n\n## Credits\n\nThis library is inspired by CSS Flexbox layout and Google's [flexbox-layout](https://github.com/google/flexbox-layout) for Android.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffluttercandies%2Fflexbox_layout","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffluttercandies%2Fflexbox_layout","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffluttercandies%2Fflexbox_layout/lists"}