skip to Main Content

Because there is still not support for multiple screens (https://github.com/flutter/flutter/issues/30701) I need to find a way to build application based on screen size.

I need to build different widgets based on screen size, before building MaterialApp.
Is there a way to check the screen size and not to rebuild the app ?

Here is the code:

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    final bool isDualScreen =
        MediaQuery.sizeOf(context).height > MediaQuery.sizeOf(context).width;

    if (isDualScreen) {
      return const DualScreen();
    }

    return const MainAppWidget();
  }
}

class MainAppWidget extends StatelessWidget {
  const MainAppWidget({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class DualScreen extends StatelessWidget {
  const DualScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.transparent,
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.center,
        children: [
          Material(
            color: Colors.transparent,
            child: SizedBox(
                height: MediaQuery.of(context).size.height / 2,
                child: Container()),
          ),
          const Expanded(
            child: MainAppWidget(),
          ),
        ],
      ),
    );
  }
}

$ flutter doctor
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 3.16.0, on Ubuntu 23.10 6.5.0-13-generic, locale
    en_US.UTF-8)
[✓] Android toolchain - develop for Android devices (Android SDK version 34.0.0)
[✓] Chrome - develop for the web
[✓] Linux toolchain - develop for Linux desktop
[✓] Android Studio (version 2022.3)
[✓] IntelliJ IDEA Community Edition (version 2023.2)
[✓] VS Code (version unknown)
    ✗ Unable to determine VS Code version.
[✓] Connected device (2 available)
[✓] Network resources

• No issues found!

enter image description here

2

Answers


  1. For that I recommend using getx here is an example:

    GetMaterialApp -> SwitchScreen -> [DualScreen || MainAppWidget]

    import 'package:flutter/material.dart';
    import 'package:get/get.dart';
    
    void main() {
      runApp(const MyApp());
    }
    
    class MyApp extends StatelessWidget {
      const MyApp({super.key});
    
      // This widget is the root of your application.
      @override
      Widget build(BuildContext context) {
        return const GetMaterialApp(
          title: 'Flutter Demo',
          home: SwitchScreen(),
        );
      }
    }
    
    class SwitchScreen extends StatelessWidget {
      const SwitchScreen({super.key});
    
      @override
      Widget build(BuildContext context) {
        return Get.height > Get.width ? const DualScreen() : const MainAppWidget();
      }
    }
    
    class MainAppWidget extends StatelessWidget {
      const MainAppWidget({super.key});
    
      @override
      Widget build(BuildContext context) {
        return const Scaffold(body: Text("Home page"));
      }
    }
    
    class DualScreen extends StatelessWidget {
      const DualScreen({super.key});
    
      @override
      Widget build(BuildContext context) {
        return Container(
          color: Colors.transparent,
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.center,
            children: [
              Material(
                color: Colors.transparent,
                child: SizedBox(
                    height: MediaQuery.of(context).size.height / 2,
                    child: Container()),
              ),
              const Expanded(
                child: MainAppWidget(),
              ),
            ],
          ),
        );
      }
    }
    

    if no want use GETX you can create a sinlgeton for take only the first size

    example:

    import 'package:flutter/material.dart';
    
    void main() {
      runApp(const MyApp());
    }
    
    class MyApp extends StatelessWidget {
      const MyApp({super.key});
    
      // This widget is the root of your application.
      @override
      Widget build(BuildContext context) {
        // final WinDual winDual = WinDual(context);
        return const MaterialApp(
          title: 'Flutter Demo',
          home: SwitchScreen(),
        );
      }
    }
    
    ///Singleton class to check if the device is dual screen or not
    ///
    class WinDual {
      static WinDual? _appData;
    
      factory WinDual(BuildContext context) {
        _appData ??= WinDual._internal(context);
        return _appData!;
      }
      bool isDual = false;
      late BuildContext context;
    
      WinDual._internal(BuildContext context) {
        isDual =
            MediaQuery.of(context).size.height > MediaQuery.of(context).size.width;
      }
    }
    
    class SwitchScreen extends StatelessWidget {
      const SwitchScreen({super.key});
    
      @override
      Widget build(BuildContext context) {
        ///invoke the WinDual class to check if the device is dual screen or not
        ///it only looks at the size the first time it is invoked
        return WinDual(context).isDual ? const DualScreen() : const MainAppWidget();
      }
    }
    
    class MainAppWidget extends StatelessWidget {
      const MainAppWidget({super.key});
    
      @override
      Widget build(BuildContext context) {
        return const Scaffold(body: Text("Home page"));
      }
    }
    
    class DualScreen extends StatelessWidget {
      const DualScreen({super.key});
    
      @override
      Widget build(BuildContext context) {
        return Container(
          color: Colors.transparent,
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.center,
            children: [
              Material(
                color: Colors.transparent,
                child: SizedBox(
                    height: MediaQuery.of(context).size.height / 2,
                    child: Container()),
              ),
              const Expanded(
                child: MainAppWidget(),
              ),
            ],
          ),
        );
      }
    }
    
    Login or Signup to reply.
  2. If you’re asking for a way to get the screen size without rebuilding when it changes, you can use WidgetsBinding:

    Size screenSize = WidgetsBinding.instance.window.physicalSize;
    double width = screenSize.width;
    double height = screenSize.height;
    

    You could rewrite your MyApp widget like this:

    class MyApp extends StatefulWidget {
      const MyApp({super.key});
    
      @override
      _MyAppState createState() => _MyAppState();
    }
    
    class _MyAppState extends State<MyApp> {
      late bool isDualScreen;
    
      @override
      void initState() {
        super.initState();
        final Size screenSize = WidgetsBinding.instance.window.physicalSize /
            WidgetsBinding.instance.window.devicePixelRatio;
        isDualScreen = screenSize.height > screenSize.width;
      }
    
      @override
      Widget build(BuildContext context) {
        if (isDualScreen) {
          return const DualScreen();
        }
        return const MainAppWidget();
      }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search