简体   繁体   中英

Universal UI layout on flutter for screens of different sizes

I'm flutter beginner. I'm reading the documentation and trying it out. Sorry for my google english.


I have a small application. The problem is that it looks different on different screens.


ATTENTION! I understand the problem of universal layout and have already read what the original flutter documentation offers me to solve the problem of different screens.


Basically, I am being asked to define a screen border by using MediaQuery.of () and constrain it to some parameter like <600 or> 800 and so on. The problem is that I use the font size parameter for the text and my buttons periodically lose the text inside them, or they turn out to be too small if I do not add LOTS of checks with MediaQuery.of () on LITERALLY EACH element. Do I really have to use MediaQuery.of (). Size.width on each object? Is there no other solution? It seems to me to be very cumbersome and inconvenient. Perhaps I misunderstand the concept of the responsive apps offered to me.

No need for packages. I have created the same that this package does https://pub.dev/packages/flutter_screenutil

I am using this in production apps.

import 'dart:ui' as ui;

import 'package:flutter/material.dart';

class Responsiveness {
  static Responsiveness _instance;
  static const Size defaultSize = Size(375, 812);

  Size uiSize = defaultSize;

  bool allowFontScaling;

  static double _screenWidth;
  static double _screenHeight;
  static double _pixelRatio;
  static double _statusBarHeight;
  static double _bottomBarHeight;
  static double _textScaleFactor;

  Responsiveness._() {
    MediaQueryData mediaQuery = MediaQueryData.fromWindow(ui.window);
    _pixelRatio = mediaQuery.devicePixelRatio;
    _screenWidth = mediaQuery.size.width;
    _screenHeight = mediaQuery.size.height;
    _statusBarHeight = mediaQuery.padding.top;
    _bottomBarHeight = mediaQuery.padding.bottom;
    _textScaleFactor = mediaQuery.textScaleFactor;
  }

  factory Responsiveness() {
    assert(
      _instance != null,
      '\nEnsure to initialize Responsiveness before accessing it.',
    );
    return _instance;
  }

  static void init({
    Size designSize = defaultSize,
    bool allowFontScaling = false,
  }) {
    _instance ??= Responsiveness._();
    _instance
      ..uiSize = designSize
      ..allowFontScaling = allowFontScaling;
  }

  static double get textScaleFactor => _textScaleFactor;

  /// The size of the media in logical pixels (e.g, the size of the screen).
  static double get pixelRatio => _pixelRatio;

  /// The horizontal extent of this size.
  static double get screenWidth => _screenWidth;

  /// The vertical extent of this size. dp
  static double get screenHeight => _screenHeight;

  /// The vertical extent of this size. px
  static double get screenWidthPx => _screenWidth * _pixelRatio;

  /// The vertical extent of this size. px
  static double get screenHeightPx => _screenHeight * _pixelRatio;

  /// The offset from the top
  static double get statusBarHeight => _statusBarHeight;

  /// The offset from the bottom.
  static double get bottomBarHeight => _bottomBarHeight;

  /// The ratio of the actual dp to the design draft px
  double get scaleWidth => _screenWidth / uiSize.width;

  double get scaleHeight =>
      (_screenHeight - _statusBarHeight - _bottomBarHeight) / uiSize.height;

  double get scaleText => scaleWidth;

  /// Adapted to the device width of the UI Design.
  /// Height can also be adapted according to this to ensure no deformation ,
  /// if you want a square
  num setWidth(num width) => width * scaleWidth;

  /// Highly adaptable to the device according to UI Design
  /// It is recommended to use this method to achieve a high degree of adaptation
  /// when it is found that one screen in the UI design
  /// does not match the current style effect, or if there is a difference in shape.
  num setHeight(num height) => height * scaleHeight;

  num setSpacing(num spacing) => spacing * scaleWidth;

  num setHorizontalSpacing(num spacing) => spacing * scaleWidth;

  num setVerticalSpacing(num spacing) => spacing * scaleHeight;

  /// Icon sizing function
  num setIconSize(num size) => size * scaleWidth;

  ///@param [fontSize]
  ///Font size adaptation method
  ///@param [fontSize] The size of the font on the UI design, in px.
  ///@param [allowFontScaling]
  num setFontSize(num fontSize, {bool allowFontScalingSelf}) =>
      allowFontScalingSelf == null
          ? (allowFontScaling
              ? (fontSize * scaleText)
              : ((fontSize * scaleText) / _textScaleFactor))
          : (allowFontScalingSelf
              ? (fontSize * scaleText)
              : ((fontSize * scaleText) / _textScaleFactor));
}

extension ResponsivenessExtension on num {
  // shorthand for width
  num get w => Responsiveness().setWidth(this);

  // shorthand for height
  num get h => Responsiveness().setHeight(this);

  // shorthand for fontsize
  num get f => Responsiveness().setFontSize(this);

  // shorthand for spacing(Padding, margin)
  num get s => Responsiveness().setSpacing(this);

  // shorthand for spacing(Vertical Padding, Vertical margin)
  num get vs => Responsiveness().setVerticalSpacing(this);

  // shorthand for spacing(Horizontal Padding, Horizontal margin)
  num get hs => Responsiveness().setHorizontalSpacing(this);

  // shorthand for icon size
  num get ics => Responsiveness().setIconSize(this);
}

Intialize in main.dart

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

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  Responsiveness.init();
  runApp(MaterialApp(home: MyApp(),));
}

Use in any widget like

class MyApp extends StatelessWidget {
 @override
  Widget build(BuildContext context) {
    return Container(
      width: 120.w,
      height: 120.h,
      padding: EdgeInsets.all(10.s),
      child: Text(
        'hai', 
        style: TextStyle(fontSize: 12.f,),
      ),
    );
  }
}

Note: .w, .h, .f, .s are extensions created in Responsiveness

For further control you can use

import 'package:flutter/material.dart';

/// The is a generic widget, used for determining the screen sizes (mobile or desktop)
/// isSmallScreen and isLargeScreen are the functions to decide the width of screen

class ResponsiveLayout extends StatelessWidget {
  /// variable to be used for desktop view
  final Widget largeScreen;

  /// variable to be used for mobile view
  final Widget smallScreen;

  const ResponsiveLayout({
    Key key,
    @required this.largeScreen,
    this.smallScreen,
  }) : super(key: key);

  //static double desktopSize based on screenSize 
  static double desktopSize(context) {
    return (MediaQuery.of(context).size.width>1200)? 1140:970;
  }

  static bool isSmallScreen(BuildContext context) {
    return MediaQuery.of(context).size.width < 992;
  }

  static bool isLargeScreen(BuildContext context) {
    return MediaQuery.of(context).size.width >= 992;
  }

  @override
  Widget build(BuildContext context) {
    return LayoutBuilder(
      builder: (context, constraints) {
        if (constraints.maxWidth >= 992) {
          return largeScreen;
        } else {
          return smallScreen ?? largeScreen;
        }
      },
    );
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM