วิธีทำให้แอปพลิเคชันตอบสนองตามขนาดหน้าจอที่แตกต่างกัน


94

ฉันกำลังประสบปัญหาในการทำให้มันตอบสนองตามขนาดหน้าจอต่างๆ จะทำให้ตอบสนองได้อย่างไร?

@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: () {})
                ]),
              ),
            ),
          ),
        ],
      ),
    );
  }
}

ฉันเขียนวิธีง่ายๆที่นี่jaycoding.tech/tutorials/guides/…เพราะฉันคิดว่าไม่MediaQueryเพียงพอ คุณอาจต้องการตรวจสอบ
NduJay

คำตอบ:


78

ใช้MediaQueryคลาส:

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

MediaQuery : สร้างแผนผังย่อยที่คิวรีสื่อแก้ไขข้อมูลที่กำหนด

MediaQueryData : ข้อมูลเกี่ยวกับสื่อ (เช่นหน้าต่าง)

ในการรับอัตราส่วนพิกเซลของอุปกรณ์:

queryData.devicePixelRatio

ในการรับความกว้างและความสูงของหน้าจออุปกรณ์:

queryData.size.width
queryData.size.height

ในการรับตัวประกอบมาตราส่วนข้อความ:

queryData.textScaleFactor

ใช้AspectRatioคลาส:

จาก doc:

วิดเจ็ตที่พยายามปรับขนาดชายน์ให้เป็นอัตราส่วนเฉพาะ

อันดับแรกวิดเจ็ตจะพยายามใช้ความกว้างที่ใหญ่ที่สุดที่อนุญาตโดยข้อ จำกัด ของโครงร่าง ความสูงของวิดเจ็ตถูกกำหนดโดยใช้อัตราส่วนภาพที่กำหนดกับความกว้างซึ่งแสดงเป็นอัตราส่วนของความกว้างต่อความสูง

ตัวอย่างเช่นอัตราส่วนกว้างยาว 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,
      )
    ),
  ),
),

นอกจากนี้คุณสามารถใช้ :


3
ฉันสามารถรับความกว้างและความสูงของอุปกรณ์ได้ฉันจะกำหนดขนาดการทดสอบช่องว่างระยะขอบผ่านqueryDataได้อย่างไร
Farhana

33

คลาสนี้จะช่วยและเริ่มต้นคลาสด้วยเมธอด 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


จะเพิ่ม EdgeInsets ด้านล่างด้วยคลาส SizeConfig นี้ได้อย่างไร
Farwa

ฉันคิดว่าในฐานะที่เป็นช่องว่างภายในของคอนเทนเนอร์จะทำงานได้ ลองบอกเลยว่าช่วยคุณได้ !!

16

สิ่งที่ฉันทำคือใช้ความกว้างและความสูงของหน้าจอและคำนวณตาราง 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;

สิ่งนี้ใช้ได้ดีกับโครงการล่าสุดบางโครงการ


1
วิธีคำนวณ fontSizes? คำนวณตามความกว้างหรือความสูงดีไหม
Harsh Bhavsar

ฉันกำลังคำนวณตามความกว้าง แต่พูดตามตรงฉันไม่ได้ลองใช้แอพที่รองรับทั้งโหมดแนวนอนและแนวตั้ง แต่คุณอาจยังคำนวณได้ไม่เหมือนกันในทั้งสองทิศทาง
datayeah

วิธีนี้ช่วยแก้ปัญหาความแตกต่างของความหนาแน่นของหน้าจอได้อย่างไร การบอกว่าคุณแบ่งหน้าจอออกเป็นบล็อกตาราง 100 * 100 คุณทำให้ดูเหมือนว่าบล็อกผลลัพธ์มีขนาดเท่ากันทั้งหมด (เช่นสี่เหลี่ยม) แต่ไม่ใช่ หากคุณมีอุปกรณ์ที่มีจำนวนพิกเซลสองเท่าในแนวตั้ง (ความสูงของหน้าจอ) มากกว่าแนวนอน (ความกว้างของหน้าจอ) บล็อกผลลัพธ์ของคุณจะเป็นรูปสี่เหลี่ยมผืนผ้าแทนที่จะเป็นสี่เหลี่ยมซึ่งหมายความว่าโค้ดของคุณยังคงสร้างปัญหาเดิมที่คุณเริ่มพยายามแก้ไข ทดสอบโค้ดของคุณกับความหนาแน่นของหน้าจอหลายระดับเพื่อพิสูจน์สิ่งนี้ นี่ไม่ใช่วิธีแก้ปัญหาสำหรับฉันจริงๆ
SilSur

