[dart] 다른 화면 크기에 따라 Flutter 앱이 반응하도록 만드는 방법은 무엇입니까?

다양한 화면 크기에 따라 반응하는 데 어려움이 있습니다. 반응 형으로 만드는 방법?

@override
       Widget build(BuildContext context) {
       return new Container(
       decoration: new BoxDecoration(color: Colors.white),
       child: new Stack(
        children: [
          new Padding(
            padding: const EdgeInsets.only(bottom: 350.0),
            child: new GradientAppBar(" "),
          ),
          new Positioned(
            bottom: 150.0,
            height: 260.0,
            left: 10.0,
            right: 10.0,
            child: new Padding(
              padding: new EdgeInsets.all(10.0),
              child: new Card(
                child: new Column(
                  mainAxisSize: MainAxisSize.min,
                  children: <Widget>[
                    const ListTile(
                      title: const Text(
                        'LOGIN',
                        textAlign: TextAlign.center,
                        style: const TextStyle(
                          fontSize: 16.50,
                          fontFamily: "Helvetica",
                          fontWeight: FontWeight.bold,
                          color: Colors.black87,
                          letterSpacing: 1.00,
                        ),
                      ),
                    ),
                    new ListTile(
                      leading: const Icon(Icons.person),
                      title: new TextField(
                        controller: _user1,
                        decoration: new InputDecoration(
                            labelText: '     Enter a username'),
                      ),
                    ),
                    new ListTile(
                      leading: const Icon(Icons.person_pin),
                      title: new TextField(
                        controller: _pass1,
                        decoration: new InputDecoration(
                            labelText: '     Enter a password'),
                        obscureText: true,
                      ),
                    ),
                  ],
                ),
              ),
            ),
          ),
          new Positioned(
            bottom: 70.0,
            left: 15.0,
            right: 05.0,
            child: new ButtonTheme.bar(
            // make buttons use the appropriate styles for cards
              child: new ButtonBar(
                children: <Widget>[
                  new FlatButton(
                    padding: new EdgeInsets.only(right: 13.0),
                    child: new Text(
                      'REGISTER HERE',
                      style: new TextStyle(
                          color: Colors.black87,
                          fontFamily: "Helvetica",
                          fontSize: 15.00,
                          fontWeight: FontWeight.bold),
                    ),
                    onPressed: () {
                      Navigator.of(context).pushNamed('/facebook');
                    },
                  ),
                  new FlatButton(
                    padding: new EdgeInsets.only(right: 22.0),
                    child: new Text(
                      'FORGOT PASSWORD?',
                      style: new TextStyle(
                          color: Colors.black87,
                          fontFamily: "Helvetica",
                          fontSize: 15.00,
                          fontWeight: FontWeight.bold),
                    ),
                    onPressed: () {
                      Navigator.of(context).pushNamed('/Forgot');
                    },
                  ),
                ],
              ),
            ),
          ),
          new Positioned(
            bottom: 73.0,
            height: 180.0,
            left: 20.0,
            right: 52.0,
            child: new Padding(
              padding: new EdgeInsets.all(0.00),
              child: new ButtonTheme(
                minWidth: 10.0,
                height: 20.0,
                padding: new EdgeInsets.only(right: 37.0),
                child: new ButtonBar(children: <Widget>[
                  new CupertinoButton(
                      borderRadius:
                          const BorderRadius.all(const Radius.circular(36.0)),
                      padding: new EdgeInsets.only(left: 70.0),
                      color: const Color(0xFF426DB7),
                      child: new Text(
                        "     LOGIN                            ",
                        style: new TextStyle(
                            color: Colors.white,
                            fontSize: 12.50,
                            fontFamily: "Handwriting",
                            fontWeight: FontWeight.w500,
                            letterSpacing: 0.00),
                      ),
                      onPressed: () {})
                ]),
              ),
            ),
          ),
        ],
      ),
    );
  }
}



