अलग-अलग स्क्रीन आकार के अनुसार स्पंदन ऐप को कैसे उत्तरदायी बनाया जाए?


85

मुझे विभिन्न स्क्रीन आकारों के अनुसार इसे उत्तरदायी बनाने के लिए कठिनाइयों का सामना करना पड़ रहा है। इसे उत्तरदायी कैसे बनाया जाए?

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

जवाबों:


72

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

इसके अलावा आप उपयोग कर सकते हैं :


3
मैं डिवाइस की चौड़ाई और ऊंचाई प्राप्त करने में सक्षम हूं, मैं कैसे परीक्षण आकार, पैडिंग, मार्जिन सेट कर सकता हूं queryData
फरहाना

29

यह क्लास मदद करेगा और फिर इनिट विधि से क्लास को इनिशियलाइज़ करेगा।

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


इस SizeConfig वर्ग के साथ EdgeInsets नीचे कैसे जोड़ें?
फरवा

मुझे लगता है कि कंटेनर की गद्दी काम करेगी। कोशिश करो और मुझे बताओ तुम्हारी मदद करने के लिए !!

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 की गणना कैसे करें? चौड़ाई या ऊंचाई के आधार पर गणना करना अच्छा है?
हर्ष भावसार

मैं उनकी चौड़ाई के आधार पर गणना कर रहा हूं। लेकिन ईमानदार होने के लिए, मैंने इसे उन ऐप्स के साथ आज़माया नहीं जो परिदृश्य और पोर्ट्रेट मोड दोनों का समर्थन करते हैं। लेकिन आप अभी भी इसे दोनों झुकावों पर अलग-अलग गणना करने में सक्षम हो सकते हैं।
दिनांक

यह स्क्रीन घनत्व अंतर की समस्या को बिल्कुल कैसे हल करता है? यह कहकर कि आप स्क्रीन को 100 * 100 ग्रिड ब्लॉक्स में विभाजित करते हैं, जिससे आप यह ध्वनि बनाते हैं कि परिणामी ब्लॉक सभी समान आकार (यानी वर्ग) के हैं, लेकिन वे नहीं हैं। यदि आपके पास एक ऐसा उपकरण है जिसमें क्षैतिज (स्क्रीन चौड़ाई) की तुलना में लंबवत (स्क्रीन ऊंचाई) पिक्सेल की संख्या दोगुनी है, तो आपके परिणामी ब्लॉक वर्गों के बजाय आयताकार होंगे - जिसका अर्थ है कि आपका कोड अभी भी वही समस्या पैदा करता है जिसे आप हल करने की कोशिश करना शुरू कर देते हैं। यह साबित करने के लिए कई स्क्रीन घनत्व पर अपने कोड का परीक्षण करें। तो यह वास्तव में मेरे लिए एक समाधान नहीं है।
सिलसूर

@SilSur, यकीन है कि ब्लॉक किसी भी डिवाइस और घनत्व पर समान आकार नहीं हैं, लेकिन यह काम करता है (ज्यादातर मामलों में)। मुझे बस प्रत्येक विजेट के लिए निर्णय लेना है जो मैं स्क्रीन पर जोड़ता हूं यदि मैं चाहता हूं कि यह स्थिति और आकार की गणना किसी ब्लॉक की चौड़ाई या ऊंचाई के बारे में की जाए - और दोनों। मैंने इस पद्धति का उपयोग उन ऐप्स में किया है जो डिवाइस-विशिष्ट सुधारों के बिना किसी भी iPhone, iPad या एंड्रॉइड फोन / टैबलेट पर चलते हैं। परिदृश्य और चित्र। लेकिन आप सही हैं कि यह विधि अभी भी जटिल UI समस्याओं को पूरी तरह से हल नहीं कर रही है। मैं अभी भी इसे संभालने के लिए कुछ बेहतर देख रहा हूं।
दिनांक

9

MediaQueryकक्षा की जाँच करें

उदाहरण के लिए, वर्तमान मीडिया का आकार जानने के लिए (जैसे, खिड़की अपने अनुप्रयोग से युक्त), आप पढ़ सकते हैं MediaQueryData.sizeसे संपत्ति MediaQueryDataद्वारा दिया MediaQuery.of: MediaQuery.of(context).size

तो आप निम्न कार्य कर सकते हैं:

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

आप मीडिया का उपयोग करने के बजाय तैनात मतलब है ??
प्रॉपेन डीपी

मुझे समझ में नहीं आ रहा है कि आप क्या करने की कोशिश कर रहे हैं
अज़ीज़

पोस्टेडेड का उपयोग करके, ढेर के अंदर पैडिंग। मैंने इसे स्क्रीन आकार में समायोजित कर दिया है। इसे उत्तरदायी बनाने के लिए मुझे क्या के स्थान पर मीडियाक्वेरी का उपयोग करना चाहिए ??
प्रवीण Dp

5