@SilSur แน่ใจว่าบล็อกมีขนาดไม่เท่ากันบนอุปกรณ์และความหนาแน่นใด ๆ แต่นั่นคือสิ่งที่ทำให้มันใช้งานได้ (ในกรณีส่วนใหญ่) ฉันต้องตัดสินใจสำหรับแต่ละวิดเจ็ตฉันเพิ่มลงในหน้าจอว่าฉันต้องการให้มีการคำนวณตำแหน่งและขนาดตามความกว้างหรือความสูงของบล็อกหรือทั้งสองอย่าง ฉันเคยใช้วิธีนี้ในแอพที่ทำงานบนโทรศัพท์ / แท็บเล็ต iphone, ipad หรือ android โดยไม่มีการแก้ไขเฉพาะอุปกรณ์ แนวนอนและแนวตั้ง แต่คุณคิดถูกที่วิธีนี้ยังไม่สามารถแก้ปัญหา UI ที่ซับซ้อนได้อย่างสมบูรณ์แบบ ฉันยังคงมองหาสิ่งที่ดีกว่าเพื่อจัดการเรื่องนี้
datayeah

11

ตรวจสอบMediaQueryชั้นเรียน

ตัวอย่างเช่นในการเรียนรู้ขนาดของสื่อในปัจจุบัน (เช่นหน้าต่างที่มีแอปของคุณ) คุณสามารถอ่านMediaQueryData.sizeคุณสมบัติจากMediaQueryDataกลับโดย:MediaQuery.ofMediaQuery.of(context).size

คุณสามารถทำสิ่งต่อไปนี้ได้:

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

คุณหมายถึงแทนที่จะใช้ตำแหน่ง mediaQuery ??
praveen Dp

ฉันไม่เข้าใจว่าคุณกำลังพยายามทำอะไร
aziza

ใช้ postitioned, padding ภายใน stack. ฉันปรับเป็นขนาดหน้าจอแล้วตอนนี้เพื่อให้ตอบสนองฉันควรใช้ mediaquery แทนอะไร ??
praveen Dp

8

วิธีที่ง่ายที่สุดในการสร้าง UI ที่ตอบสนองสำหรับขนาดหน้าจอที่แตกต่างกันคือปลั๊กอิน Sizerภาพหน้าจอ Sizer

สร้าง UI ที่ตอบสนองในอุปกรณ์ขนาดหน้าจอและแท็บเล็ต ตรวจสอบปลั๊กอินนี้⬇️
https://pub.dev/packages/sizer

.h  - for widget height
.w  - for widget width
.sp - for font size

การใช้งาน.h, .w, .spหลังจากที่คุ้มค่าเช่นนี้⬇️

ตัวอย่าง:

Container(
  height: 10.0.h,  //10% of screen height
  width: 80.0.w,   //80% of screen width
  child: Text('Sizer', style: TextStyle(fontSize: 12.0.sp)),
);

ฉันได้สร้างแอปที่ตอบสนองได้มากมายด้วยปลั๊กอินนี้


2
วิธีนี้ยอดเยี่ยมมากฉันจะลองสังเกตพฤติกรรมแล้วลงมือผลิตด้วยถ้ามันทำให้ฉันพอใจ
Wambert Orion

2
ขอบคุณมาก @urmish patel มันเป็นวิธีที่ง่ายที่สุดในการทำให้แอปตอบสนอง
Tarun Sharma

5

คุณสามารถใช้เปอร์เซ็นต์ของความกว้างหรือความสูงเป็นอินพุตสำหรับขนาดมาตราส่วน

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