답변

MediaQuery수업 사용 :

MediaQueryData queryData;
queryData = MediaQuery.of(context);

MediaQuery : 미디어 쿼리가 주어진 데이터로 확인되는 하위 트리를 설정합니다.

MediaQueryData : 미디어 (예 : 창)에 대한 정보.

장치 픽셀 비율을 얻으려면 :

queryData.devicePixelRatio

장치 화면의 너비와 높이를 가져 오려면 :

queryData.size.width
queryData.size.height

텍스트 축척 비율을 얻으려면 :

queryData.textScaleFactor

AspectRatio수업 사용 :

문서에서 :

특정 종횡비로 자식 크기를 조정하는 위젯입니다.

위젯은 먼저 레이아웃 제약에서 허용하는 가장 큰 너비를 시도합니다. 위젯의 높이는 너비와 높이의 비율로 표현되는 너비에 주어진 가로 세로 비율을 적용하여 결정됩니다.

예를 들어 16 : 9 너비 : 높이 종횡비의 값은 16.0 / 9.0입니다. 최대 너비가 무한한 경우 최대 높이에 종횡비를 적용하여 초기 너비가 결정됩니다.

이제 두 번째 예를 살펴 보겠습니다. 이번에는 가로 세로 비율이 2.0이고 너비가 0.0에서 100.0 사이 여야하고 높이가 0.0에서 100.0 사이 여야하는 레이아웃 제약 조건이 있습니다. 너비 100.0 (허용되는 최대 값)과 높이 50.0 (가로 세로 비율 일치)을 선택합니다.

//example
new Center(
 child: new AspectRatio(
  aspectRatio: 100 / 100,
  child: new Container(
    decoration: new BoxDecoration(
      shape: BoxShape.rectangle,
      color: Colors.orange,
      )
    ),
  ),
),

또한 다음을 사용할 수 있습니다 .


답변

이 클래스는 init 메서드를 사용하여 클래스를 돕고 초기화합니다.

import 'package:flutter/widgets.dart';

class SizeConfig {
  static MediaQueryData _mediaQueryData;
  static double screenWidth;
  static double screenHeight;
  static double blockSizeHorizontal;
  static double blockSizeVertical;
  static double _safeAreaHorizontal;
  static double _safeAreaVertical;
  static double safeBlockHorizontal;
  static double safeBlockVertical;

  void init(BuildContext context){
    _mediaQueryData = MediaQuery.of(context);
    screenWidth = _mediaQueryData.size.width;
    screenHeight = _mediaQueryData.size.height;
    blockSizeHorizontal = screenWidth/100;
    blockSizeVertical = screenHeight/100;
    _safeAreaHorizontal = _mediaQueryData.padding.left +
        _mediaQueryData.padding.right;
    _safeAreaVertical = _mediaQueryData.padding.top +
        _mediaQueryData.padding.bottom;
    safeBlockHorizontal = (screenWidth - _safeAreaHorizontal)/100;
    safeBlockVertical = (screenHeight - _safeAreaVertical)/100;
  }
}

그런 다음 위젯 차원에서 다음을 수행하십시오.

Widget build(BuildContext context) {
    SizeConfig().init(context);
    return Container(
    height: SizeConfig.safeBlockVertical * 10, //10 for example
    width: SizeConfig.safeBlockHorizontal * 10, //10 for example
    );}

이 게시물 작성자의 모든 크레딧 :
https://medium.com/flutter-community/flutter-effectively-scale-ui-according-to-different-screen-sizes-2cb7c115ea0a


답변

내가하는 일은 화면 너비와 높이를 가져 와서 100 * 100 그리드를 계산하여 사물을 배치하고 크기를 조정하고 재사용 할 수있는 정적 변수로 저장하는 것입니다. 대부분의 경우 아주 잘 작동합니다. 이렇게 :

