Files
CloudHome-Ops/lib/utils/responsive.dart

56 lines
1.8 KiB
Dart
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import 'package:flutter/material.dart';
/// 响应式断点工具:用 [Size.shortestSide] 而非 width 判定窗口尺寸,
/// 使手机横屏(1600×900 → shortSide=900)正确落入 medium 档。
///
/// 详见 docs/手机端UI优化方案-v2.md §7.4。
enum AppWindowSize { compact, medium, expanded }
class AppResponsive {
AppResponsive(this.size, this.orientation);
final Size size;
final Orientation orientation;
factory AppResponsive.of(BuildContext context) => AppResponsive(
MediaQuery.sizeOf(context),
MediaQuery.orientationOf(context),
);
bool get isLandscape => orientation == Orientation.landscape;
AppWindowSize get windowSize => switch (size.shortestSide) {
< 600 => AppWindowSize.compact,
< 840 => AppWindowSize.medium, // ★ 手机横屏 900 落这里
_ => AppWindowSize.expanded,
};
/// 横屏且宽度够时启用主从(双栏)布局。
bool get useMasterDetail => size.width >= 840 && isLandscape;
/// 自适应网格列数(列表 / 卡片网格)。
int gridCount({double minTileWidth = 320}) =>
(size.width / minTileWidth).floor().clamp(2, 6);
/// 内容最大宽度(限宽居中,避免横屏拉爆)。
double get contentMaxWidth => switch (windowSize) {
AppWindowSize.compact => double.infinity,
AppWindowSize.medium => 560,
AppWindowSize.expanded => 720,
};
/// 栅格间距。
double get gutter => switch (windowSize) {
AppWindowSize.compact => 12,
AppWindowSize.medium => 24,
_ => 32,
};
/// 卡片内边距(横屏更宽松)。
double get cardPadding => windowSize == AppWindowSize.compact ? 16 : 20;
}
extension AppResponsiveX on BuildContext {
AppResponsive get responsive => AppResponsive.of(this);
}