आप स्केल आकार के लिए इनपुट के रूप में चौड़ाई या ऊंचाई का एक प्रतिशत ले सकते हैं।

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

जहां अंत में गुणक में एक मान होता है जो पाठ को सक्रिय एमुलेटर के लिए अच्छा बनाता है।

नीचे यह बताया गया है कि मैंने इसे कैसे सेट किया ताकि सभी स्केल किए गए आयाम एक ही स्थान पर केंद्रीकृत हो जाएं। इस तरह से आप उन्हें आसानी से और जल्दी से फिर से गर्म कर सकते हैं फिर से लोड के साथ फिर से लोड बिना 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

मैं अन्य लोगों (@datayeah & Vithani Ravi) को थोड़ा मुश्किल से हल कर रहा हूं, इसलिए मैंने सोचा कि मैं इस चर स्क्रीन घनत्व स्केलिंग समस्या को हल करने या बंद करने के लिए अपना खुद का प्रयास साझा करूंगा। इसलिए मैं इस समस्या को एक ठोस / निश्चित आधार से जोड़ता हूं: मैं अपने सभी स्केलिंग को 2: 1 (ऊंचाई: चौड़ाई) के एक निश्चित (अपरिवर्तनीय) अनुपात से दूर करता हूं। मेरे पास एक सहायक वर्ग "मैकगाइवर" है जो अपने ऐप में सभी भारी उठाने (और उपयोगी कोड चालाकी) करता है। इस "McGyver" वर्ग में केवल स्थिर विधियाँ और स्थिर स्थिर वर्ग सदस्य हैं।

RATIO SCALING METHOD: मैं 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()- इसलिए मैं मूल रूप से इस स्केलिंग सामान के साथ पागल हो जाता हूं ... क्योंकि मैं अपने ऐप्स की मांग करता हूं किसी भी पैमाने या स्क्रीन घनत्व पर बिल्कुल सही पिक्सेल !! मैं अपने इन्टल्स-स्केल, डबल्स, पेडिंग, टेक्स्ट (वह सब कुछ जो डिवाइस में यूआई स्थिरता की आवश्यकता होती है) के अनुपात में। मैं अपने ग्रंथों को केवल चौड़ाई के आधार पर स्केल करता हूं, लेकिन यह निर्दिष्ट करता हूं कि अन्य सभी स्केलिंग के लिए किस अक्ष का उपयोग किया जाए (जैसा कि ऊपर कोड उदाहरण में कॉल के ScaleType.widthलिए उपयोग किए गए एनम के साथ किया गया था McGyver.rsDouble())।

मुझे पता है कि यह पागल है - और मुख्य धागे पर बहुत काम करना है - लेकिन मैं उम्मीद कर रहा हूं कि कोई व्यक्ति मेरे प्रयास को यहां देखेगा और मेरी स्क्रीन घनत्व 1: 1 स्केलिंग के लिए बेहतर (अधिक हल्के वजन) समाधान खोजने में मदद करेगा। बुरे सपने।


1
@ अब्बास। एम - हाँ, मैंने अनुपात-स्केलिंग कोड लाइन में एक छोटा बदलाव किया है [अपडेट कोड देखें] और मेरा मानना ​​है कि निकटतम मैं एक वास्तविक 1: 1 अनुपात स्केलिंग समाधान पर आ सकता हूं - मैंने काफी संख्या में कोशिश की है इस एक को पाने के लिए विकल्प। इस अद्यतन कोड के साथ अभी भी कुछ अजीब [बढ़त-मामले] स्केलिंग मुद्दे हैं लेकिन कई घनत्व स्क्रीन पर UI समानता वास्तव में आश्वस्त है - अद्यतन कोड के साथ स्क्रीन के बीच बहुत सूक्ष्म अंतर। कृपया मुझे बताएं कि आपको क्या लगता है - प्रतिक्रिया की बहुत सराहना की जाती है।
सिलसूर

मुख्य थ्रेड के बारे में स्पष्ट बात, इनिट और कॉल को इनिट मुख्य ब्लॉक में ले जाएं क्योंकि स्क्रीन का आकार ऐप इनिट के बाद नहीं बदलेगा, इसलिए आपके पास केवल मुख्य थ्रेड ऐप के बजाय एक बार ऐप इनीट में हिट होगा, जबकि प्रत्येक विजेट रेंडर
फ्रेड Grott

@SilSur, आपका समाधान बहुत अच्छा लग रहा है। क्या आप पूरे मैकगाइवर वर्ग को साझा करने का मन रखते हैं?
डेविड