AppConfig.width = MediaQuery.of(context).size.width;
AppConfig.height = MediaQuery.of(context).size.height;
AppConfig.blockSize = AppConfig.width / 100;
AppConfig.blockSizeVertical = AppConfig.height / 100;

그런 다음 다음과 같이 이러한 값에 따라 모든 크기를 조정합니다.

double elementWidth = AppConfig.blockSize * 10.0;   // 10% of the screen width

또는

double fontSize = AppConfig.blockSize * 1.2;

때로는 안전 영역 (노치 등)이 레이아웃을 죽이기 때문에 다음 사항도 고려할 수 있습니다.

AppConfig.safeAreaHorizontal = MediaQuery.of(context).padding.left +
    MediaQuery.of(context).padding.right;

double screenWidthWithoutSafeArea = AppConfig.width - AppConfig.safeAreaHorizontal;

이것은 최근의 일부 프로젝트에서 훌륭하게 작동했습니다.


답변

MediaQuery수업 확인

예를 들어, 현재 미디어의 크기를 배울 수 (예를 들어 앱이 포함 된 창), 당신은 읽을 수 MediaQueryData.size로부터 재산 MediaQueryData에 의해 반환을 MediaQuery.of: MediaQuery.of(context).size.

따라서 다음을 수행 할 수 있습니다.

 new Container(
                      height: MediaQuery.of(context).size.height/2,
..            )


답변

스케일 크기에 대한 입력으로 너비 또는 높이의 백분율을 사용할 수 있습니다.

fontSize: MediaQuery.of(_ctxt).size.height * 0.065

끝에있는 승수에 활성 에뮬레이터에서 텍스트를보기 좋게 만드는 값이 있습니다.

아래는 조정 된 모든 차원이 한곳에 집중되도록 설정하는 방법입니다. 이렇게 Media.of()하면 코드 전체에서 호출 을 찾을 필요없이 Hot Reload를 사용하여 쉽고 빠르게 다시 실행할 수 있습니다 .

  1. 모든 매핑 appScale.dart 를 저장할 파일을 만듭니다.

    class AppScale {
      BuildContext _ctxt;

      AppScale(this._ctxt);

      double get labelDim => scaledWidth(.04);
      double get popupMenuButton => scaledHeight(.065);

      double scaledWidth(double widthScale) {
        return MediaQuery.of(_ctxt).size.width * widthScale;
      }

      double scaledHeight(double heightScale) {
        return MediaQuery.of(_ctxt).size.height * heightScale;
      }
    }

  1. 그런 다음 조정 된 값이 필요한 곳을 참조하십시오.

    AppScale _scale = AppScale(context);

    // ... 

    Widget label1 = Text(
      "Some Label",
      style: TextStyle(fontSize: _scale.labelDim),
    );

이 게시물의 답변에 감사드립니다.


답변

나는 다른 사람들의 (@datayeah & Vithani Ravi) 솔루션을 여기에서 조금 어렵게 노크하고 있었기 때문에,이 가변 화면 밀도 스케일링 문제를 해결하기위한 내 자신의 시도를 공유하거나 닥쳐 버릴 것이라고 생각했습니다. 그래서 저는이 문제를 견고하고 고정 된 기초에서 접근합니다. 모든 스케일링은 2 : 1 (높이 : 너비)의 고정 (불변) 비율을 기준으로합니다. 내 앱에서 모든 무거운 작업 (및 유용한 코드 미세 조정)을 수행하는 도우미 클래스 “McGyver”가 있습니다. 이 “McGyver”클래스는 정적 메서드와 정적 상수 클래스 멤버 만 포함합니다.

비율 크기 조정 방법 : 2 : 1 가로 세로 비율을 기준으로 너비와 높이를 독립적으로 조정합니다. 너비 및 높이 입력 값을 가져와 각각 너비 및 높이 상수로 나누고 마지막으로 각 너비 및 높이 입력 값의 크기를 조정하는 조정 계수를 계산합니다. 실제 코드는 다음과 같습니다.

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

