Maruf Hassan
Maruf Hassan

Reputation: 1248

How to use SizeConfig in ThemeData in Flutter

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.

Upvotes: 0

Views: 3526

Answers (1)

Pathik Patel
Pathik Patel

Reputation: 1490

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.

Upvotes: 0

Related Questions