How to use SizeConfig in ThemeData in Flutter

0

To create responsive apps in Flutter, I use size_configs.dart file which handles the responsiveness of the code in different screens. I inject the SizeConfigs().init(context); below the MyApp root widget to make the app responsive. The init method takes in a context to scale the width, height and fontSize. I created functions as well so that I can put the exact values of fonts which I get from Figma designs instead of percentage like in the Sizer package.

The getFont(), getHeight(), getWidth() function take in a double and create responsive size for the text according to the screen.

size_configs.dart

import 'package:flutter/material.dart';

class SizeConfigs {
  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;
    // On iPhone 11 the defaultSize = 10 almost
    // So if the screen size increase or decrease then our defaultSize also vary
    defaultSize = orientation == Orientation.landscape
        ? screenHeight * 0.024
        : screenWidth * 0.024;
  }
}

double getFont(double size) {
  double defaultsSize = SizeConfigs.defaultSize * size;
  return (defaultsSize / 10);
}

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

// Get the proportionate width as per screen size
double getWidth(double inputWidth) {
  double screenWidth = SizeConfigs.screenWidth;
  // 375 is the layout width that Figma provides
  return (inputWidth / 375.0) * screenWidth;
}

I also have an app_theme.dart file where I store the ThemeData that I use in my app.

app_theme.dart

class AppTheme {
  //Light Theme Colors
  static Color lightBackgroundColor = const Color(0xffFFFFFF);
  static Color lightPrimaryColor = const Color(0xffF5E8EA);
  static Color lightSecondaryColor = const Color(0xff192533);
  static Color iconColor = const Color(0xffEEF0EB);

  ///Light Theme configuration
  static final lightTheme = ThemeData(
    textTheme: lightTextTheme,
    brightness: Brightness.light,
    backgroundColor: lightBackgroundColor,
    primaryColorLight: lightPrimaryColor,
    accentColor: lightSecondaryColor,
    selectedRowColor: tertiaryColor,
    unselectedWidgetColor: iconColor,
    toggleButtonsTheme:
        ToggleButtonsThemeData(color: tertiaryColor, disabledColor: iconColor),
    //buttonTheme: ButtonThemeData(buttonColor: tertiaryColor),
    toggleableActiveColor: tertiaryColor,
    visualDensity: VisualDensity.adaptivePlatformDensity,
  );
  ///Light TextTheme configuration
  static final TextTheme lightTextTheme = TextTheme(
    headline4: _mainTitle,
    headline5: _title,
    subtitle1: _subtitle,
    bodyText1: _body,
    bodyText2: _detail,
  );
  /// Main Title
  static final TextStyle _mainTitle = TextStyle(
    fontFamily: "RedHatDisplay-Black",
    fontSize: 36,
  );

  /// Title
  static final TextStyle _title = TextStyle(
    fontFamily: "RedHatDisplay-Bold",
    fontSize: 28,
  );

  /// Subtitle
  static final TextStyle _subtitle = TextStyle(
    fontFamily: "RedHatDisplay-Medium",
    fontSize: 18,
  );

  /// Body
  static final TextStyle _body = TextStyle(
    fontFamily: "RedHatDisplay-Regular",
    fontSize: 16,
  );

  /// Detail
  static final TextStyle _detail = TextStyle(
    fontFamily: "RedHatDisplay-Regular",
    fontSize: 14,
  );
}

The problem lies here. ThemeData doesn't have a BuildContext, so MediaQuery doesn't work in it, thus I can't call my getFont() function inside the fontSize parameter of the TextStyle.

What I do is use the copyWith method and override the fontSize property with the function.

     Text(
            'HomeScreen',
            style: Theme.of(context).textTheme.headline4.copyWith(fontSize: getFont(18)),
          ),

I want to just use the Theme.of(context).headline4 wherever I need them and its font should act as responsively and TextStyle should be able to take my getFont() function.

  static final TextStyle _mainTitle = TextStyle(
    fontFamily: "RedHatDisplay-Black",
   //This should take in the getFont function from the SizeConfigs.
    fontSize: getFont(36),
  );

TL;DR - I want a way to pass MediQuery data(SizeConfigs) which works with BuildContext to ThemeData which does not have a BuildContext.

flutter
dart
flutter-layout
responsiveness
asked on Stack Overflow Apr 14, 2021 by Maruf Hassan

1 Answer

0

Some of the properties require context to obtain their values.
To use such properties globally (without providing context),

  • In your initial widget (or builder) set screen-height, screen-width, etc values globally from build method.
  • Separate getFont function from SizeConfig, make it accessible globally, replace SizeConfig.* with those parameters which made global.

Once you set these parameters globally, you don't need to pass context at any point.

answered on Stack Overflow Apr 15, 2021 by Pathik Patel

User contributions licensed under CC BY-SA 3.0