@ डेविड - मैकगाइवर वर्ग एक बहुत भारी वर्ग (और परियोजना विशिष्ट) है। इस उदाहरण में मैंने जो प्रयोग किया है उसमें कई कार्य हैं जो UI स्केलिंग समस्या के लिए प्रासंगिक नहीं हैं। इसलिए यह पूरी कक्षा को अपलोड करने के लिए मेरे लिए अधिक महत्वपूर्ण है। हालाँकि, मैंने कक्षा में थोड़ा सुधार किया और कोड के एक भिन्न संस्करण को एक अन्य SO प्रश्न में पोस्ट किया । शायद आप अपने स्केलिंग कोड को प्रदान किए गए URL पर बेहतर कोड की तर्ज पर अपडेट कर सकते हैं।
सिलसूर

4

बहुत शोध और परीक्षण के बाद, मैंने एक ऐप के लिए एक समाधान विकसित किया है जो मैं वर्तमान में एंड्रॉइड / आईओएस से फ्लटर में परिवर्तित कर रहा हूं।

एंड्रॉइड और आईओएस के साथ मैंने एक 'स्केलिंग फैक्टर' का इस्तेमाल किया जो कि बेस फॉन्ट साइज पर लागू होता था, जो टेक्स्ट साइज को स्क्रीन साइज के सापेक्ष देते थे।

यह लेख बहुत मददगार था: https://medium.com/flutter-community/flutter-effectively-scale-ui-according-to-different-screen-sizes-2cb7c115ea0a

मैंने सामग्री डिजाइन टाइपोग्राफिक शैलियों के फ़ॉन्ट आकार प्राप्त करने के लिए एक स्टेटलेसविजेट बनाया। MediaQuery का उपयोग करके डिवाइस आयाम प्राप्त करना, स्केलिंग कारक की गणना करना, फिर सामग्री डिज़ाइन टेक्स्ट आकारों को रीसेट करना। कस्टम सामग्री डिज़ाइन थीम को परिभाषित करने के लिए विजेट का उपयोग किया जा सकता है।

उपयोग किए गए एमुलेटर:

  • पिक्सेल सी - 9.94 "टैबलेट
  • पिक्सेल 3 - 5.46 "फोन
  • iPhone 11 प्रो मैक्स - 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
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 के समाधान के समान है - केवल अंतर यह है कि यह बड़े करीने से पैक किया गया है। डेटाय के रूप में एक ही समस्याएं यहां लागू होती हैं - विभिन्न स्क्रीन घनत्व उपकरणों पर 1: 1 स्केलिंग के लिए एक अच्छा समाधान नहीं। स्क्रीन घनत्व समस्या इस "समाधान" के साथ हल नहीं है।
सिलसूर

1

आप कंटेनरों के रूप में माता-पिता के आयाम या FracticallySizedBox के लिए MediaQuery का उपयोग कर सकते हैं।


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;
            }
          }

1

विभिन्न स्क्रीन आकार के लिए उत्तरदायी UI बनाने का सबसे आसान तरीका Sizer है प्लगइन है।

किसी भी स्क्रीन के आकार के डिवाइस में भी टैबलेट को उत्तरदायी यूआई बनाएं। इसे इस प्लगइन की जाँच करें p
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)),
);

मैं इस प्लगइन के साथ कई उत्तरदायी अनुप्रयोग का निर्माण किया है।


0

इस पृष्ठ को फ़्लटर विकी से देखें:

उत्तरदायी ऐप्स बनाना

LayoutBuilder वर्ग का उपयोग करें: इसकी बिल्डर संपत्ति से, आपको एक BoxConstraints मिलता है। प्रदर्शन करने के लिए तय करने के लिए बाधा के गुणों की जांच करें। उदाहरण के लिए, यदि आपका अधिकतम चौड़ाई आपके चौड़ाई ब्रेकपॉइंट से अधिक है, तो एक पंक्ति के साथ एक स्कैफोल्ड ऑब्जेक्ट वापस करें जिसमें बाईं ओर एक सूची है। यदि यह संकरा है, तो उस सूची वाले ड्रॉअर के साथ एक पाड़ वस्तु लौटाएं। आप डिवाइस की ऊंचाई, पहलू अनुपात, या कुछ अन्य संपत्ति के आधार पर अपने प्रदर्शन को समायोजित कर सकते हैं। जब बाधाएं बदल जाती हैं (जैसे उपयोगकर्ता फोन घुमाता है, या आपके ऐप को नूगा में टाइल यूआई में डालता है), तो बिल्ड फ़ंक्शन फिर से चालू हो जाएगा।


0

फ़ाइल नाम (app_config.dart) को फ़ोल्डर के नाम (उत्तरदायी_स्क्रीन) को लिबास फ़ोल्डर में बनाएँ:

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 विजेट घड़ी के बारे में अधिक जानकारी के लिए, 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(),
);

0

अपने एप्लिकेशन को उत्तरदायी बनाने के लिए आप Responsive_helper पैकेज का उपयोग कर सकते हैं ।

अपने ऐप को उत्तरदायी बनाने के लिए यह एक बहुत ही आसान तरीका है। बस उदाहरण पृष्ठ पर एक नज़र डालें और फिर आप यह पता लगाएंगे कि इसका उपयोग कैसे करना है।


हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.