| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109 |
- import 'dart:math' as math;
- import 'dart:typed_data';
- import 'package:flutter/material.dart';
- import 'shortcut_tile.dart';
- class ShortcutSpec {
- const ShortcutSpec({
- required this.title,
- required this.subtitle,
- required this.iconAsset,
- required this.assigned,
- required this.onTap,
- this.onLongPress,
- this.longPressHint,
- this.iconBytes,
- this.showEqualizer = false,
- });
- final String title;
- final String? subtitle;
- final String iconAsset;
- final bool assigned;
- final VoidCallback onTap;
- final VoidCallback? onLongPress;
- final String? longPressHint;
- final Uint8List? iconBytes;
- final bool showEqualizer;
- }
- /// Fits up to 16 home shortcuts. Columns and tile size are chosen together so
- /// the whole set stays visible and grows denser as apps are added. The grid is
- /// anchored to the bottom so a short row does not float mid-page.
- class ShortcutGrid extends StatelessWidget {
- const ShortcutGrid({
- super.key,
- required this.shortcuts,
- required this.compact,
- });
- final List<ShortcutSpec> shortcuts;
- final bool compact;
- @override
- Widget build(BuildContext context) {
- return LayoutBuilder(
- builder: (context, constraints) {
- if (!constraints.hasBoundedWidth || !constraints.hasBoundedHeight) {
- return const SizedBox.shrink();
- }
- if (shortcuts.isEmpty) return const SizedBox.shrink();
- final dense = shortcuts.length > 8;
- final horizontalGap = dense
- ? (compact ? 10.0 : 14.0)
- : (compact ? 18.0 : 24.0);
- final rowGap = dense
- ? (compact ? 12.0 : 16.0)
- : (compact ? 18.0 : 26.0);
- final labelAllowance = compact ? 46.0 : 50.0;
- final maxTileSize = compact ? 168.0 : 196.0;
- var bestSize = 0.0;
- for (var columns = 2; columns <= 6; columns++) {
- if (columns > shortcuts.length) break;
- final rows = (shortcuts.length / columns).ceil();
- final widthLimited =
- (constraints.maxWidth - horizontalGap * (columns - 1)) / columns;
- final heightLimited =
- (constraints.maxHeight - rowGap * (rows - 1)) / rows -
- labelAllowance;
- final candidate = math
- .min(widthLimited, heightLimited)
- .clamp(0.0, maxTileSize);
- if (candidate > bestSize) bestSize = candidate;
- }
- final size = bestSize.clamp(64.0, maxTileSize);
- return Align(
- alignment: Alignment.bottomCenter,
- child: Wrap(
- alignment: WrapAlignment.center,
- crossAxisAlignment: WrapCrossAlignment.start,
- spacing: horizontalGap,
- runSpacing: rowGap,
- children: [
- for (final shortcut in shortcuts)
- ShortcutTile(
- title: shortcut.title,
- subtitle: shortcut.subtitle,
- iconAsset: shortcut.iconAsset,
- size: size,
- assigned: shortcut.assigned,
- onTap: shortcut.onTap,
- onLongPress: shortcut.onLongPress,
- longPressHint: shortcut.longPressHint,
- iconBytes: shortcut.iconBytes,
- showEqualizer: shortcut.showEqualizer,
- ),
- ],
- ),
- );
- },
- );
- }
- }
|