/// 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; const _DeviceMetrics(this.wScale, this.hScale, this.size, this.direction, {this.offset = Offset.zero}); } enum DesignFit { fitWidth, fitHeight, fill } enum _DesignMethod { width, height, average, fontSize, absoluteFontSize, widthScale, heightScale, combine, origin, statusBarHeight, wrappedInSafeAreaStatusBarHeight, navigationBarHeight, wrappedInSafeAreaNavigationBarHeight } class DesignMetrics { Size designResolution = Size.zero; final List objects = []; late Size measuredSize; static Map 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); DesignMetrics.dynamic() : 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); 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 / 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); } }