โดยที่ตัวคูณท้ายมีค่าที่ทำให้ข้อความดูดีสำหรับโปรแกรมจำลองที่ใช้งานอยู่

ด้านล่างนี้คือวิธีการตั้งค่าเพื่อให้มิติที่ปรับขนาดทั้งหมดรวมศูนย์ไว้ในที่เดียว ด้วยวิธีนี้คุณสามารถปรับเปลี่ยนได้อย่างง่ายดายและรวดเร็วด้วย Hot Reload โดยไม่ต้องมองหาการMedia.of()โทรตลอดทั้งรหัส

  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),
    );

ขอบคุณคำตอบในโพสต์นี้


4
Place dependency in pubspec.yaml

flutter_responsive_screen: ^1.0.0

Function hp = Screen(MediaQuery.of(context).size).hp;
Function wp = Screen(MediaQuery.of(context).size).wp;

Example :
return Container(height: hp(27),weight: wp(27));

4
บางทีคำอธิบายเกี่ยวกับสิ่งที่เกิดขึ้นภายใต้ฝากระโปรงจะดีมากในครั้งต่อไปที่คุณโพสต์ "วิธีแก้ปัญหา"? อย่างไรก็ตามฉันตรวจสอบ GitHub สำหรับการอ้างอิงนี้ โดยพื้นฐานแล้วเป็นคลาสเดียว (มีรหัส 16 บรรทัด) ที่รับค่าความกว้างและความสูงของอินพุตและปรับขนาดตามความกว้างและความสูงของหน้าจอเป็นเปอร์เซ็นต์ โดยพื้นฐานแล้วมันเหมือนกับวิธีแก้ปัญหาของ @datayeah ข้อแตกต่างเพียงอย่างเดียวคืออันนี้บรรจุอย่างเรียบร้อย ปัญหาเดียวกันกับ datayeah ใช้ที่นี่ - ไม่ใช่วิธีแก้ปัญหาที่ดีเลยสำหรับการปรับขนาด 1: 1 บนอุปกรณ์ความหนาแน่นของหน้าจอที่แตกต่างกัน ปัญหาความหนาแน่นของหน้าจอไม่สามารถแก้ไขได้ด้วย "วิธีแก้ปัญหา" นี้
SilSur

4

หลังจากการวิจัยและทดสอบมากมายฉันได้พัฒนาโซลูชันสำหรับแอปที่ฉันกำลังแปลงจาก Android / iOS เป็น Flutter

สำหรับ Android และ iOS ฉันใช้ 'Scaling Factor' ที่ใช้กับขนาดตัวอักษรพื้นฐานแสดงผลขนาดข้อความที่สัมพันธ์กับขนาดหน้าจอ

บทความนี้มีประโยชน์มาก: https://medium.com/flutter-community/flutter-effectively-scale-ui-according-to-different-screen-sizes-2cb7c115ea0a

ฉันสร้าง StatelessWidget เพื่อรับขนาดแบบอักษรของรูปแบบการพิมพ์ของ Material Design การรับขนาดอุปกรณ์โดยใช้ MediaQuery การคำนวณปัจจัยการปรับขนาดจากนั้นรีเซ็ตขนาดข้อความดีไซน์ Material วิดเจ็ตสามารถใช้เพื่อกำหนดธีมการออกแบบวัสดุที่กำหนดเองได้

อีมูเลเตอร์ที่ใช้:

  • 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,
                    ),
                  ),
                ],
              ),
            ),
          ),
        ),
      ),
    );
  }
}

3

ฉันเคยเคาะโซลูชัน (@datayeah & Vithani Ravi) ของคนอื่นมาค่อนข้างยากดังนั้นฉันจึงคิดว่าฉันจะแบ่งปันความพยายามของตัวเองในการแก้ปัญหาการปรับขนาดความหนาแน่นของหน้าจอที่แปรผันหรือหุบปาก ดังนั้นฉันจึงเข้าใกล้ปัญหานี้จากรากฐานที่มั่นคง / คงที่: ฉันตั้งฐานสเกลทั้งหมดของฉันด้วยอัตราส่วนคงที่ (ไม่เปลี่ยนรูป) เป็น 2: 1 (ความสูง: ความกว้าง) ฉันมีคลาสตัวช่วย "McGyver" ที่ช่วยยกของหนัก (และโค้ด finessing ที่เป็นประโยชน์) ในแอปของฉัน คลาส "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,
    );
  }

}

