Exception when trying to get the Proportionate Screen Width/Height using MediaQuery.of(context)

Viewed 1068

I am trying to get the proportionate height/width as per screen size from the size_config.dart file. this is implemented using the getProportionateScreenHeight and getProportionateScreenWidth functions.

I am using this in the Sizedbox in the body.dart to get the height as per the screen size.

But I am getting the following exception when I tried to run the code.

What am I doing incorrectly? And how can I fixed it?

════════ Exception caught by widgets library ═══════════════════════════════════════════════════════
The following NoSuchMethodError was thrown building Body(dirty):
The method 'toDouble' was called on null.
Receiver: null
Tried calling: toDouble()

size_config.dart:

import 'package:flutter/material.dart';

class SizeConfig {
  static MediaQueryData _mediaQueryData;
  static double screenWidth;
  static double screenHeight;
  static double defaultSize;
  static Orientation orientation;

  void init(BuildContext context) {
    _mediaQueryData = MediaQuery.of(context);
    screenWidth = _mediaQueryData.size.width;
    screenHeight = _mediaQueryData.size.height;
    orientation = _mediaQueryData.orientation;
  }
}

// Get the proportionate height as per screen size
double getProportionateScreenHeight(double inputHeight) {
  double screenHeight = SizeConfig.screenHeight;
  // 812 is the layout height that designer use
  return (inputHeight / 812.0) * screenHeight;
}

// Get the proportionate height as per screen size
double getProportionateScreenWidth(double inputWidth) {
  double screenWidth = SizeConfig.screenWidth;
  // 375 is the layout width that designer use
  return (inputWidth / 315.0) * screenWidth;
}

body.dart

import 'package:flutter/material.dart';
import 'size_config.dart';

class Body extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: Padding(
        padding: EdgeInsets.only(left: 28.0),
        child: SingleChildScrollView(
          child: Column(
            children: [
              SizedBox(height: getProportionateScreenHeight(20)),
              Text(
                'Welcome, Jack',
                style: TextStyle(
                  fontSize: 32.0,
                  color: Colors.black,
                  fontWeight: FontWeight.bold,
                ),
              ),
              SizedBox(height: getProportionateScreenHeight(28)),
              Text(
                'Welcome, Jack',
                style: TextStyle(
                  fontSize: 32.0,
                  color: Colors.black,
                  fontWeight: FontWeight.bold,
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}
2 Answers

That's because you forgot to initialise your init method. Here's what you need to do:

class Body extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // Add this line
    SizeConfig().init(context);

    return SafeArea(...);
  }
}

It almost looks like you should use SizeConfig as a singleton, but you can't because orientation and _mediaQueryData fields can change. It's redundant to create a class which in fact duplicates informations from MediaQueryData (MediaQuery.of(context)). The best option is to remove SizeConfig completely and use extension (possible since Dart 2.7) instead:

extension MediaQueryDataProportionate on MediaQueryData {
  /// 812 is the layout height that designer use
  static const double layoutHeight = 812.0;

  /// 375 is the layout width that designer use
  static const double layoutWidth = 315.0;

  /// Get the proportionate height as per screen size.
  double getProportionateScreenHeight(double inputHeight) =>
      (inputHeight / layoutHeight) * size.height;

  /// Get the proportionate height as per screen size.
  double getProportionateScreenWidth(double inputWidth) =>
      (inputWidth / layoutWidth) * size.width;
}

After importing this extension you can use it as below:

MediaQuery.of(context).getProportionateScreenHeight(20)
Related