class McGyver {

  static const double _fixedWidth = 410;    // Set to an Aspect Ratio of 2:1 (height:width)
  static const double _fixedHeight = 820;   // Set to an Aspect Ratio of 2:1 (height:width) 

  // Useful rounding method (@andyw solution -> /programming/28419255/how-do-you-round-a-double-in-dart-to-a-given-degree-of-precision-after-the-decim/53500405#53500405)
  static double roundToDecimals(double val, int decimalPlaces){
    double mod = pow(10.0, decimalPlaces);
    return ((val * mod).round().toDouble() / mod);
  }

  // The 'Ratio-Scaled' Widget method (takes any generic widget and returns a "Ratio-Scaled Widget" - "rsWidget")
  static Widget rsWidget(BuildContext ctx, Widget inWidget, double percWidth, double percHeight) {

    // ---------------------------------------------------------------------------------------------- //
    // INFO: Ratio-Scaled "SizedBox" Widget - Scaling based on device's height & width at 2:1 ratio.  //
    // ---------------------------------------------------------------------------------------------- //

    final int _decPlaces = 5;
    final double _fixedWidth = McGyver._fixedWidth;
    final double _fixedHeight = McGyver._fixedHeight;

    Size _scrnSize = MediaQuery.of(ctx).size;                // Extracts Device Screen Parameters.
    double _scrnWidth = _scrnSize.width.floorToDouble();     // Extracts Device Screen maximum width.
    double _scrnHeight = _scrnSize.height.floorToDouble();   // Extracts Device Screen maximum height.

    double _rsWidth = 0;
    if (_scrnWidth == _fixedWidth) {   // If input width matches fixedWidth then do normal scaling.
      _rsWidth = McGyver.roundToDecimals((_scrnWidth * (percWidth / 100)), _decPlaces);
    } else {   // If input width !match fixedWidth then do adjustment factor scaling.
      double _scaleRatioWidth = McGyver.roundToDecimals((_scrnWidth / _fixedWidth), _decPlaces);
      double _scalerWidth = ((percWidth + log(percWidth + 1)) * pow(1, _scaleRatioWidth)) / 100;
      _rsWidth = McGyver.roundToDecimals((_scrnWidth * _scalerWidth), _decPlaces);
    }

    double _rsHeight = 0;
    if (_scrnHeight == _fixedHeight) {   // If input height matches fixedHeight then do normal scaling.
      _rsHeight = McGyver.roundToDecimals((_scrnHeight * (percHeight / 100)), _decPlaces);
    } else {   // If input height !match fixedHeight then do adjustment factor scaling.
      double _scaleRatioHeight = McGyver.roundToDecimals((_scrnHeight / _fixedHeight), _decPlaces);
      double _scalerHeight = ((percHeight + log(percHeight + 1)) * pow(1, _scaleRatioHeight)) / 100;
      _rsHeight = McGyver.roundToDecimals((_scrnHeight * _scalerHeight), _decPlaces);
    }

    // Finally, hand over Ratio-Scaled "SizedBox" widget to method call.
    return SizedBox(
      width: _rsWidth,
      height: _rsHeight,
      child: inWidget,
    );
  }

}

… … …

그런 다음 다음과 같이 “rsWidget ()”메서드에 대한 간단한 정적 호출을 사용하여 위젯을 개별적으로 확장 할 수 있습니다.

  // Step 1: Define your widget however you like (this widget will be supplied as the "inWidget" arg to the "rsWidget" method in Step 2)...
  Widget _btnLogin = RaisedButton(color: Colors.blue, elevation: 9.0,
                                  shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(McGyver.rsDouble(context, ScaleType.width, 2.5))),
                                  child: McGyver.rsText(context, "LOGIN", percFontSize: EzdFonts.button2_5, textColor: Colors.white, fWeight: FontWeight.bold),
                                  onPressed: () { _onTapBtnLogin(_tecUsrId.text, _tecUsrPass.text); }, );

  // Step 2: Scale your widget by calling the static "rsWidget" method...
  McGyver.rsWidget(context, _btnLogin, 34.5, 10.0)   // ...and Bob's your uncle!!