... ... ...

จากนั้นคุณจะปรับขนาดวิดเจ็ตของคุณทีละรายการ (ซึ่งสำหรับโรคสมบูรณ์แบบคือ UI ทั้งหมดของฉัน) ด้วยการเรียกแบบคงที่ไปยังเมธอด "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()- โดยทั่วไปฉันจะคลั่งไคล้กับสิ่งที่ปรับขนาดนี้ ... เพราะฉันต้องการให้แอปของฉันเป็น พิกเซลสมบูรณ์แบบในทุกขนาดหรือความหนาแน่นของหน้าจอ !! ฉันปรับอัตราส่วน ints, doubles, padding, text (ทุกอย่างที่ต้องการความสอดคล้องของ UI ในอุปกรณ์ต่างๆ) ฉันปรับขนาดข้อความของฉันตามความกว้างเท่านั้น แต่ระบุแกนที่จะใช้สำหรับมาตราส่วนอื่น ๆ ทั้งหมด (เช่นเดียวกับScaleType.widthenum ที่ใช้สำหรับการMcGyver.rsDouble()เรียกในตัวอย่างโค้ดด้านบน)

ฉันรู้ว่ามันบ้า - และเป็นงานที่ต้องทำมากมายในเธรดหลัก - แต่ฉันหวังว่าใครบางคนจะเห็นความพยายามของฉันที่นี่และช่วยฉันหาวิธีแก้ปัญหาที่ดีกว่า (น้ำหนักเบามากขึ้น) สำหรับการปรับความหนาแน่นของหน้าจอ 1: 1 ฝันร้าย


1
@ Abbas.M - ใช่ฉันได้ทำการเปลี่ยนแปลงเล็กน้อยกับบรรทัดรหัสอัตราส่วนมาตราส่วน [ดูรหัสที่อัปเดต] และฉันเชื่อว่านี่เป็นวิธีที่ใกล้เคียงที่สุดที่ฉันจะได้โซลูชันอัตราส่วนอัตราส่วน 1: 1 จริง - ฉันได้ลองมาแล้วจำนวนหนึ่ง ตัวเลือกที่จะได้รับสิ่งนี้ ยังคงมีปัญหาการปรับขนาด [edge-case] แปลก ๆ เล็กน้อยกับโค้ดที่อัปเดตนี้ แต่ความคล้ายคลึงกันของ UI บนหน้าจอความหนาแน่นหลายหน้าจอนั้นน่าเชื่อจริงๆ - ความแตกต่างที่ละเอียดอ่อนมากสามารถสังเกตได้ระหว่างหน้าจอที่มีรหัสที่อัปเดต โปรดแจ้งให้เราทราบว่าคุณคิดอย่างไร - ข้อเสนอแนะจะได้รับการชื่นชมอย่างมาก
SilSur

สิ่งที่ชัดเจนเกี่ยวกับเธรดหลักให้ย้ายการเริ่มต้นและการโทรไปยังบล็อกหลักของแอป init เนื่องจากขนาดหน้าจอจะไม่เปลี่ยนแปลงหลังจากเริ่มต้นแอปดังนั้นคุณจะมีเธรดหลักเพียงครั้งเดียวที่เริ่มต้นแอปแทนที่จะแสดงผลวิดเจ็ตแต่ละรายการ
เฟร็ด Grott

@SilSur โซลูชันของคุณดูดีมาก คุณสนใจที่จะแบ่งปันคลาส McGyver ทั้งหมดหรือไม่?
David

