skip to Main Content

I have a Flutter app and now I want to make a web version of it when I am trying to run it the web app is occupying a full desktop screen which disturbs the design. This is the code that I am using

MediaQuery(
    data: new MediaQueryData(),
    child: MaterialApp(
        home: ScreenUtilInit(
            splitScreenMode: true,
            designSize: const Size(390, 844),
            minTextAdapt: true,
            builder: (context, child) {
              return MainHomePageN();
            })))

I want the web view to be similar to the height and width of a mobile screen and the remaining screen to be black. So is there a way to achieve so by adding a constrain at a single place.

6

Answers


  1. I guess this should do it:

    ConstrainedBox(
      constraints: const BoxConstraints(maxWidth: 390),
      child: const ScreenUtilInit(
      //...
      ),
    );
    
    Login or Signup to reply.
  2. In general, just wrapping your entire app in a SizedBox that is in a Center should work, for example

    Center(
      child: SizedBox(
        height: 844,
        width: 390,
        child: MediaQuery(
          ...
        )
      )
    )
    

    But I’m not familiar ScreenUtilInit, and it might be that the inner workings of it doesn’t work well with this solution.

    Login or Signup to reply.
  3. This will show the mobile design in web, by adjusting width:

    Code:

    import 'package:flutter/cupertino.dart';
    import 'package:flutter/material.dart';
    
    import 'dart:ui' as ui;
    
    class MobileDesignWidget extends StatelessWidget {
      final maxWebAppRatio = 4.8 / 6.0;
      final minWebAppRatio = 9.0 / 16.0;
    
      final Widget child;
    
      MobileDesignWidget({
        required this.child,
      });
    
      @override
      Widget build(BuildContext context) {
        return LayoutBuilder(
          builder: (context, constraints) {
            if (constraints.maxHeight < constraints.maxWidth) {
              return Container(
                alignment: Alignment.center,
                child: ClipRect(
                  child: AspectRatio(
                    aspectRatio: getCurrentWebAppRatio(),
                    child: child,
                  ),
                ),
              );
            }
            return child;
          },
        );
      }
    
      double getCurrentWebAppRatio() {
        double currentWebAppRatio = minWebAppRatio;
    
        // Fixed ratio for Web
        var physicalScreenSize = ui.window.physicalSize;
        var physicalWidth = physicalScreenSize.width;
        var physicalHeight = physicalScreenSize.height;
    
        currentWebAppRatio = physicalWidth / physicalHeight;
        if (currentWebAppRatio > maxWebAppRatio) {
          currentWebAppRatio = maxWebAppRatio;
        } else if (currentWebAppRatio < minWebAppRatio) {
          currentWebAppRatio = minWebAppRatio;
        }
        return currentWebAppRatio;
      }
    }
    

    Use it like this :

      @override
      Widget build(BuildContext context) {
        return MobileDesignWidget(
          child: /*your scaffold*/,
        );
      }
    
    Login or Signup to reply.
  4. I suppose this is what you are trying to achieve, but without a design/picture/image is hard to know.

    void main() => runApp(const MyApp());
    
    class MyApp extends StatelessWidget {
      const MyApp({super.key});
    
      static const String _title = 'Flutter Code Sample';
    
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: _title,
          home: kIsWeb
              ? Row(children: const [
                  Spacer(),
                  SizedBox(
                    width: 390,
                    child: YourWidget(...),
                  ),
                  Spacer(),
                ])
              : ScreenUtilInit(...),
        );
      }
    }
    

    so, if you are running on web don’t use ScreenUtilInit (I haven’t used that package before), so you can set the width you want and fill the remaining space with a black color.

    Login or Signup to reply.
  5. I think there are many ways to achieve it. But to adapt only the web code and change the minimal of original code lets try with LayoutBuilder.
    We dont have clues about your original code here, but add a variable in constructor of your screens. They will be double? width and double? height. The trick will be: If we are on web, we will have a Layoutbuilder passing custom width and custom height.
    So in initState of your screens, check:

    @override
    
    
    void initState() {
        if (widget.width != null) {
          yourOriginalWidthVariable = widget.width; //receive the custom size from layoutBuilder simulating desirable screen size 
          yourOriginalHeightVariable = widget.height;
        } else {
          yourOriginalWidthVariable = MediaQuery.of(context).size.width; //receive the screen size
          yourOriginalWidthVariable = MediaQuery.of(context).size.height;
        }
        super.initState();
      }
    

    With this we have setup the screen size. Now we Just need to insert the black feature in each side. So, in your main (or in a root point) add a LayoutBuilder. I will give you a sample. Lets say you will place it in your main.dart file:

    return MaterialApp(
        onGenerateRoute: route.controller,
        initialRoute: route.indexPage,
        title: 'your app name',
        debugShowCheckedModeBanner: false,
        theme: ThemeData(
          colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
          useMaterial3: true,
        ),
        home: LayoutBuilder(
        builder: (BuildContext context, BoxConstraints constraints) {
          width = constraints.maxWidth;
          height = constraints.maxHeight;
          if(kIsWeb){
            width = width&*0.25;// adjust to better simulate the mobile screen. Needs to test
            height = height*0.9; //the same
          }
          return SizedBox(
           height: constraints.maxHeight; //ensure allways max height
           width: constraints.maxWidth;// ensure always max width
           child: Row(
            children: [
             Expanded(
              child: Container(
              color: Colors.black)
             ),
             SizedBox(
             width:width, //will receive the size of your desire
             child: yourIndexScreen(width: kisweb ? width : null, height: kisWeb ? height : null); //pass the width and height if is web
            ),
             Expanded(
              child: Container(
              color: Colors.black)
             ),
            ]           
          ),
          );
          
        },
      ),
      );
    
    Login or Signup to reply.
  6. The issue with your approach is that you’re setting that size only to MainHomePageN. The moment you push a new screen on the stack, it no longer has those sizes. (I’m not familiar with ScreenUtilInit so I might be wrong)

    A very over-engineered solution would be to use auto_route like this:

    class WidgetAtTheTopOfTheApp extends StatelessWidget {
      const WidgetAtTheTopOfTheApp({super.key});
    
      @override
      Widget build(BuildContext context) {
        return const SizedBox(
          width: 500,
          child: AutoRouter(),
        );
      }
    }
    

    Then in the routing file you’d have something like this:

    @MaterialAutoRouter(
      replaceInRouteName: 'Screen,Route',
      routes: <AutoRoute>[
        AutoRoute(
          path: '/',
          children: [
            AutoRoute(
              path: '',
              page: LandingScreen,
            ),
            ... other screens and stuff
          ],
          page: WidgetAtTheTopOfTheApp,
        ),
      ],
    )
    

    Please check the documentation of the package, because I have not tested this code yet.

    Another approach is to simply create a widget with the desired size which you put at the top of each scaffold. (This will take a little more refactoring)

    class WidgetAtTheTopOfTheScaffold extends StatelessWidget {
      final Widget child;
      const WidgetAtTheTopOfTheScaffold({super.key, required this.child});
    
      @override
      Widget build(BuildContext context) {
        return SizedBox(
          width: 500,
          child: child,
        );
      }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search