멋진 점은 “rsWidget ()”메서드가 위젯을 반환한다는 것입니다 !! 따라서 _rsBtnLogin모든 곳에서 사용 하기 위해 확장 된 위젯을 다른 변수에 할당 하거나 단순히 McGyver.rsWidget()내부에서 전체 메서드 호출을 사용할 수 있습니다.build() (위젯 트리에 배치하는 데 필요한 정확한 방법). 제대로 작동합니다.

더 기민한 코더를 위해 : 두 개의 추가 비율 조정 방법을 사용 McGyver.rsText()했고 McGyver.rsDouble()(위 코드에 정의되어 있지 않음) RaisedButton()내 앱에서 기본적으로이 스케일링 작업에 열광 한다는 사실을 알게 될 것입니다. 어떤 스케일이나 화면 밀도에서도 완벽한 픽셀 !! int, doubles, padding, text (장치 간 UI 일관성이 필요한 모든 것)의 비율을 조정합니다. 너비만을 기준으로 텍스트 크기를 조정하지만 다른 모든 크기 조정에 사용할 축을 지정합니다 ( 위 코드 예제에서 호출에 ScaleType.width사용 된 열거 형 으로 수행됨 McGyver.rsDouble()).

나는 이것이 미친 짓이라는 것을 알고 있으며 메인 스레드에서 할 일이 많지만 누군가가 여기에서 내 시도를보고 내 화면 밀도 1 : 1 스케일링에 대한 더 나은 (더 가벼운) 솔루션을 찾도록 도와주기를 바랍니다. 악몽.


답변

많은 연구와 테스트 끝에 현재 Android / iOS에서 Flutter로 변환중인 앱에 대한 솔루션을 개발했습니다.

Android와 iOS에서는 기본 글꼴 크기에 적용된 ‘Scaling Factor’를 사용하여 화면 크기에 상대적인 텍스트 크기를 렌더링했습니다.

이 문서는 매우 도움이되었다 : https://medium.com/flutter-community/flutter-effectively-scale-ui-according-to-different-screen-sizes-2cb7c115ea0a

Material Design 인쇄 스타일의 글꼴 크기를 얻기 위해 StatelessWidget을 만들었습니다. MediaQuery를 사용하여 장치 치수 가져 오기, 배율 계수 계산, 머티리얼 디자인 텍스트 크기 재설정. 위젯은 커스텀 머티리얼 디자인 테마를 정의하는 데 사용할 수 있습니다.

사용 된 에뮬레이터 :

  • Pixel C-9.94 인치 태블릿
  • Pixel 3-5.46 인치 휴대 전화
  • iPhone 11 Pro Max-5.8 형 휴대폰

표준 글꼴 크기

크기가 조정 된 글꼴

set_app_theme.dart (SetAppTheme 위젯)

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

class SetAppTheme extends StatelessWidget {

  final Widget child;

  SetAppTheme({this.child});