@David - คลาส McGyver เป็นคลาสที่หนักมาก (และเฉพาะโครงการ) สิ่งที่ฉันใช้ในตัวอย่างนี้มีฟังก์ชันมากมายที่ไม่เกี่ยวข้องกับปัญหาการปรับขนาด UI ดังนั้นฉันจึงอัปโหลดทั้งชั้นเรียนมากเกินไป / ไม่มีประสิทธิภาพ ฉันได้ แต่ปรับปรุงในระดับบิตและมีการโพสต์รุ่นที่แตกต่างกันของรหัสเพื่อคำถาม SO อีก บางทีคุณสามารถอัปเดตโค้ดมาตราส่วนของคุณตามบรรทัดของโค้ดที่ปรับปรุงแล้วได้ที่ URL ที่ให้มา
SilSur

1

คุณสามารถใช้ MediaQuery สำหรับมิติของผู้ปกครองหรือ FractionallySizedBox เป็นคอนเทนเนอร์


1

วิธีการแก้ปัญหาของฉันคล้ายกับวิธีที่ดาทาเยห์ทำ ฉันมีค่าความกว้างและความสูงแบบฮาร์ดโค้ดจำนวนมากและแอปก็ดูดีบนอุปกรณ์บางเครื่อง ดังนั้นฉันจึงได้ความสูงของหน้าจอของอุปกรณ์และเพิ่งสร้างปัจจัยเพื่อปรับขนาดค่าฮาร์ดโค้ด

double heightFactor = MediaQuery.of(context).size.height/708

โดยที่ 708 คือความสูงของอุปกรณ์เฉพาะ


1

ฉันพยายามทำให้เรียบง่ายที่สุด ลองดูสิ ฉันสร้างยูทิลิตี้ที่ตอบสนองโดยมีฟังก์ชัน getresponsivevalue รับผิดชอบในการให้ค่าตามขนาดหน้าจอหากคุณไม่กำหนดค่าสำหรับหน้าจอขนาดกลางหน้าจอขนาดใหญ่โหมดแนวนอนโดยค่าเริ่มต้นจะให้ค่าที่กำหนดหน้าจอสั้น การต้อนรับอย่างอบอุ่นสำหรับข้อสงสัยใด ๆ ฉันชอบที่จะปรับปรุง

class SampleView extends StatelessWidget {
@override
Widget build(BuildContext context) {
 return Center(
  child: Container(
    width: 200,
    height: 200,
    color: Responsive().getResponsiveValue(
        forLargeScreen: Colors.red,
        forMediumScreen: Colors.green,
        forShortScreen: Colors.yellow,
        forMobLandScapeMode: Colors.blue,
        context: context),
  ),
);

}}

 // utility class
          class Responsive {
            // function reponsible for providing value according to screensize
            getResponsiveValue(
                {dynamic forShortScreen,
                dynamic forMediumScreen,
                dynamic forLargeScreen,
                dynamic forMobLandScapeMode,
                BuildContext context}) {

              if (isLargeScreen(context)) {

                return forLargeScreen ?? forShortScreen;
              } else if (isMediumScreen(context)) {

                return forMediumScreen ?? forShortScreen;
              } 
           else if (isSmallScreen(context) && isLandScapeMode(context)) {

                return forMobLandScapeMode ?? forShortScreen;
              } else {
                return forShortScreen;
              }
            }
          
            isLandScapeMode(BuildContext context) {
              if (MediaQuery.of(context).orientation == Orientation.landscape) {
                return true;
              } else {
                return false;
              }
            }
          
            static bool isLargeScreen(BuildContext context) {
              return getWidth(context) > 1200;
            }
          
            static bool isSmallScreen(BuildContext context) {
              return getWidth(context) < 800;
            }
          
            static bool isMediumScreen(BuildContext context) {
              return getWidth(context) > 800 && getWidth(context) < 1200;
            }
          
            static double getWidth(BuildContext context) {
              return MediaQuery.of(context).size.width;
            }
          }

0

ตรวจสอบหน้านี้จาก flutter wiki:

การสร้างแอปที่ตอบสนอง

