在Flutter中,在没有BuildContext的类中获取屏幕大小

22

我正在尝试在Flutter中获取屏幕大小,但是我的自定义类中没有build方法。如何在不使用BuildContext类的情况下获取屏幕大小?

以下是代码:

class ShapesPainter extends CustomPainter {
  @override
  void paint(Canvas canvas, Size size) {

    BuildContext context;
    double width = MediaQuery.of(context).size.width;
    double height = MediaQuery.of(context).size.height;
    final paint = Paint();

    paint.color = Colors.deepOrange;

    var center = Offset(size.width / 2, size.height / 2);

    print(height);
    print(width);

    Rect rect = Rect.fromLTWH(0.0, 0.0, width, height);
    canvas.drawRect(rect, paint);
  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) {
    return false;
  }
}

出现以下错误:

在绘制时抛出了以下断言: 'package:flutter/src/widgets/media_query.dart': Failed assertion: line 689 pos 12: 'context != null': is not true.

6个回答

56

使用

MediaQueryData.fromWindow(WidgetsBinding.instance.window);

你可以使用它来获取MediaQuery而无需上下文, 它依赖于窗口实例来获取大小信息。


6
这是本页面唯一正确回答原问题的答案。 - Stevey
一个值可能为“null”的表达式在被取消引用之前必须进行空值检查。 这是我使用它时遇到的错误,有人能帮忙吗! - Apoorv pandey
3
只需在其中添加一个感叹号,并告诉编译器你知道自己在做什么,就像这样:MediaQueryData.fromWindow(WidgetsBinding.instance!.window) - Klemen Tusar
1
哇,非常好。我可以通过以下方式访问我的 heightMediaQueryData.fromWindow(WidgetsBinding.instance.window).size.width.toInt()。谢谢! - Felipe Sales
'MediaQueryData.fromWindow'已被弃用,不应再使用。请改用MediaQueryData.fromView。 - Nikhil kumar
显示剩余2条评论

16
截止到2023年5月,在Flutter 3.10.1中,MediaQueryData.fromWindow()已被弃用。现在请使用WidgetsBinding.instance.platformDispatcher.views.first.physicalSize.width。将width替换为height即可获取屏幕的高度。

5

如果您只需要屏幕的宽度和高度作为小部件ShapesPainter的参数,那么您可以直接将其传递。

解决方案代码:

class ShapesPainter extends CustomPainter {

  final double width;
  final double height;

  ShapesPainter({this.width,this.height});

  @override
  void paint(Canvas canvas, Size size) {

    final paint = Paint();

    paint.color = Colors.deepOrange;

    var center = Offset(size.width / 2, size.height / 2);

    print(height);
    print(width);

    Rect rect = Rect.fromLTWH(0.0, 0.0, width, height);
    canvas.drawRect(rect, paint);
  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) {
    return false;
  }
}

使用方法:

// Wherever you'll be using it
ShapesPainter(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
)

2
如果你愿意,甚至可以使用 double.infinity - Son of Stackoverflow

2

为了完成 @MohammadKhanAwan 的回答,

WidgetsBinding.instance.platformDispatcher.views.first.physicalSize.width 返回分辨率(例如:1080 / 2400),以获取与 MediaQuery.of(context).size 相同的值

您需要按以下方式除以像素比例

mixin Responsive {
  final double widthScreen = WidgetsBinding
          .instance.platformDispatcher.views.first.physicalSize.width /
      WidgetsBinding.instance.platformDispatcher.views.first.devicePixelRatio;
  
final double heightScreen = WidgetsBinding
              .instance.platformDispatcher.views.first.physicalSize.height /
          WidgetsBinding.instance.platformDispatcher.views.first.devicePixelRatio;
    }

1
我之前使用了window单例来获取屏幕的宽度和高度。
double width = (window.physicalSize.shortestSide / window.devicePixelRatio);
double height = (window.physicalSize.longestSide / window.devicePixelRatio);

但是它已被弃用, 因此也包括MediaQueryData.fromWindow() (来自接受的答案)。
解决方案 FlutterView.physicalSize给你
矩形的尺寸,这个视图中渲染的场景将在屏幕上绘制,以物理像素为单位。 FlutterView.devicePixelRatio给你
每个逻辑像素对应的设备像素数,用于显示该视图的屏幕。
通过使用以下代码片段,您可以获取实际的逻辑屏幕宽度和高度:
FlutterView view = PlatformDispatcher.instance.views.first;

double physicalWidth = view.physicalSize.width;
double physicalHeight = view.physicalSize.height;

double devicePixelRatio = view.devicePixelRatio;

double screenWidth = physicalWidth / devicePixelRatio;
double screenHeight = physicalHeight / devicePixelRatio;

-4
以以下方式,您可以在不在构建方法中声明它们的情况下获取设备屏幕尺寸。
  void paint(BuildContext context)
{
  double width = MediaQuery.of(context).size.width;
  double height = MediaQuery.of(context).size.height;
}

在导入此方法后,您可以在其他文件的构建方法中访问它们。

paint(context)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接