guru_sdk/guru_ui/packages/design/lib/design_metrics.dart

375 lines
11 KiB
Dart
Raw Normal View History

/// Created by @Haoyi on 2021/7/7
///
part of "design.dart";
class _DeviceMetrics {
final double wScale;
final double hScale;
final Size size;
final TextDirection? direction;
final Offset offset;
final SystemAdaptation? adaptation;
const _DeviceMetrics(this.wScale, this.hScale, this.size, this.direction,
{this.offset = Offset.zero, this.adaptation});
}
enum DesignFit { fitWidth, fitHeight, fill }
enum _DesignMethod {
width,
height,
average,
fontSize,
absoluteFontSize,
widthScale,
heightScale,
combine,
origin,
statusBarHeight,
wrappedInSafeAreaStatusBarHeight,
navigationBarHeight,
wrappedInSafeAreaNavigationBarHeight
}
class SystemAdaptation {
final double? pixelRatio;
final double? textScaleFactor;
const SystemAdaptation({this.pixelRatio, this.textScaleFactor});
static SystemAdaptation? defaultSystemAdaptation;
static double? get globalPixelRation => defaultSystemAdaptation?.pixelRatio;
static double? get globalTextScaleFactor => defaultSystemAdaptation?.textScaleFactor;
}
class DesignMetrics {
Size designResolution = Size.zero;
final List<DesignObject> objects = [];
final SystemAdaptation? adaptation;
late Size measuredSize;
static Map<num, DesignField> originFields = {
0: DesignField._origin(0),
1: DesignField._origin(1),
2: DesignField._origin(2),
3: DesignField._origin(3),
4: DesignField._origin(4),
5: DesignField._origin(5),
6: DesignField._origin(6),
7: DesignField._origin(7),
8: DesignField._origin(8),
9: DesignField._origin(9),
};
DesignMetrics.create(this.designResolution, {this.adaptation});
DesignMetrics.dynamic({this.adaptation}) : designResolution = Size.zero;
DesignField origin(num value) {
final result = originFields[value];
if (result != null) {
return result;
}
final field = DesignField._origin(value);
originFields[value] = field;
return field;
}
DesignField designWidth(double size) {
final field = DesignField._width(size);
_add(field);
return field;
}
DesignField designHorizontal(double size) {
final field = DesignField._width(size);
_add(field);
return field;
}
DesignField designHeight(double size) {
final field = DesignField._height(size);
_add(field);
return field;
}
DesignField designVertical(double size) {
final field = DesignField._height(size);
_add(field);
return field;
}
DesignField designFontSize(double size) {
final field = DesignField._average(size);
_add(field);
return field;
}
DesignField designAverageSize(double size) {
final field = DesignField._average(size);
_add(field);
return field;
}
DesignField design(DesignField field) {
_add(field);
return field;
}
DesignField widthScale(double scale) {
final field = DesignField._widthScale(scale);
_add(field);
return field;
}
DesignField heightScale(double scale) {
final field = DesignField._heightScale(scale);
_add(field);
return field;
}
DesignField relativeRatio(DesignField relative, double ratio) {
final field = DesignField._relativeRatio(relative, ratio);
_add(field);
return field;
}
DesignSize designSize(double width, double height) {
final size = _DesignExplicitSize(width, height);
_add(size);
return size;
}
DesignSize designFieldSize(DesignField width, DesignField height) {
final size = _DesignFieldSize(width, height);
_add(size);
return size;
}
DesignSize widthRatioSize({required double width, required double ratio}) {
final size = _DesignWidthRatioSize(width, ratio);
_add(size);
return size;
}
DesignSize heightRatioSize({required double height, required double ratio}) {
final size = _DesignHeightRatioSize(height, ratio);
_add(size);
return size;
}
DesignRect fromLTRB(double left, double top, double right, double bottom) {
final rect = _DesignExplicitRect.fromLTRB(left, top, right, bottom);
_add(rect);
return rect;
}
DesignRect fromLTWH(double left, double top, double width, double height) {
return fromLTRB(left, top, left + width, top + height);
}
DesignRect fromCenter(Offset center, double width, double height) {
return fromLTRB(center.dx - width * 0.5, center.dy - height * 0.5, center.dx + width * 0.5,
center.dy + height * 0.5);
}
DesignRect fromFieldLTRB(
DesignField left, DesignField top, DesignField right, DesignField bottom) {
final rect = _DesignFieldRect.fromLTRB(left, top, right, bottom);
_add(rect);
return rect;
}
DesignRect fromFieldLTWH(
DesignField left, DesignField top, DesignField width, DesignField height) {
return fromFieldLTRB(left, top, left + width, top + height);
}
DesignRect fromFieldCenter(
DesignField centerX, DesignField centerY, DesignField width, DesignField height) {
return fromFieldLTRB(
centerX - DesignField._relativeRatio(width, 0.5),
centerY - DesignField._relativeRatio(height, 0.5),
centerX + DesignField._relativeRatio(width, 0.5),
centerY + DesignField._relativeRatio(height, 0.5));
}
DesignOffset fieldOffset(DesignField dx, DesignField dy) {
final offset = DesignOffset(dx, dy);
_add(offset);
return offset;
}
DesignOffset offset(double dx, double dy) {
return fieldOffset(designHorizontal(dx), designVertical(dy));
}
DesignField statusBarHeight({double defaultHeight = 0, bool wrappedInSafeArea = false}) {
final field = wrappedInSafeArea
? DesignField.wrappedInSafeAreaStatusBarHeight(defaultHeight)
: DesignField.statusBarHeight(defaultHeight: defaultHeight);
_add(field);
return field;
}
DesignField fakeStatusBarHeight({double fakeHeight = 0}) {
final field = DesignField.wrappedInSafeAreaStatusBarHeight(fakeHeight);
_add(field);
return field;
}
DesignField navigationBarHeight({double defaultHeight = 0, bool wrappedInSafeArea = false}) {
final field = wrappedInSafeArea
? DesignField.wrappedInSafeAreaNavigationBarHeight(defaultHeight)
: DesignField.navigationBarHeight(defaultHeight: defaultHeight);
_add(field);
return field;
}
DesignField combineAdd(DesignField field1, DesignField field2) {
final field = field1 + field2;
_add(field);
return field;
}
void _add(DesignObject object) {
objects.add(object);
}
MeasuredMetrics measure(Size size) {
measuredSize = size;
final deviceMetrics = _DeviceMetrics(
size.width / designResolution.width, size.height / designResolution.height, size, null,
adaptation: adaptation);
for (var field in objects) {
field.measure(deviceMetrics);
}
// print("size:$size designResolution:$designResolution ${deviceMetrics.wScale} ${deviceMetrics.hScale}");
return MeasuredMetrics(deviceMetrics, designResolution);
}
MeasuredMetrics adaptiveMeasure(Size screenSize,
{DesignFit fit = DesignFit.fill, double scale = 1.0, double? limitSize, Size? designSize}) {
Size size;
designResolution = designSize ?? designResolution;
switch (fit) {
case DesignFit.fitWidth:
final newWidth = min(screenSize.width * scale, limitSize ?? screenSize.width);
final newHeight = newWidth * (designResolution.height / designResolution.width);
size = Size(newWidth, newHeight);
break;
case DesignFit.fitHeight:
final newHeight = screenSize.height * scale;
final newWidth = newHeight * (designResolution.width / designResolution.height);
size = Size(newWidth, newHeight);
break;
default:
size = screenSize;
break;
}
return measure(size);
}
}
class MeasuredMetrics {
final _DeviceMetrics metrics;
final Size designResolution;
Size get size => metrics.size;
double get measuredWidth => size.width;
double get measuredHeight => size.height;
// 宽高比
double get aspectRatio => size.width / size.height;
double get designAspectRatio => designResolution.width / designResolution.height;
double get deviceInverseAspectRatio => 1 / aspectRatio;
double get designInverseAspectRatio => 1 / designAspectRatio;
double get layoutHeightScaleFactor => designInverseAspectRatio / deviceInverseAspectRatio;
double get layoutWidthScaleFactor => deviceInverseAspectRatio / designInverseAspectRatio;
MeasuredMetrics(this.metrics, this.designResolution);
Size measureSize(double width, double height) {
return Size(metrics.wScale * width, metrics.hScale * height);
}
Offset measureOffset(double x, double y) {
return Offset(metrics.wScale * x, metrics.hScale * y);
}
double measureWidth(double width, {bool consistent = false}) {
// 宽度暂不支持这个参数
return metrics.wScale * width;
}
double measureHeight(double height, {bool consistent = false}) {
return metrics.hScale * height * (consistent ? layoutHeightScaleFactor : 1.0);
}
double measureVertical(double vertical, {bool consistent = false}) {
return metrics.hScale * vertical * (consistent ? layoutHeightScaleFactor : 1.0);
}
double measureHorizontal(double horizontal, {bool consistent = false}) {
// 宽度暂不支持这个参数
return metrics.wScale * horizontal;
}
double measureFontSize(double fontSize) {
return DesignField._calculate(_DesignMethod.fontSize, metrics, fontSize);
}
double measureAbsoluteFontSize(double fontSize, {bool consistent = false}) {
if (consistent) {
return fontSize *
metrics.hScale /
(metrics.adaptation?.textScaleFactor ?? Get.textScaleFactor);
}
return DesignField._calculate(_DesignMethod.absoluteFontSize, metrics, fontSize);
}
double statusBarHeight(double ifAbsent) {
return DesignField._calculate(_DesignMethod.statusBarHeight, metrics, ifAbsent);
}
double wrappedInSafeAreaStatusBarHeight(double ifAbsent) {
return DesignField._calculate(
_DesignMethod.wrappedInSafeAreaStatusBarHeight, metrics, ifAbsent);
}
double navigationBarHeight(double navigationBarHeight) {
return DesignField._calculate(_DesignMethod.navigationBarHeight, metrics, navigationBarHeight);
}
double relativeWidthRatio(double width, double ratio) {
return metrics.wScale * width * ratio;
}
double relativeHeightRatio(double height, double ratio) {
return metrics.hScale * height * ratio;
}
Rect fromLTWH(double left, double top, double width, double height) {
return Rect.fromLTWH(left * metrics.wScale, top * metrics.hScale, width * metrics.wScale,
height * metrics.hScale);
}
Rect fromLTRB(double left, double top, double right, double bottom) {
return Rect.fromLTRB(left * metrics.wScale, top * metrics.hScale, right * metrics.wScale,
bottom * metrics.hScale);
}
}