Layout cells in FlexBox based on cell min width

This commit is contained in:
Elias Bonnici 2024-08-08 15:46:11 +02:00
parent cbedbfae4e
commit ea665b3299
No known key found for this signature in database
GPG Key ID: 5EAC28EA3F980CCF
4 changed files with 41 additions and 76 deletions

View File

@ -320,13 +320,16 @@ class _AppPageState extends ConsumerState<AppPage> {
Widget? _buildAppBarTitle(
BuildContext context, bool hasRail, bool hasManage, bool fullyExpanded) {
final showNavigation = ref.watch(_navigationVisibilityProvider);
final showDetailView = ref.watch(_detailViewVisibilityProvider);
EdgeInsets padding;
if (fullyExpanded) {
padding = EdgeInsets.only(left: showNavigation ? 280 : 72, right: 320);
padding = EdgeInsets.only(
left: showNavigation ? 280 : 72, right: showDetailView ? 320 : 0.0);
} else if (!hasRail && hasManage) {
padding = const EdgeInsets.only(right: 320);
} else if (hasRail && hasManage) {
padding = const EdgeInsets.only(left: 72, right: 320);
padding = EdgeInsets.only(left: 72, right: showDetailView ? 320 : 0.0);
} else if (hasRail && !hasManage) {
padding = const EdgeInsets.only(left: 72);
} else {
@ -627,7 +630,7 @@ class _AppPageState extends ConsumerState<AppPage> {
opacity: visible ? 1 : 0,
duration: const Duration(milliseconds: 300),
child: Container(
color: Theme.of(context).colorScheme.secondaryContainer,
color: Theme.of(context).hoverColor,
height: 1.0,
),
);
@ -643,6 +646,7 @@ class _AppPageState extends ConsumerState<AppPage> {
hasManage,
fullyExpanded,
),
centerTitle: true,
leading: hasRail
? Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,

View File

@ -548,9 +548,9 @@ class _FidoUnlockedPageState extends ConsumerState<_FidoUnlockedPage> {
selected: _selected == cred,
),
layout: layout,
spacing: layout == FlexLayout.grid ? 4.0 : null,
runSpacing: layout == FlexLayout.grid ? 4.0 : null,
getItemsPerRow: _getItemsPerRow,
cellMinWidth: 265,
spacing: layout == FlexLayout.grid ? 4.0 : 0.0,
runSpacing: layout == FlexLayout.grid ? 4.0 : 0.0,
)
],
),
@ -563,36 +563,6 @@ class _FidoUnlockedPageState extends ConsumerState<_FidoUnlockedPage> {
);
}
int _getItemsPerRow(double width) {
int itemsPerRow = 1;
if (width <= 600) {
// single column
itemsPerRow = 1;
} else if (width <= 900) {
// 2 column
itemsPerRow = 2;
} else if (width < 1300) {
// 3 column
itemsPerRow = 3;
} else if (width < 1500) {
// 4 column
itemsPerRow = 4;
} else if (width < 1700) {
// 5 column
itemsPerRow = 5;
} else if (width < 1900) {
// 6 column
itemsPerRow = 6;
} else if (width < 2100) {
// 7 column
itemsPerRow = 7;
} else {
// 8 column
itemsPerRow = 8;
}
return itemsPerRow;
}
Widget _buildLoadingPage(BuildContext context) => AppPage(
title: AppLocalizations.of(context)!.s_passkeys,
capabilities: const [Capability.fido2],

View File

@ -75,8 +75,9 @@ class AccountList extends ConsumerWidget {
selected: value.credential == selected,
large: pinnedLayout == FlexLayout.grid,
),
spacing: pinnedLayout == FlexLayout.grid ? 4.0 : null,
runSpacing: pinnedLayout == FlexLayout.grid ? 4.0 : null,
cellMinWidth: 250,
spacing: pinnedLayout == FlexLayout.grid ? 4.0 : 0.0,
runSpacing: pinnedLayout == FlexLayout.grid ? 4.0 : 0.0,
layout: pinnedLayout,
),
],
@ -96,8 +97,9 @@ class AccountList extends ConsumerWidget {
selected: value.credential == selected,
large: normalLayout == FlexLayout.grid,
),
spacing: normalLayout == FlexLayout.grid ? 4.0 : null,
runSpacing: normalLayout == FlexLayout.grid ? 4.0 : null,
cellMinWidth: 250,
spacing: normalLayout == FlexLayout.grid ? 4.0 : 0.0,
runSpacing: normalLayout == FlexLayout.grid ? 4.0 : 0.0,
layout: normalLayout,
),
],

View File

@ -1,4 +1,5 @@
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:material_symbols_icons/symbols.dart';
@ -19,50 +20,39 @@ enum FlexLayout {
class FlexBox<T> extends StatelessWidget {
final List<T> items;
final Widget Function(T value) itemBuilder;
final int Function(double width)? getItemsPerRow;
final FlexLayout layout;
final double? spacing;
final double? runSpacing;
final double cellMinWidth;
final double spacing;
final double runSpacing;
const FlexBox({
super.key,
required this.items,
required this.itemBuilder,
this.getItemsPerRow,
required this.cellMinWidth,
this.layout = FlexLayout.list,
this.spacing = 0.0,
this.runSpacing = 0.0,
});
int _getItemsPerRow(double width) {
int itemsPerRow = 1;
if (layout == FlexLayout.grid) {
if (width <= 420) {
// single column
itemsPerRow = 1;
} else if (width <= 620) {
// 2 column
itemsPerRow = 2;
} else if (width < 860) {
// 3 column
itemsPerRow = 3;
} else if (width < 1200) {
// 4 column
itemsPerRow = 4;
} else if (width < 1500) {
// 5 column
itemsPerRow = 5;
} else if (width < 1800) {
// 6 column
itemsPerRow = 6;
} else if (width < 2000) {
// 7 column
itemsPerRow = 7;
} else {
// 8 column
itemsPerRow = 8;
// Calculate the maximum number of cells that can fit in one row
int cellsPerRow = (width / (cellMinWidth + spacing)).floor();
// Ensure there's at least one cell per row
if (cellsPerRow < 1) {
cellsPerRow = 1;
}
// Calculate the total width needed for the calculated number of cells and spacing
double totalWidthNeeded =
cellsPerRow * cellMinWidth + (cellsPerRow - 1) * spacing;
// Adjust the number of cells per row if the calculated total width exceeds the available width
if (totalWidthNeeded > width) {
cellsPerRow = cellsPerRow - 1 > 0 ? cellsPerRow - 1 : 1;
}
return itemsPerRow;
return cellsPerRow;
}
List<List<T>> getChunks(int itemsPerChunk) {
@ -86,9 +76,8 @@ class FlexBox<T> extends StatelessWidget {
return LayoutBuilder(
builder: (context, constraints) {
final width = constraints.maxWidth;
final itemsPerRow = layout == FlexLayout.grid
? getItemsPerRow?.call(width) ?? _getItemsPerRow(width)
: 1;
final itemsPerRow =
layout == FlexLayout.grid ? _getItemsPerRow(width) : 1;
final chunks = getChunks(itemsPerRow);
return Column(
@ -105,7 +94,7 @@ class FlexBox<T> extends StatelessWidget {
SizedBox(width: spacing),
],
if (c.length < itemsPerRow) ...[
// Prevents resizing when an items is removed
// Prevents resizing when an item is removed
SizedBox(width: 8 * (itemsPerRow - c.length).toDouble()),
Spacer(
flex: itemsPerRow - c.length,