Mobile developers all know that page adaptation needs to be carried out for different mobile phones of different models and sizes, and iOS and Android adaptation schemes are different. How should Flutter development handle screen adaptation?

Units in Flutter

Flutter uses a point similar to the point pt, or point, in iOS. We often say the iPhone8 is 375×667, but its resolution is actually 750×1334. Because the iPhone8 has a pixel ratio of 2.0, the iPhone8plus has a pixel ratio of 3.0.

The size of each iPhone model

Obtain device information from Flutter

To obtain device-related information, you can use an official library

Device_info: ^ 2.0.3Copy the code
Future getDeviceInfo() Async {DeviceInfoPlugin deviceInfo = DeviceInfoPlugin(); var dataInfo; If (platform. isIOS) {print(' iOS device: '); IosDeviceInfo iosInfo = await deviceInfo.iosInfo; dataInfo = iosInfo; } else if(platform. isAndroid) {print('Android device '); AndroidDeviceInfo androidInfo = await deviceInfo.androidInfo; dataInfo = androidInfo; } return dataInfo; }Copy the code

Gets the screen size

Need to introduce

import 'dart:ui';
Copy the code

Get screen width and height, fringe height, resolution and other information

Final mediaQueryData = MediaQuery. Of (context); / / 2. Get the width and height final screenWidth = mediaQueryData. Size. The width; final screenHeight = mediaQueryData.size.height; final physicalWidth = window.physicalSize.width; final physicalHeight = window.physicalSize.height; final dpr = window.devicePixelRatio; / / 3. The height of the status bar / / a fringe of screen: 44 no bang screen for 20 final statusBarHeight = mediaQueryData. The padding. The top; / / a fringe of screen: 34 no bang screen 0 final bottomHeight = mediaQueryData. The padding. The bottom; Print (' screenWidth :$screenHeight :$screenHeight'); Print (' physicalWidth: $physicalHeight'); Print ($DPR); Print (' statusBarHeight :$bottomHeight');Copy the code

Printed device dimensions

Performing hot restart... Syncing files to device iPhone 12 Pro... Lua/lua/lua/lua/lua/lua/lua/lua/lua/lua/lua/lua/lua/lua/lua/lua/lua/lua/lua/lua/lua/lua/lua/lua/lua/lua 3.0 Flutter status bar height 47.0 Bottom height 34.0Copy the code

Adaptation scheme

1. By means of equal ratio conversion

Calculation formula: actual size = UI size * device width/design drawing width

This encapsulates a class Adapt that lets you get information about the screen

class Adapt { static double screenWidth = 0; static double screenHeight = 0; static double physicalWidth = 0; static double physicalHeight = 0; static double dpr = 0; Static double ratio = 1.0; static double statusBarHeight = 0; static double bottomHeight = 0; static void initialize(BuildContext context, {double UIWidth = 375}) { // 1. Final mediaQueryData = mediaQuery.of (context); / / 2. Get the width and height of screenWidth = mediaQueryData. Size. The width; screenHeight = mediaQueryData.size.height; physicalWidth = window.physicalSize.width; physicalHeight = window.physicalSize.height; // DPR = window.devicepixelRatio; / / 3. The status bar height / / top bang: 47 pt not bang screen for 20 pt statusBarHeight = mediaQueryData. The padding. The top; / / bottom of bang: 34 pt no bangs screen 0 pt bottomHeight = mediaQueryData. Padding. The bottom; // ratio = screenWidth/UIWidth; } static pt(size){ return size * Adapt.ratio; }}Copy the code

The sample code

The UI gives the design a size of 375 by 667 and defines a (300 by 300)pt box to display 30pt text

@override Widget build(BuildContext context) { Adapt.initialize(context); Return Scaffold(appBar: appBar (title: const Text(' screen fit '),), body: Center(Child: Container(width: Adapt.pt(300), height: Adapt.pt(300), color: Colors.orange, alignment: Alignment.center, child: Text( 'Hello Word', style: TextStyle(fontSize: Adapt.pt(30)), textAlign: TextAlign.center, ), ), ), ); }Copy the code

Run the effect diagram, obviously on the right to do more in line with the effect

2. RPX scheme adaptation

RPX is a fit in the applet. It uses 750px as the design, 1rpx= screen width /750, and all other units are RPX units.

  • Whatever screen it is, 750 pieces
  • On iPhone8:1rpx = 375/750 = 0.5px
  • On iPhone12proMax: 1rpx = 428/750 = 0.571px

You can calculate an RPX by multiplying your size and RPX units: 300px width: 3002rpx

  • It worked out on the iPhone8300px
  • The result was calculated on the iPhone12proMax342.6 px.

As you can see from the calculations, there are significant statistical differences.

Here, too, we encapsulate a class Adapt that directly captures the information on the screen

class Adapt { static MediaQueryData _mediaQueryData = MediaQueryData(); static double screenWidth = 0; static double screenHeight = 0; static double rpx = 0; static double px = 0; static void initialize(BuildContext context, {double standardWidth = 750}) { _mediaQueryData = MediaQuery.of(context); screenWidth = _mediaQueryData.size.width; screenHeight = _mediaQueryData.size.height; rpx = screenWidth / standardWidth; px = screenWidth / standardWidth * 2; } // Static double setPx(double size) {return adapt. RPX * size * 2; } // Set static double setRpx(double size) {return Adapt. RPX * size; }}Copy the code

The sample code

And the above requirements are the same, the final effect of adaptation is the same

@override Widget build(BuildContext context) { Adapt.initialize(context); Return Scaffold(appBar: appBar (title: const Text(' screen fit '),), body: Center(Child: Container(width: Adapt.setPx(300), height: Adapt.setPx(300), color: Colors.orange, alignment: Alignment.center, child: Text( 'Hello Word', style: TextStyle(fontSize: Adapt.setPx(30)), textAlign: TextAlign.center, ), ), ), ); }Copy the code

Note: The context must be used in the Widget that already has the MaterialApp, otherwise it will not work. I’ve defined the default size of the renderer to be 375*667, where you can customize the width of the renderer.

3. Flutter_screenutil plug-in

  • Pubspec. Introduced in yaml
Flutter_screenutil: ^ 5.0.1Copy the code
  • Initialize the Widget with the Context in the Widget that already has the MaterialApp
ScreenUtil.init(context, width: 750, height: 1334, allowFontScaling: false);
Copy the code

The sample code

Container(
   width: ScreenUtil().setWidth(300),
   height: ScreenUtil().setHeight(300)
 }
Copy the code
Text(
  'Hello Word',
  style: TextStyle(fontSize: ScreenUtil.getInstance().setSp(30)),
  textAlign: TextAlign.center,
)
Copy the code

For more information, please refer to pub.flutter-io.cn/packages/fl…

Not clear in the UI design px, pt, ppi, dpi, dp, the relationship between the sp can refer to this article: www.jianshu.com/p/2871c48c6…