flutter_screenutil

repository·master·Indexed 26 days ago

https://github.com/openflutter/flutter_screenutil

A Flutter plugin designed to adapt screen and font sizes to ensure UI layouts remain consistent across different device screen sizes. It provides tools for scaling dimensions (w, h, r, sw, sh) and font sizes (sp), along with responsive widgets like RPadding, REdgeInsets, and RSizedBox. The library includes ScreenUtilInit for initialization and supports advanced rebuild logic and font size resolution strategies.

Tokens
5.6K
Snippets
13
Records
31
Agent score
83%

What's inside flutter_screenutil

  1. Initialize ScreenUtil for Hybrid/Theme Support

    master

    If you need to support font adaptation within the textTheme of an app theme (common in hybrid development), use the second initialization method:

    1. Call await ScreenUtil.ensureScreenSize(); in your main() function.
    2. Use ScreenUtil.init(context) inside the builder of your MaterialApp.
    void main() async {
      // Add this line
      await ScreenUtil.ensureScreenSize();
      runApp(MyApp());
    }
    
    // Inside MaterialApp builder
    builder: (ctx, child) {
      ScreenUtil.init(ctx);
      return Theme(
        data: ThemeData(
          primarySwatch: Colors.blue,
          textTheme: TextTheme(bodyText2: TextStyle(fontSize: 30.sp)),
        ),
        child: HomePage(title: 'FlutterScreenUtil Demo'),
      );
    }
  2. Prevent font scaling with system accessibility settings

    master

    By default, .sp scales with the system's font size accessibility settings. To prevent this and keep font sizes constant, you can either set textScaleFactor: 1.0 on a specific Text widget or wrap a widget tree in a MediaQuery that overrides the textScaleFactor.

    // Option 1: For a single Text widget
    Text("text", textScaleFactor: 1.0)
    
    // Option 2: For a specific widget subtree
    MediaQuery(
      data: MediaQuery.of(context).copyWith(textScaleFactor: 1.0),
      child: AnyWidget(),
    )
    
    // Option 3: Globally in MaterialApp builder
    MaterialApp(
      builder: (context, widget) {
        return MediaQuery(
          data: MediaQuery.of(context).copyWith(textScaleFactor: 1.0),
          child: widget,
        );
      },
      home: HomePage(),
    )
  3. Initialize ScreenUtil using ScreenUtilInit

    master

    The recommended way to initialize the library is using the ScreenUtilInit widget at the root of your application (e.g., in your MaterialApp). This allows you to set the designSize (the dimensions of your UI design draft in dp) and provides a builder to construct your app.

    Key properties:

    • designSize: The size of the device screen in the design draft (e.g., Size(360, 690)).
    • minTextAdapt: Whether to adapt text according to the minimum of width and height.
    • splitScreenMode: Support for split screen mode.
    • builder: A function returning a Widget (usually MaterialApp).
    void main() => runApp(MyApp());
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return ScreenUtilInit(
          designSize: Size(360, 690),
          minTextAdapt: true,
          splitScreenMode: true,
          builder: () => MaterialApp(
            // ... other code
            builder: (context, widget) {
              // Add this line to make ScreenUtil sensitive to screen changes
              ScreenUtil.setContext(context);
              return MediaQuery(
                // Setting font does not change with system font size
                data: MediaQuery.of(context).copyWith(textScaleFactor: 1.0),
                child: widget!,
              );
            },
          ),
        );
      }
    }
  4. Initialize ScreenUtil manually with ScreenUtil.init

    master

    For hybrid development or specific use cases where ScreenUtilInit is not used, you can manually initialize the library using ScreenUtil.init. This is typically done within a build method or a StatefulWidget's initState using BoxConstraints from a LayoutBuilder or MediaQuery.

    @override
    Widget build(BuildContext context) {
      ScreenUtil.init(
          BoxConstraints(
              maxWidth: MediaQuery.of(context).size.width,
              maxHeight: MediaQuery.of(context).size.height),
          designSize: Size(360, 690),
          context: context,
          orientation: Orientation.portrait);
      return Scaffold();
    }
  5. Customize iOS Launch Screen Assets

    master

    To customize the iOS launch screen, you can either replace the image files directly in the example/ios/Runner/Assets.xcassets/LaunchImage.imageset/ directory or use Xcode for a visual approach:

    1. Open the iOS project in Xcode using the command: open ios/Runner.xcworkspace.
    2. In the Project Navigator, select Runner/Assets.xcassets.
    3. Drag and drop your desired images into the asset catalog.
    open ios/Runner.xcworkspace
  6. Initialize ScreenUtil manually for hybrid or specific use cases

    master

    If you cannot use ScreenUtilInit (e.g., in hybrid development or when you need to support text adaptation in themes manually), you can initialize it using ScreenUtil.ensureScreenSize() in main and calling ScreenUtil.init(context, designSize: ...) within a builder or a build method.

    void main() async {
      await ScreenUtil.ensureScreenSize();
      runApp(MyApp());
    }
    
    // Inside MaterialApp builder or a Widget's build method:
    ScreenUtil.init(context, designSize: const Size(360, 690));
  7. Install flutter_screenutil

    master

    Add flutter_screenutil to your pubspec.yaml dependencies. Check for the latest version before installing.

    dependencies:
      flutter:
        sdk: flutter
      flutter_screenutil: ^{latest version}
    dependencies:
      flutter:
        sdk: flutter
      # add flutter_screenutil
      flutter_screenutil: ^{latest version}
  8. Initialize ScreenUtilInit

    master

    The recommended way to initialize the library is using the ScreenUtilInit widget. You must provide either a builder, a child, or both. Set the designSize to match your UI design dimensions in dp.

    Key properties:

    • designSize: The size of the device screen in the design draft (e.g., Size(360, 690)).
    • minTextAdapt: Whether to adapt text according to the minimum of width and height.
    • splitScreenMode: Enables support for split screen.
    • builder: A function to return a widget that uses the library (e.g., MaterialApp).
    return ScreenUtilInit(
      designSize: const Size(360, 690),
      minTextAdapt: true,
      splitScreenMode: true,
      builder: (_ , child) {
        return MaterialApp(
          debugShowCheckedModeBanner: false,
          title: 'First Method',
          theme: ThemeData(
            primarySwatch: Colors.blue,
            textTheme: Typography.englishLike2018.apply(fontSizeFactor: 1.sp),
          ),
          home: child,
        );
      },
      child: const HomePage(title: 'First Method'),
    );
  9. Initialize ScreenUtil

    master

    To use ScreenUtil for adaptive sizing, you must initialize it with your UI design dimensions. You can use ScreenUtil.init within a widget tree or ScreenUtil.ensureScreenSizeAndInit to wait for the window size to be available (recommended for splash screens or bootstrap logic).

    Common parameters:

    • designSize: The size of the phone in your UI design (default is Size(360, 690)).
    • splitScreenMode: Whether to handle split-screen mode.
    • minTextAdapt: Whether to adapt text based on the smaller scale factor.
    • fontSizeResolver: A custom function to resolve font sizes.
  10. Widget testing with ScreenUtil (Version 5.9.0+)

    master

    When writing widget tests that depend on flutter_screenutil, you must use tester.pumpAndSettle() to ensure animations and state changes settle correctly and to avoid unexpected errors.

    testWidgets('Should ensure widgets settle correctly', (WidgetTester tester) async {
      await tester.pumpWidget(
        const MaterialApp(
          home: ScreenUtilInit(
            child: MyApp(),
          ),  
        ),
      );
      await tester.pumpAndSettle();
      // Continue with assertions
    });