  @override
  Widget build(BuildContext context) {

    final _divisor = 400.0;

    final MediaQueryData _mediaQueryData = MediaQuery.of(context);

    final _screenWidth = _mediaQueryData.size.width;
    final _factorHorizontal = _screenWidth / _divisor;

    final _screenHeight = _mediaQueryData.size.height;
    final _factorVertical = _screenHeight / _divisor;

    final _textScalingFactor = min(_factorVertical, _factorHorizontal);

    final _safeAreaHorizontal = _mediaQueryData.padding.left + _mediaQueryData.padding.right;
    final _safeFactorHorizontal = (_screenWidth - _safeAreaHorizontal) / _divisor;

    final _safeAreaVertical = _mediaQueryData.padding.top + _mediaQueryData.padding.bottom;
    final _safeFactorVertical = (_screenHeight - _safeAreaVertical) / _divisor;

    final _safeAreaTextScalingFactor = min(_safeFactorHorizontal, _safeFactorHorizontal);

    print('Screen Scaling Values:' + '_screenWidth: $_screenWidth');
    print('Screen Scaling Values:' + '_factorHorizontal: $_factorHorizontal ');

    print('Screen Scaling Values:' + '_screenHeight: $_screenHeight');
    print('Screen Scaling Values:' + '_factorVertical: $_factorVertical ');

    print('_textScalingFactor: $_textScalingFactor ');

    print('Screen Scaling Values:' + '_safeAreaHorizontal: $_safeAreaHorizontal ');
    print('Screen Scaling Values:' + '_safeFactorHorizontal: $_safeFactorHorizontal ');

    print('Screen Scaling Values:' + '_safeAreaVertical: $_safeAreaVertical ');
    print('Screen Scaling Values:' + '_safeFactorVertical: $_safeFactorVertical ');

    print('_safeAreaTextScalingFactor: $_safeAreaTextScalingFactor ');

    print('Default Material Design Text Themes');
    print('display4: ${Theme.of(context).textTheme.display4}');
    print('display3: ${Theme.of(context).textTheme.display3}');
    print('display2: ${Theme.of(context).textTheme.display2}');
    print('display1: ${Theme.of(context).textTheme.display1}');
    print('headline: ${Theme.of(context).textTheme.headline}');
    print('title: ${Theme.of(context).textTheme.title}');
    print('subtitle: ${Theme.of(context).textTheme.subtitle}');
    print('body2: ${Theme.of(context).textTheme.body2}');
    print('body1: ${Theme.of(context).textTheme.body1}');
    print('caption: ${Theme.of(context).textTheme.caption}');
    print('button: ${Theme.of(context).textTheme.button}');

    TextScalingFactors _textScalingFactors = TextScalingFactors(
        display4ScaledSize: (Theme.of(context).textTheme.display4.fontSize * _safeAreaTextScalingFactor),
        display3ScaledSize: (Theme.of(context).textTheme.display3.fontSize * _safeAreaTextScalingFactor),
        display2ScaledSize: (Theme.of(context).textTheme.display2.fontSize * _safeAreaTextScalingFactor),
        display1ScaledSize: (Theme.of(context).textTheme.display1.fontSize * _safeAreaTextScalingFactor),
        headlineScaledSize: (Theme.of(context).textTheme.headline.fontSize * _safeAreaTextScalingFactor),
        titleScaledSize: (Theme.of(context).textTheme.title.fontSize * _safeAreaTextScalingFactor),
        subtitleScaledSize: (Theme.of(context).textTheme.subtitle.fontSize * _safeAreaTextScalingFactor),
        body2ScaledSize: (Theme.of(context).textTheme.body2.fontSize * _safeAreaTextScalingFactor),
        body1ScaledSize: (Theme.of(context).textTheme.body1.fontSize * _safeAreaTextScalingFactor),
        captionScaledSize: (Theme.of(context).textTheme.caption.fontSize * _safeAreaTextScalingFactor),
        buttonScaledSize: (Theme.of(context).textTheme.button.fontSize * _safeAreaTextScalingFactor));

    return Theme(
      child: child,
      data: _buildAppTheme(_textScalingFactors),
    );
  }
}

final ThemeData customTheme = ThemeData(
  primarySwatch: appColorSwatch,
  // fontFamily: x,
);

final MaterialColor appColorSwatch = MaterialColor(0xFF3787AD, appSwatchColors);

