device.dart 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. import 'dart:io';
  2. import 'dart:math';
  3. import 'dart:ui';
  4. import 'package:device_info_plus/device_info_plus.dart';
  5. import 'package:flutter/material.dart';
  6. import 'package:logging/logging.dart';
  7. class Device {
  8. final Logger _log = Logger('Device');
  9. final Directory baseDir;
  10. Device(this.context, this.baseDir);
  11. AndroidDeviceInfo? androidDeviceInfo;
  12. /// 获取平台性能
  13. int get androidSdkInt => androidDeviceInfo != null ? androidDeviceInfo!.version.sdkInt : 100;
  14. bool get isOldAndroid => androidSdkInt < 26; // 安卓8以下
  15. bool get isLowRamDevice => androidDeviceInfo != null ? androidDeviceInfo!.isLowRamDevice : false;
  16. bool get isLowEndDevice => Platform.numberOfProcessors <= 1 || isOldAndroid || isLowRamDevice;
  17. static double get devPixelRatio => PlatformDispatcher.instance.views.first.devicePixelRatio;
  18. static Size get physicalSize => PlatformDispatcher.instance.views.first.physicalSize;
  19. static Size get logicalSize => physicalSize / devPixelRatio;
  20. ///final Size screenSize;
  21. final BuildContext context;
  22. final aspectRatio = 3.0 / 2.0; // 图片宽高比按照 2 / 3 设定,相应的 board play 区域也是这个比例
  23. final _tabletProfile = DeviceProfile(horizontalPadding: 20, verticalPadding: 10);
  24. final _profile = DeviceProfile(horizontalPadding: 10, verticalPadding: 10);
  25. double _bannerHeight = 0;
  26. int get previewImageSize => (boardSize.shortestSide * devicePixelRatio).toInt();
  27. set bannerHeight(double height) {
  28. _bannerHeight = height;
  29. }
  30. /// 获取当前配置
  31. DeviceProfile get profile => isTablet ? _tabletProfile : _profile;
  32. /// 屏幕尺寸
  33. Size get screenSize => MediaQuery.of(context).size;
  34. /// 像素密度
  35. double get devicePixelRatio => isLowEndDevice ? 1 : MediaQuery.of(context).devicePixelRatio;
  36. double get dpi => devicePixelRatio * 160;
  37. /// safeArea高度 Z
  38. double get safeAreaHeight => MediaQuery.of(context).viewPadding.top + MediaQuery.of(context).viewPadding.bottom;
  39. /// 获取appbar的高度
  40. double get appBarHeight => AppBar().preferredSize.height;
  41. /// Play 尺寸
  42. Size get boardSize =>
  43. Size(screenSize.width - profile.horizontalPadding * 2, screenSize.height - (safeAreaHeight + appBarHeight + profile.verticalPadding * 2));
  44. /// 根据谷歌的描述,banner尺寸最小50px, 最大不超过15%
  45. double get estimateBannerHeight => max(50, screenSize.height * 0.15).truncateToDouble();
  46. double get bannerHeight => _bannerHeight == 0 ? estimateBannerHeight : _bannerHeight;
  47. /// 是否平板
  48. bool get isTablet => screenSize.shortestSide >= 600;
  49. String filePath(String relativePath) => '${baseDir.path}/$relativePath';
  50. // board核心绘制区域
  51. Rect get targetRect {
  52. final double appBarHeight = AppBar().preferredSize.height + MediaQuery.of(context).padding.top;
  53. const double bannerHeight = 50.0;
  54. final double availableHeight = screenSize.height - appBarHeight - bannerHeight;
  55. final double paddedWidth = screenSize.width - 2 * profile.horizontalPadding;
  56. final double paddedHeight = availableHeight - 2 * profile.verticalPadding;
  57. final double targetWidth = paddedWidth;
  58. final double targetHeight = targetWidth * aspectRatio;
  59. final double finalPuzzleWidth;
  60. final double finalPuzzleHeight;
  61. if (targetHeight > paddedHeight) {
  62. finalPuzzleHeight = paddedHeight;
  63. finalPuzzleWidth = paddedHeight / aspectRatio;
  64. } else {
  65. finalPuzzleWidth = targetWidth;
  66. finalPuzzleHeight = targetHeight;
  67. }
  68. final double targetYStart = appBarHeight + profile.verticalPadding + (paddedHeight - finalPuzzleHeight) / 2;
  69. final double targetXStart = profile.horizontalPadding + (paddedWidth - finalPuzzleWidth) / 2;
  70. final newTargetRect = Rect.fromLTWH(targetXStart, targetYStart, finalPuzzleWidth, finalPuzzleHeight);
  71. return newTargetRect;
  72. }
  73. // 最佳图片分辨率
  74. Size get bestImageSize => Size(targetRect.width * devPixelRatio, targetRect.height * devPixelRatio);
  75. }
  76. class DeviceProfile {
  77. final double horizontalPadding; // 水平padding
  78. final double verticalPadding; // 垂直padding
  79. DeviceProfile({
  80. this.horizontalPadding = 10,
  81. this.verticalPadding = 10, //Play board padding
  82. });
  83. }