【问题标题】:How To Do Dynamic Font Size According to ScreenWidth When Specifying FontSize In ThemeData?ThemeData中指定FontSize时如何根据ScreenWidth做动态字体大小?
【发布时间】:2020-12-10 10:27:34
【问题描述】:

我需要根据用户屏幕的宽度更改字体大小。为此,我使用了一个 size_config.dart 文件,其中包含 getProportionateScreenWidth() 方法来检索用户屏幕宽度并进行一些计算。

因为我想要一个明暗的 UI,所以我创建了两个 ThemeData 类,并决定在其中执行所有 TextStyles。我现在的问题是,当我尝试调用该方法来设置字体大小时,我得到一个 NoSuchMethodError: The method 'toDouble' was called on null。想必是因为 ThemeData 是在应用启动之前计算出来的吧?因此没有可以使用的屏幕宽度,所以我得到一个错误。有没有简单的解决方法?

//size_config.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;
  }
}

double getProportionateScreenWidth(double inputWidth) {
  double screenWidth = SizeConfig.screenWidth;
  // 375 is the layout width that designer use
  return (inputWidth / 375.0) * screenWidth;
}
//themes.dart
ThemeData lightTheme() {
  return ThemeData (
    textTheme: lightTextTheme()
    //and other theme stuff
  );
}

TextTheme textTheme() {
  return TextTheme(
      headline1: TextStyle(
          color: Color(0xFF000000),
          fontSize: getProportionateScreenWidth(25), //problem is with here i believe
          fontWeight: FontWeight.normal),
  );
}
//main.dart
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: lightTheme(), //instantiating theme
      initialRoute: '/onboarding',
      routes: {
        '/onboarding': (context) => OnboardingScreen(),
        '/home': (context) => HomeScreen(),
        '/assistant': (context) => AssistantScreen(),
      },
    );
  }
}
//body.dart (where headline1 is being used) don't believe problem is here as this is not even rendered in upon start of the app (an onBoarding screen comes before it named routing is used to navigate the separate screens)
Text(
  'Hello,',
  textAlign: TextAlign.left,
  style: Theme.of(context).textTheme.headline1,
),
//Error message
════════ Exception caught by widgets library ═══════════════════════════════════
The following NoSuchMethodError was thrown building MyApp(dirty):
The method 'toDouble' was called on null.
Receiver: null
Tried calling: toDouble()

The relevant error-causing widget was
    MyApp 
package:dash/main.dart:17
When the exception was thrown, this was the stack
#0      Object.noSuchMethod  (dart:core-patch/object_patch.dart:51:5)
#1      double.*  (dart:core-patch/double.dart:36:23)
#2      getProportionateScreenWidth 
package:dash/size_config.dart:29
#3      textTheme 
package:dash/themes.dart:35
#4      lightTheme 
package:dash/themes.dart:11
...
════════════════════════════════════════════════════════════════════════════════

非常感谢您的帮助!

【问题讨论】:

  • 为什么不使用 AutoSizeText 包?它如此快速高效,我可以轻松替换文本小部件。
  • 我已经用文本小部件设计了它,我宁愿在重做之前看看是否有一个简单的解决方案可以解决我当前的问题。
  • AutoSizeText 就像用 AutoSizeText() 替换 Text() 一样简单。如果你真的不想用,没关系。

标签: flutter dart flutter-test


【解决方案1】:

我为此使用媒体查询使用 MediaQuery.of(context).size.height/100 * 5,我首先将设备高度转换为百分比并将其乘以某个数字。您也可以这样做,并且可以为维度创建一个单独的类。我的维度类看起来像这样。

class Dimensions {
  static double boxWidth;
  static double boxHeight;

  Dimensions(context) {
    boxHeight = MediaQuery.of(context).size.height / 100;
    boxWidth = MediaQuery.of(context).size.width / 100;
  }
}

然后我可以调用Dimensions.box height *(某人)来设置任何动态变化的约束,但请记住在任何构建方法之前初始化这个维度类。
如下所示。

  @override
  Widget build(BuildContext context) {
    Dimensions(context);   //initializing context
    return Material(
      child: Center(
        child: Text(
          "This is Splash Screen",
          style: TextStyle(fontSize: Dimensions.boxHeight * 5), //Using dynamic sizing.
        ),
      ),
    );
  }

【讨论】:

  • 我在 size_config.dart 文件中也使用了媒体查询,只是之前没有包含它。我将那部分添加到我的代码中,您可以看看吗?
  • 你初始化你的上下文了吗,你必须在 MaterialApp 之前初始化它,就在 Build Method 下面看我上面的代码?
  • 你可以复制粘贴我上面的代码,或者尝试在构造函数中初始化你的静态变量,如果它不能在外面初始化。您可以查看我的代码,它非常简单,并且可以很好地与方向配合使用,因为它初始化自身,因为媒体查询是一个继承的小部件,因此它将根据屏幕高度进行缩放,
  • 我尝试在我的代码中实现您的代码,但它说上下文不包含 MediaQuery。知道为什么会这样吗?
  • 实际上我尝试了相同的方法,我们无法在 MAterial App 内的材料应用程序之前访问上下文,但现在可能有一种方法,但现在,您可以直接使用我的类,只需使用这些尺寸来初始化您的字体大小(我试过后帧回调我没有工作所以......)。
【解决方案2】:

你也可以查看这个包flutter_screenutil

一个调整屏幕和字体大小的颤振插件。保证在不同的模型上看起来不错

一个调整屏幕和字体大小的flutter插件。让你的UI在不同的屏幕大小上显示合理的布局!

他们仍在不断开发它,它非常易于使用。

【讨论】:

    【解决方案3】:
    //main.dart
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
       
         SizeConfig().init(context); // add this line for initialization
    
        return MaterialApp(
          title: 'Flutter Demo',
          theme: lightTheme(), //instantiating theme
          initialRoute: '/onboarding',
          routes: {
            '/onboarding': (context) => OnboardingScreen(),
            '/home': (context) => HomeScreen(),
            '/assistant': (context) => AssistantScreen(),
          },
        );
      }
    }
    

    【讨论】:

    • 您能否为您的答案添加一些解释以提供上下文?
    猜你喜欢
    • 1970-01-01
    • 2015-09-09
    • 2020-12-07
    • 2016-09-17
    • 2017-06-29
    • 1970-01-01
    • 2014-09-04
    • 1970-01-01
    • 2016-09-24
    相关资源
    最近更新 更多