Map<int, Color> appSwatchColors =
{
  50  : Color(0xFFE3F5F8),
  100 : Color(0xFFB8E4ED),
  200 : Color(0xFF8DD3E3),
  300 : Color(0xFF6BC1D8),
  400 : Color(0xFF56B4D2),
  500 : Color(0xFF48A8CD),
  600 : Color(0xFF419ABF),
  700 : Color(0xFF3787AD),
  800 : Color(0xFF337799),
  900 : Color(0xFF285877),
};

_buildAppTheme (TextScalingFactors textScalingFactors) {

  return customTheme.copyWith(

    accentColor: appColorSwatch[300],
    buttonTheme: customTheme.buttonTheme.copyWith(buttonColor: Colors.grey[500],),
    cardColor: Colors.white,
    errorColor: Colors.red,
    inputDecorationTheme: InputDecorationTheme(border: OutlineInputBorder(),),
    primaryColor: appColorSwatch[700],
    primaryIconTheme: customTheme.iconTheme.copyWith(color: appColorSwatch),
    scaffoldBackgroundColor: Colors.grey[100],
    textSelectionColor: appColorSwatch[300],
    textTheme: _buildAppTextTheme(customTheme.textTheme, textScalingFactors),
    appBarTheme: customTheme.appBarTheme.copyWith(
        textTheme: _buildAppTextTheme(customTheme.textTheme, textScalingFactors)),

//    accentColorBrightness: ,
//    accentIconTheme: ,
//    accentTextTheme: ,
//    appBarTheme: ,
//    applyElevationOverlayColor: ,
//    backgroundColor: ,
//    bannerTheme: ,
//    bottomAppBarColor: ,
//    bottomAppBarTheme: ,
//    bottomSheetTheme: ,
//    brightness: ,
//    buttonBarTheme: ,
//    buttonColor: ,
//    canvasColor: ,
//    cardTheme: ,
//    chipTheme: ,
//    colorScheme: ,
//    cupertinoOverrideTheme: ,
//    cursorColor: ,
//    dialogBackgroundColor: ,
//    dialogTheme: ,
//    disabledColor: ,
//    dividerColor: ,
//    dividerTheme: ,
//    floatingActionButtonTheme: ,
//    focusColor: ,
//    highlightColor: ,
//    hintColor: ,
//    hoverColor: ,
//    iconTheme: ,
//    indicatorColor: ,
//    materialTapTargetSize: ,
//    pageTransitionsTheme: ,
//    platform: ,
//    popupMenuTheme: ,
//    primaryColorBrightness: ,
//    primaryColorDark: ,
//    primaryColorLight: ,
//    primaryTextTheme: ,
//    secondaryHeaderColor: ,
//    selectedRowColor: ,
//    sliderTheme: ,
//    snackBarTheme: ,
//    splashColor: ,
//    splashFactory: ,
//    tabBarTheme: ,
//    textSelectionHandleColor: ,
//    toggleableActiveColor: ,
//    toggleButtonsTheme: ,
//    tooltipTheme: ,
//    typography: ,
//    unselectedWidgetColor: ,
  );
}

class TextScalingFactors {

  final double display4ScaledSize;
  final double display3ScaledSize;
  final double display2ScaledSize;
  final double display1ScaledSize;
  final double headlineScaledSize;
  final double titleScaledSize;
  final double subtitleScaledSize;
  final double body2ScaledSize;
  final double body1ScaledSize;
  final double captionScaledSize;
  final double buttonScaledSize;

  TextScalingFactors({

    @required this.display4ScaledSize,
    @required this.display3ScaledSize,
    @required this.display2ScaledSize,
    @required this.display1ScaledSize,
    @required this.headlineScaledSize,
    @required this.titleScaledSize,
    @required this.subtitleScaledSize,
    @required this.body2ScaledSize,
    @required this.body1ScaledSize,
    @required this.captionScaledSize,
    @required this.buttonScaledSize
  });
}