ใช้คลาส LayoutBuilder: จากคุณสมบัติ builder คุณจะได้รับ BoxConstraints ตรวจสอบคุณสมบัติของข้อ จำกัด เพื่อตัดสินใจว่าจะแสดงอะไร ตัวอย่างเช่นถ้า maxWidth ของคุณมากกว่าเบรกพอยต์ความกว้างของคุณให้ส่งคืนวัตถุ Scaffold ด้วยแถวที่มีรายการทางด้านซ้าย ถ้าแคบกว่าให้ส่งคืนวัตถุ Scaffold ด้วยลิ้นชักที่มีรายการนั้น คุณยังสามารถปรับการแสดงผลของคุณตามความสูงของอุปกรณ์อัตราส่วนภาพหรือคุณสมบัติอื่น ๆ เมื่อข้อ จำกัด เปลี่ยนไป (เช่นผู้ใช้หมุนโทรศัพท์หรือทำให้แอปของคุณเป็นไทล์ UI ใน Nougat) ฟังก์ชันการสร้างจะทำงานอีกครั้ง


0

สร้างชื่อไฟล์ (app_config.dart) ในชื่อโฟลเดอร์ (responsive_screen) ในโฟลเดอร์ lib:

import 'package:flutter/material.dart';

class AppConfig {
  BuildContext _context;
  double _height;
  double _width;
  double _heightPadding;
  double _widthPadding;

  AppConfig(this._context) {
    MediaQueryData _queryData = MediaQuery.of(_context);
    _height = _queryData.size.height / 100.0;
    _width = _queryData.size.width / 100.0;
    _heightPadding =
    _height - ((_queryData.padding.top + _queryData.padding.bottom) / 100.0);
    _widthPadding =
      _width - (_queryData.padding.left + _queryData.padding.right) / 100.0;
  }

  double rH(double v) {
   return _height * v;
  }

  double rW(double v) {
    return _width * v;
  }

  double rHP(double v) {
    return _heightPadding * v;
  }

 double rWP(double v) {
   return _widthPadding * v;
 }
}

แล้ว:

import 'responsive_screen/app_config.dart';
 ...
class RandomWordsState extends State<RandomWords> {
  AppConfig _ac;
  ...
  @override
  Widget build(BuildContext context) {
    _ac = AppConfig(context);
    ...
    return Scaffold(
      body: Container(
        height: _ac.rHP(50),
        width: _ac.rWP(50),
        color: Colors.red,
        child: Text('Test'),
      ),
    );
    ...
  }

0

ปัญหานี้สามารถแก้ไขได้โดยใช้MediaQuery.of (บริบท)

ในการรับความกว้างของหน้าจอ: MediaQuery.of(context).size.width

ในการรับความสูงของหน้าจอ: MediaQuery.of(context).size.height

สำหรับข้อมูลเพิ่มเติมเกี่ยวกับนาฬิกา MediaQuery Widget https://www.youtube.com/watch?v=A3WrA4zAaPw


0
  padding: EdgeInsets.only(
      left: 4.0,
      right: ResponsiveWidget.isSmallScreen(context) ? 4: 74, //Check for screen type
      top: 10,
      bottom: 40),

คำแนะนำของ Google ใช้ได้ดี แต่อาจไม่สมบูรณ์แบบ


0

ใช้ ResponsiveBuilder หรือ ScreenTypeLayout

import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:responsive_builder/responsive_builder.dart';

class Sample extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        elevation: 0,
        backgroundColor: Colors.black,
      ),
      body: ResponsiveBuilder(
        builder: (context, info) {
          var screenType = info.deviceScreenType;
          String _text;
          switch (screenType){
            case DeviceScreenType.desktop: {
              _text = 'Desktop';
              break;
            }
            case DeviceScreenType.tablet: {
              _text = 'Tablet';
              break;
            }
            case DeviceScreenType.mobile: {
              _text = 'Mobile';
              break;
            }
            case DeviceScreenType.watch: {
              _text = 'Watch';
              break;
            }
            default:
              return null;
          }
          return Center(child: Text(_text, style: TextStyle(fontSize: 32, color: Colors.black),));
        },
      ),
    );
  }
}

// screen type layout
ScreenTypeLayout.builder(
  mobile: MobilePage(),
  tablet: TabletPage(),
  desktop: DesktopPage(),
  watch: Watchpage(),
);


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.