TextTheme _buildAppTextTheme(

    TextTheme _customTextTheme,
    TextScalingFactors _scaledText) {

  return _customTextTheme.copyWith(

    display4: _customTextTheme.display4.copyWith(fontSize: _scaledText.display4ScaledSize),
    display3: _customTextTheme.display3.copyWith(fontSize: _scaledText.display3ScaledSize),
    display2: _customTextTheme.display2.copyWith(fontSize: _scaledText.display2ScaledSize),
    display1: _customTextTheme.display1.copyWith(fontSize: _scaledText.display1ScaledSize),
    headline: _customTextTheme.headline.copyWith(fontSize: _scaledText.headlineScaledSize),
    title: _customTextTheme.title.copyWith(fontSize: _scaledText.titleScaledSize),
    subtitle: _customTextTheme.subtitle.copyWith(fontSize: _scaledText.subtitleScaledSize),
    body2: _customTextTheme.body2.copyWith(fontSize: _scaledText.body2ScaledSize),
    body1: _customTextTheme.body1.copyWith(fontSize: _scaledText.body1ScaledSize),
    caption: _customTextTheme.caption.copyWith(fontSize: _scaledText.captionScaledSize),
    button: _customTextTheme.button.copyWith(fontSize: _scaledText.buttonScaledSize),

  ).apply(bodyColor: Colors.black);
}

main.dart (데모 앱)

import 'package:flutter/material.dart';
import 'package:scaling/set_app_theme.dart';


void main() => runApp(MyApp());


class MyApp extends StatelessWidget {

  @override
  Widget build(BuildContext context) {

    return MaterialApp(
      home: SetAppTheme(child: HomePage()),
    );
  }
}


class HomePage extends StatelessWidget {

  final demoText = '0123456789';

  @override
  Widget build(BuildContext context) {

    return SafeArea(
      child: Scaffold(
        appBar: AppBar(
          title: Text('Text Scaling with SetAppTheme',
            style: TextStyle(color: Colors.white),),
        ),
        body: SingleChildScrollView(
          child: Center(
            child: Padding(
              padding: const EdgeInsets.all(8.0),
              child: Column(
                children: <Widget>[
                  Text(
                    demoText,
                    style: TextStyle(
                      fontSize: Theme.of(context).textTheme.display4.fontSize,
                    ),
                  ),
                  Text(
                    demoText,
                    style: TextStyle(
                      fontSize: Theme.of(context).textTheme.display3.fontSize,
                    ),
                  ),
                  Text(
                    demoText,
                    style: TextStyle(
                      fontSize: Theme.of(context).textTheme.display2.fontSize,
                    ),
                  ),
                  Text(
                    demoText,
                    style: TextStyle(
                      fontSize: Theme.of(context).textTheme.display1.fontSize,
                    ),
                  ),
                  Text(
                    demoText,
                    style: TextStyle(
                      fontSize: Theme.of(context).textTheme.headline.fontSize,
                    ),
                  ),
                  Text(
                    demoText,
                    style: TextStyle(
                      fontSize: Theme.of(context).textTheme.title.fontSize,
                    ),
                  ),
                  Text(
                    demoText,
                    style: TextStyle(
                      fontSize: Theme.of(context).textTheme.subtitle.fontSize,
                    ),
                  ),
                  Text(
                    demoText,
                    style: TextStyle(
                      fontSize: Theme.of(context).textTheme.body2.fontSize,
                    ),
                  ),
                  Text(
                    demoText,
                    style: TextStyle(
                      fontSize: Theme.of(context).textTheme.body1.fontSize,
                    ),
                  ),
                  Text(
                    demoText,
                    style: TextStyle(
                      fontSize: Theme.of(context).textTheme.caption.fontSize,
                    ),
                  ),
                  Text(
                    demoText,
                    style: TextStyle(
                      fontSize: Theme.of(context).textTheme.button.fontSize,
                    ),
                  ),
                ],
              ),
            ),
          ),
        ),
      ),
    );
  }
}