Giter Site home page Giter Site logo

filledstacks / responsive_builder Goto Github PK

View Code? Open in Web Editor NEW
483.0 11.0 82.0 2.48 MB

A set of widgets to make responsive UI building in flutter more readable

License: MIT License

Kotlin 0.16% Swift 0.53% Objective-C 0.05% Dart 60.46% HTML 0.24% CMake 10.85% C++ 26.74% C 0.97%

responsive_builder's Introduction

Responsive UI in Flutter Banner

Responsive Builder 💻➡️🖥➡️📱➡️⌚️

The responsive builder package contains widgets that allows you to create a readable responsive UI. The package is inspired by the Responsive UI Flutter series created by FilledStacks.

It aims to provide you with widgets that make it easy to build different UI's along two different Axis. Orientation x ScreenType. This means you can have a separate layout for Mobile - Landscape, Mobile - Portrait, Tablet - Landscape and Tablet-Portrait.

If you follow along with the series you will have a complete understanding of how it's built and how to use it. Part 2 goes over how we build the example included in this project.

Responsive Layout Preview

Installation

Add responsive_builder as dependency to your pubspec file.

responsive_builder:

Usage

This package provides a widget called ResponsiveBuilder that provides you with a builder function that returns the current SizingInformation. The SizingInformation includes the DeviceScreenType, screenSize and localWidgetSize. This can be used for fine grained responsive control from a view level down to per widget responsive level.

Responsive Builder

The ResponsiveBuilder is used as any other builder widget.

// import the package
import 'package:responsive_builder/responsive_builder.dart';

// Use the widget
ResponsiveBuilder(
    builder: (context, sizingInformation) {
      // Check the sizing information here and return your UI
          if (sizingInformation.deviceScreenType == DeviceScreenType.desktop) {
          return Container(color:Colors.blue);
        }

        if (sizingInformation.deviceScreenType == DeviceScreenType.tablet) {
          return Container(color:Colors.red);
        }

        if (sizingInformation.deviceScreenType == DeviceScreenType.watch) {
          return Container(color:Colors.yellow);
        }

        return Container(color:Colors.purple);
      },
    },
  );
}

This will return different colour containers depending on which device it's being shown on. A simple way to test this is to either run your code on Flutter web and resize the window or add the device_preview package and view on different devices.

Orientation Layout Builder

This widget can be seen as a duplicate of the OrientationBuilder that comes with Flutter, but the point of this library is to help you produce a readable responsive UI code base. As mentioned in the follow along tutorial I didn't want responsive code riddled with conditionals around orientation, MediaQuery or Renderbox sizes. That's why I created this builder.

The usage is easy. Provide a builder function that returns a UI for each of the orientations.

// import the package
import 'package:responsive_builder/responsive_builder.dart';

// Return a widget function per orientation
OrientationLayoutBuilder(
  portrait: (context) => Container(color: Colors.green),
  landscape: (context) => Container(color: Colors.pink),
),

This will return a different coloured container when you swap orientations for your device. In a more readable manner than checking the orientation with a conditional.

Sometimes you want your app to stay in a certain orientation. use mode property in OrientationLayoutBuilder to enforce this.

OrientationLayoutBuilder(
  /// default mode is 'auto'
  mode: info.isMobile
    ? OrientationLayoutBuilderMode.portrait
    : OrientationLayoutBuilderMode.auto,
  ...
),

Screen Type Layout

This widget is similar to the Orientation Layout Builder in that it takes in Widgets that are named and displayed for different screen types.

// import the package
import 'package:responsive_builder/responsive_builder.dart';

// Construct and pass in a widget per screen type
ScreenTypeLayout(
  mobile: Container(color:Colors.blue)
  tablet: Container(color: Colors.yellow),
  desktop: Container(color: Colors.red),
  watch: Container(color: Colors.purple),
);

If you don't want to build all the widgets at once, you can use the widget builder. A widget for the right type of screen will be created only when needed.

// Construct and pass in a widget builder per screen type
ScreenTypeLayout.builder(
  mobile: (BuildContext context) => Container(color:Colors.blue),
  tablet: (BuildContext context) => Container(color:Colors.yellow),
  desktop: (BuildContext context) => Container(color:Colors.red),
  watch: (BuildContext context) => Container(color:Colors.purple),
);

Custom Screen Breakpoints

If you wish to define your own custom break points you can do so by supplying either the ScreenTypeLayout or ResponsiveBuilder widgets with a breakpoints argument.

// import the package
import 'package:responsive_builder/responsive_builder.dart';

//ScreenTypeLayout with custom breakpoints supplied
ScreenTypeLayout(
  breakpoints: ScreenBreakpoints(
    tablet: 600,
    desktop: 950,
    watch: 300
  ),
  mobile: Container(color:Colors.blue)
  tablet: Container(color: Colors.yellow),
  desktop: Container(color: Colors.red),
  watch: Container(color: Colors.purple),
);

To get a more in depth run through of this package I would highly recommend watching this tutorial where I show you how it was built and how to use it.

Global Screen Breakpoints

If you want to set the breakpoints for the responsive builders once you can call the line below before the app starts, or wherever you see fit.

void main() {
  ResponsiveSizingConfig.instance.setCustomBreakpoints(
    ScreenBreakpoints(desktop: 800, tablet: 550, watch: 200),
  );
  runApp(MyApp());
}

This will then reflect the screen types based on what you have set here. You can then still pass in custom break points per ScreenTypeLayout if you wish that will override these values for that specific ScreenTypeLayout builder.

Screen Type specific values

Sometimes you don't want to write an entire new UI just to change one value. Say for instance you want your padding on mobile to be 10, on the tablet 30 and desktop 60. Instead of re-writing UI you can use the getValueForScreenType function. This is a generic function that will return your value based on the screen type you're on. Take this example below.

Container(
  padding: EdgeInsets.all(10),
  child: Text('Best Responsive Package'),
)

What if you ONLY want to update the padding based on the device screen size. You could do.

var deviceType = getDeviceType(MediaQuery.of(context).size);
var paddingValue = 0;
switch(deviceType) {
  case DeviceScreenType.desktop:
    paddingValue = 60;
    break;
  case DeviceScreenType.tablet:
    paddingValue = 30;
    break;
  case DeviceScreenType.mobile:
    paddingValue = 10;
    break;
}
Container(
  padding: EdgeInsets.all(paddingValue),
  child: Text('Best Responsive Package'),
)

Ooooorrrr, you can use shorthand for that.

Container(
  padding: EdgeInsets.all(getValueForScreenType<double>(
                context: context,
                mobile: 10,
                tablet: 30,
                desktop: 60,
              )),
  child: Text('Best Responsive Package'),
)

It will return the value you give it for the DeviceScreen you're viewing the app on. For instance you want to hide a widget on mobile and not on tablet?

getValueForScreenType<bool>(
    context: context,
    mobile: false,
    tablet: true,
  ) ? MyWidget() : Container()

That will return true on tablet devices and false on mobile.

Responsive Sizing

In addition to providing specific layouts per device type there's also the requirement to size items based on the screen width or height. To use this functionality we added some responsive extensions. To use this wrap your Material or Cupertino App with the ResponsiveApp widget.

ResponsiveApp(
  builder: (context) => MaterialApp(
    ...
  )
)

This is required to use the following functionality.

Responsive Sizing

To use the responsive sizing all you need to do is the following.

import 'package:responsive_builder/responsive_builder.dart';

SizedBox(height: 30.screenHeight); // Or sh for shorthand
Text('respond to width', style: TextStyle(fontSize: 10.sw));

Use the number you want as the percentage and call the screenHeight or screenWidth extension. These also have shorthand extensions sh and sw.

Contribution

  1. Fork it!
  2. Create your feature branch: git checkout -b my-new-feature
  3. Commit your changes: git commit -am 'Add some feature'
  4. Push to the branch: git push origin my-new-feature
  5. Submit a pull request.

responsive_builder's People

Contributors

azmoza avatar bierbaumtim avatar chimon2000 avatar disparta avatar eimen2018 avatar ferrarafer avatar filledstacks avatar hajajmaor avatar mareklat avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

responsive_builder's Issues

different results from the same code

Hi, thanks for the plugin and the tutorials.
I'm following your responsive web tutorial and I'm experiencing a different behaviour from the sample code from your flutter web_part3 . Basically when resizing the Chrome window to the point that is tablet view the CallToAction takes the whole horizontal space as when on mobile, but the NavBar hasn't changed to mobile yet. In your code the size stays the same as when in Desktop.
I checked the code file by file and seems to be all the same.
Could you please have a look at my code at https://github.com/vinnytwice/flutter_web_test ?
Thank you very much again.
Cheers.

[FLUTTER WEB] Cannot detect landscape mode on mobile.

I have read the docs about your package. I decided using it for my website. But one thing i wanna know.
Is this package can detect phone or tablet screen but in landscape mode. Thank you very much

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: Text(widget.title),
      ),
      body: ScreenTypeLayout.builder(
        mobile: (BuildContext context) => OrientationLayoutBuilder(
          portrait: (context) => Container(color: Colors.green),
          landscape: (context) => Container(color: Colors.orange),
        ),
        tablet: (BuildContext context) => Container(color: Colors.yellow),
        desktop: (BuildContext context) => Container(color: Colors.red),
        watch: (BuildContext context) => Container(color: Colors.purple),
      ),
    );
  }
}

I tried this code above but it's not working as my expectation

image
I think it should be orange

Is the package designed for web?

I have been developing a website in flutter using this package. It works well on localhost but fails on github pages. Is there anything I can do to make it compatible with web?

Support for null-safety

Since Dart 2.12.0 beta landed in flutter beta channel, which brings sound null-safety it would be nice to have null-safety support on this package. This would enable everyone to start migrating their apps to null-safety.

I also would like to work on this and will open an pull request tomorrow.

Suggestion for getValueForScreenType method and similar ones

Current case:

getValueForScreenType<Widget>(context: context, desktop: myWidget, mobile: anotherWidget, tablet: anotherWidget, watch: anotherWidget);

It could be improved with a parameter assigning a default value for other screen types being null , example:

getValueForScreenType<Widget>(context: context, desktop: myWidget, byDefault: anotherWidget);

Web?

Is this applicable to flutter web?

Allow platform specific layouts

It would be nice to be able to provide a different layout for iOS, Android and web. Something like:

ScreenTypeLayout(
  // Platforms
  ios: Container(color:Colors.white)
  android: Container(color:Colors.black)
  web: Container(color:Colors.green)
  ...
  // Screen types
  mobile: Container(color:Colors.blue)
  tablet: Container(color: Colors.yellow),
  desktop: Container(color: Colors.red),
  watch: Container(color: Colors.purple),
);

There is some overlap with the existing screen types but the platform is another dimension of the layout and you can have any combination of "platform" and "screen type" there. It could even be more fine grained like:

desktopWeb: Container(color:Colors.red),
mobileWeb: Container(color:Colors.blue)

Unstable on Windows

Hello,
Thanks your effort for this awesome package!
It works perfectly on the web. thanks!
I found an unintentional behavior on Windows, When I adjusted the height instead of the width.
Please check

         ScreenTypeLayout(
                breakpoints:
                    ScreenBreakpoints(tablet: 773, desktop: 774, watch: 300),
                mobile: Container(
                  color: Colors.blue,
                  child: Center(child: Text('mobile')),
                ),
                // tablet: Container(
                //   color: Colors.yellow,
                //   child: Center(child: Text('tablet')),
                // ),
                desktop: Container(
                  color: Colors.red,
                  child: Center(child: Text('desktop')),
                ),
                watch: Container(
                  color: Colors.purple,
                  child: Center(child: Text('watch')),
                ),
              ),

Normal screen1 ( mobile size )

image

Unintentional screen2 ( just adjust height of screen1 )

image

Thanks!!

Passing breakpoints through context?

Currently if we need custom breakpoints, we will need to provide the ScreenBreakpoints object to every ScreenTypeLayout calls. It would be nice if we can use something like BreakpointProvider to provide it at the topmost of widget tree, then every instance of ScreenTypeLayout can get it internally.

DeviceScreenType should change depending on the device selected with device_preview

Hello,
When I try to use device_preview with your tools on my galaxy tab s4, I always have the "tablet" widget that is used no matter what device I'm trying to simulate.
According to the documentation, it should work.
How to use device_preview with responsive_builder please?
Thanks

responsive_builder: ^0.3.0
device_preview: ^0.5.5

LateInitializationError: Field 'preferDesktop' has not been initialized.

Error after updating from
responsive_builder: ^0.4.3 to responsive_builder: ^0.6.3

Error when the screen size is small on desktop
LateInitializationError: Field 'preferDesktop' has not been initialized.

Full log

======== Exception caught by widgets library =======================================================
The following LateError was thrown building LayoutBuilder:
LateInitializationError: Field 'preferDesktop' has not been initialized.

The relevant error-causing widget was: 
  LayoutBuilder LayoutBuilder:file:///home/guyluz/.pub-cache/hosted/pub.dev/responsive_builder-0.6.3/lib/src/widget_builders.dart:28:12
When the exception was thrown, this was the stack: 
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart 266:49  throw_
packages/responsive_builder/src/responsive_wrapper.dart 45:20                 get preferDesktop
packages/responsive_builder/src/widget_builders.dart 170:45                   <fn>
packages/responsive_builder/src/widget_builders.dart 40:21                    <fn>
packages/flutter/src/widgets/layout_builder.dart 119:70                       layoutCallback
packages/flutter/src/widgets/framework.dart 2682:19                           buildScope
packages/flutter/src/widgets/layout_builder.dart 153:5                        [_layout]
packages/flutter/src/rendering/object.dart 2300:59                            <fn>
packages/flutter/src/rendering/object.dart 1056:15                            [_enableMutationsToDirtySubtrees]
packages/flutter/src/rendering/object.dart 2300:7                             invokeLayoutCallback
packages/flutter/src/widgets/layout_builder.dart 228:7                        rebuildIfNecessary
packages/flutter/src/widgets/layout_builder.dart 313:5                        performLayout
packages/flutter/src/rendering/object.dart 2189:7                             layout
packages/flutter/src/rendering/box.dart 2430:11                               layout
packages/flutter/src/rendering/layout_helper.dart 56:10                       layoutChild
packages/flutter/src/rendering/stack.dart 595:43                              [_computeSize]
packages/flutter/src/rendering/stack.dart 622:12                              performLayout
packages/flutter/src/rendering/object.dart 2189:7                             layout
packages/flutter/src/rendering/box.dart 2430:11                               layout
packages/flutter/src/rendering/custom_layout.dart 171:10                      layoutChild
packages/flutter/src/material/scaffold.dart 1080:7                            performLayout
packages/flutter/src/rendering/custom_layout.dart 240:7                       [_callPerformLayout]
packages/flutter/src/rendering/custom_layout.dart 410:14                      performLayout
packages/flutter/src/rendering/object.dart 2189:7                             layout
packages/flutter/src/rendering/box.dart 2430:11                               layout
packages/flutter/src/rendering/proxy_box.dart 120:7                           performLayout
packages/flutter/src/rendering/object.dart 2189:7                             layout
packages/flutter/src/rendering/box.dart 2430:11                               layout
packages/flutter/src/rendering/proxy_box.dart 120:7                           performLayout
packages/flutter/src/rendering/proxy_box.dart 1467:11                         performLayout
packages/flutter/src/rendering/object.dart 2189:7                             layout
packages/flutter/src/rendering/box.dart 2430:11                               layout
packages/flutter/src/rendering/layout_helper.dart 56:10                       layoutChild
packages/flutter/src/rendering/stack.dart 595:43                              [_computeSize]
packages/flutter/src/rendering/stack.dart 622:12                              performLayout
packages/flutter/src/rendering/object.dart 2189:7                             layout
packages/flutter/src/rendering/box.dart 2430:11                               layout
packages/flutter/src/rendering/proxy_box.dart 120:7                           performLayout
packages/flutter/src/rendering/object.dart 2189:7                             layout
packages/flutter/src/rendering/box.dart 2430:11                               layout
packages/flutter/src/rendering/proxy_box.dart 120:7                           performLayout
packages/flutter/src/rendering/proxy_box.dart 4802:11                         performLayout
packages/flutter/src/rendering/object.dart 2189:7                             layout
packages/flutter/src/rendering/box.dart 2430:11                               layout
packages/flutter/src/widgets/layout_builder.dart 315:7                        performLayout
packages/flutter/src/rendering/object.dart 2189:7                             layout
packages/flutter/src/rendering/box.dart 2430:11                               layout
packages/flutter/src/rendering/proxy_box.dart 120:7                           performLayout
packages/flutter/src/rendering/object.dart 2189:7                             layout
packages/flutter/src/rendering/box.dart 2430:11                               layout
packages/flutter/src/rendering/proxy_box.dart 297:7                           performLayout
packages/flutter/src/rendering/object.dart 2189:7                             layout
packages/flutter/src/rendering/box.dart 2430:11                               layout
packages/flutter/src/rendering/proxy_box.dart 120:7                           performLayout
packages/flutter/src/rendering/object.dart 2189:7                             layout
packages/flutter/src/rendering/box.dart 2430:11                               layout
packages/flutter/src/rendering/proxy_box.dart 120:7                           performLayout
packages/flutter/src/rendering/object.dart 2189:7                             layout
packages/flutter/src/rendering/box.dart 2430:11                               layout
packages/flutter/src/rendering/proxy_box.dart 120:7                           performLayout
packages/flutter/src/rendering/object.dart 2189:7                             layout
packages/flutter/src/rendering/box.dart 2430:11                               layout
packages/flutter/src/rendering/proxy_box.dart 120:7                           performLayout
packages/flutter/src/rendering/object.dart 2189:7                             layout
packages/flutter/src/rendering/box.dart 2430:11                               layout
packages/flutter/src/rendering/proxy_box.dart 120:7                           performLayout
packages/flutter/src/rendering/object.dart 2189:7                             layout
packages/flutter/src/rendering/box.dart 2430:11                               layout
packages/flutter/src/rendering/proxy_box.dart 120:7                           performLayout
packages/flutter/src/rendering/object.dart 2189:7                             layout
packages/flutter/src/rendering/box.dart 2430:11                               layout
packages/flutter/src/rendering/proxy_box.dart 120:7                           performLayout
packages/flutter/src/rendering/object.dart 2189:7                             layout
packages/flutter/src/rendering/box.dart 2430:11                               layout
packages/flutter/src/rendering/proxy_box.dart 120:7                           performLayout
packages/flutter/src/rendering/object.dart 2189:7                             layout
packages/flutter/src/rendering/box.dart 2430:11                               layout
packages/flutter/src/rendering/proxy_box.dart 120:7                           performLayout
packages/flutter/src/rendering/object.dart 2189:7                             layout
packages/flutter/src/rendering/box.dart 2430:11                               layout
packages/flutter/src/rendering/proxy_box.dart 120:7                           performLayout
packages/flutter/src/rendering/proxy_box.dart 3815:13                         performLayout
packages/flutter/src/rendering/object.dart 2189:7                             layout
packages/flutter/src/rendering/box.dart 2430:11                               layout
packages/flutter/src/rendering/proxy_box.dart 120:7                           performLayout
packages/flutter/src/rendering/object.dart 2189:7                             layout
packages/flutter/src/rendering/box.dart 2430:11                               layout
packages/flutter/src/widgets/overlay.dart 856:14                              performLayout
packages/flutter/src/rendering/object.dart 2189:7                             layout
packages/flutter/src/rendering/box.dart 2430:11                               layout
packages/flutter/src/rendering/proxy_box.dart 120:7                           performLayout
packages/flutter/src/rendering/object.dart 2189:7                             layout
packages/flutter/src/rendering/box.dart 2430:11                               layout
packages/flutter/src/rendering/proxy_box.dart 120:7                           performLayout
packages/flutter/src/rendering/object.dart 2189:7                             layout
packages/flutter/src/rendering/box.dart 2430:11                               layout
packages/flutter/src/rendering/proxy_box.dart 120:7                           performLayout
packages/flutter/src/rendering/object.dart 2189:7                             layout
packages/flutter/src/rendering/box.dart 2430:11                               layout
packages/flutter/src/rendering/proxy_box.dart 120:7                           performLayout
packages/flutter/src/rendering/object.dart 2189:7                             layout
packages/flutter/src/rendering/box.dart 2430:11                               layout
packages/flutter/src/rendering/proxy_box.dart 120:7                           performLayout
packages/flutter/src/rendering/object.dart 2027:7                             [_layoutWithoutResize]
packages/flutter/src/rendering/object.dart 1020:17                            flushLayout
packages/flutter/src/rendering/binding.dart 516:19                            drawFrame
packages/flutter/src/widgets/binding.dart 865:13                              drawFrame
packages/flutter/src/rendering/binding.dart 381:5                             [_handlePersistentFrameCallback]
packages/flutter/src/scheduler/binding.dart 1289:15                           [_invokeFrameCallback]
packages/flutter/src/scheduler/binding.dart 1218:9                            handleDrawFrame
packages/flutter/src/scheduler/binding.dart 942:7                             <fn>
dart-sdk/lib/_internal/js_dev_runtime/private/isolate_helper.dart 48:19       internalCallback
====================================================================================================

======== Exception caught by widgets library =======================================================
The following LateError was thrown building LayoutBuilder:
LateInitializationError: Field 'preferDesktop' has not been initialized.

The relevant error-causing widget was: 
  LayoutBuilder LayoutBuilder:file:///home/guyluz/.pub-cache/hosted/pub.dev/responsive_builder-0.6.3/lib/src/widget_builders.dart:28:12
When the exception was thrown, this was the stack: 
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart 266:49  throw_
packages/responsive_builder/src/responsive_wrapper.dart 45:20                 get preferDesktop
packages/responsive_builder/src/widget_builders.dart 170:45                   <fn>
packages/responsive_builder/src/widget_builders.dart 40:21                    <fn>
packages/flutter/src/widgets/layout_builder.dart 119:70                       layoutCallback
packages/flutter/src/widgets/framework.dart 2682:19                           buildScope
packages/flutter/src/widgets/layout_builder.dart 153:5                        [_layout]
packages/flutter/src/rendering/object.dart 2300:59                            <fn>
packages/flutter/src/rendering/object.dart 1056:15                            [_enableMutationsToDirtySubtrees]
packages/flutter/src/rendering/object.dart 2300:7                             invokeLayoutCallback
packages/flutter/src/widgets/layout_builder.dart 228:7                        rebuildIfNecessary
packages/flutter/src/widgets/layout_builder.dart 313:5                        performLayout
packages/flutter/src/rendering/object.dart 2189:7                             layout
packages/flutter/src/rendering/box.dart 2430:11                               layout
packages/flutter/src/rendering/layout_helper.dart 56:10                       layoutChild
packages/flutter/src/rendering/stack.dart 595:43                              [_computeSize]
packages/flutter/src/rendering/stack.dart 622:12                              performLayout
packages/flutter/src/rendering/object.dart 2189:7                             layout
packages/flutter/src/rendering/box.dart 2430:11                               layout
packages/flutter/src/rendering/custom_layout.dart 171:10                      layoutChild
packages/flutter/src/material/scaffold.dart 1080:7                            performLayout
packages/flutter/src/rendering/custom_layout.dart 240:7                       [_callPerformLayout]
packages/flutter/src/rendering/custom_layout.dart 410:14                      performLayout
packages/flutter/src/rendering/object.dart 2189:7                             layout
packages/flutter/src/rendering/box.dart 2430:11                               layout
packages/flutter/src/rendering/proxy_box.dart 120:7                           performLayout
packages/flutter/src/rendering/object.dart 2189:7                             layout
packages/flutter/src/rendering/box.dart 2430:11                               layout
packages/flutter/src/rendering/proxy_box.dart 120:7                           performLayout
packages/flutter/src/rendering/proxy_box.dart 1467:11                         performLayout
packages/flutter/src/rendering/object.dart 2189:7                             layout
packages/flutter/src/rendering/box.dart 2430:11                               layout
packages/flutter/src/rendering/layout_helper.dart 56:10                       layoutChild
packages/flutter/src/rendering/stack.dart 595:43                              [_computeSize]
packages/flutter/src/rendering/stack.dart 622:12                              performLayout
packages/flutter/src/rendering/object.dart 2189:7                             layout
packages/flutter/src/rendering/box.dart 2430:11                               layout
packages/flutter/src/rendering/proxy_box.dart 120:7                           performLayout
packages/flutter/src/rendering/object.dart 2189:7                             layout
packages/flutter/src/rendering/box.dart 2430:11                               layout
packages/flutter/src/rendering/proxy_box.dart 120:7                           performLayout
packages/flutter/src/rendering/proxy_box.dart 4802:11                         performLayout
packages/flutter/src/rendering/object.dart 2189:7                             layout
packages/flutter/src/rendering/box.dart 2430:11                               layout
packages/flutter/src/widgets/layout_builder.dart 315:7                        performLayout
packages/flutter/src/rendering/object.dart 2189:7                             layout
packages/flutter/src/rendering/box.dart 2430:11                               layout
packages/flutter/src/rendering/proxy_box.dart 120:7                           performLayout
packages/flutter/src/rendering/object.dart 2189:7                             layout
packages/flutter/src/rendering/box.dart 2430:11                               layout
packages/flutter/src/rendering/proxy_box.dart 297:7                           performLayout
packages/flutter/src/rendering/object.dart 2189:7                             layout
packages/flutter/src/rendering/box.dart 2430:11                               layout
packages/flutter/src/rendering/proxy_box.dart 120:7                           performLayout
packages/flutter/src/rendering/object.dart 2189:7                             layout
packages/flutter/src/rendering/box.dart 2430:11                               layout
packages/flutter/src/rendering/proxy_box.dart 120:7                           performLayout
packages/flutter/src/rendering/object.dart 2189:7                             layout
packages/flutter/src/rendering/box.dart 2430:11                               layout
packages/flutter/src/rendering/proxy_box.dart 120:7                           performLayout
packages/flutter/src/rendering/object.dart 2189:7                             layout
packages/flutter/src/rendering/box.dart 2430:11                               layout
packages/flutter/src/rendering/proxy_box.dart 120:7                           performLayout
packages/flutter/src/rendering/object.dart 2189:7                             layout
packages/flutter/src/rendering/box.dart 2430:11                               layout
packages/flutter/src/rendering/proxy_box.dart 120:7                           performLayout
packages/flutter/src/rendering/object.dart 2189:7                             layout
packages/flutter/src/rendering/box.dart 2430:11                               layout
packages/flutter/src/rendering/proxy_box.dart 120:7                           performLayout
packages/flutter/src/rendering/object.dart 2189:7                             layout
packages/flutter/src/rendering/box.dart 2430:11                               layout
packages/flutter/src/rendering/proxy_box.dart 120:7                           performLayout
packages/flutter/src/rendering/object.dart 2189:7                             layout
packages/flutter/src/rendering/box.dart 2430:11                               layout
packages/flutter/src/rendering/proxy_box.dart 120:7                           performLayout
packages/flutter/src/rendering/object.dart 2189:7                             layout
packages/flutter/src/rendering/box.dart 2430:11                               layout
packages/flutter/src/rendering/proxy_box.dart 120:7                           performLayout
packages/flutter/src/rendering/object.dart 2189:7                             layout
packages/flutter/src/rendering/box.dart 2430:11                               layout
packages/flutter/src/rendering/proxy_box.dart 120:7                           performLayout
packages/flutter/src/rendering/proxy_box.dart 3815:13                         performLayout
packages/flutter/src/rendering/object.dart 2189:7                             layout
packages/flutter/src/rendering/box.dart 2430:11                               layout
packages/flutter/src/rendering/proxy_box.dart 120:7                           performLayout
packages/flutter/src/rendering/object.dart 2189:7                             layout
packages/flutter/src/rendering/box.dart 2430:11                               layout
packages/flutter/src/widgets/overlay.dart 856:14                              performLayout
packages/flutter/src/rendering/object.dart 2189:7                             layout
packages/flutter/src/rendering/box.dart 2430:11                               layout
packages/flutter/src/rendering/proxy_box.dart 120:7                           performLayout
packages/flutter/src/rendering/object.dart 2189:7                             layout
packages/flutter/src/rendering/box.dart 2430:11                               layout
packages/flutter/src/rendering/proxy_box.dart 120:7                           performLayout
packages/flutter/src/rendering/object.dart 2189:7                             layout
packages/flutter/src/rendering/box.dart 2430:11                               layout
packages/flutter/src/rendering/proxy_box.dart 120:7                           performLayout
packages/flutter/src/rendering/object.dart 2189:7                             layout
packages/flutter/src/rendering/box.dart 2430:11                               layout
packages/flutter/src/rendering/proxy_box.dart 120:7                           performLayout
packages/flutter/src/rendering/object.dart 2189:7                             layout
packages/flutter/src/rendering/box.dart 2430:11                               layout
packages/flutter/src/rendering/proxy_box.dart 120:7                           performLayout
packages/flutter/src/rendering/object.dart 2027:7                             [_layoutWithoutResize]
packages/flutter/src/rendering/object.dart 1020:17                            flushLayout
packages/flutter/src/rendering/binding.dart 516:19                            drawFrame
packages/flutter/src/widgets/binding.dart 865:13                              drawFrame
packages/flutter/src/rendering/binding.dart 381:5                             [_handlePersistentFrameCallback]
packages/flutter/src/scheduler/binding.dart 1289:15                           [_invokeFrameCallback]
packages/flutter/src/scheduler/binding.dart 1218:9                            handleDrawFrame
packages/flutter/src/scheduler/binding.dart 942:7                             <fn>
dart-sdk/lib/_internal/js_dev_runtime/private/isolate_helper.dart 48:19       internalCallback
====================================================================================================

======== Exception caught by services library ======================================================
The following assertion was thrown during a platform message callback:
Assertion failed: file:///home/guyluz/snap/flutter/common/flutter/packages/flutter/lib/src/services/raw_keyboard.dart:683:7
event is! RawKeyDownEvent || _keysPressed.isNotEmpty
"Attempted to send a key down event when no keys are in keysPressed. This state can occur if the key event being sent doesn't properly set its modifier flags. This was the event: RawKeyDownEvent#984f6(logicalKey: LogicalKeyboardKey#4b191(keyId: \"0x200000106\", keyLabel: \"Meta Left\", debugName: \"Meta Left\"), physicalKey: PhysicalKeyboardKey#700e3(usbHidUsage: \"0x000700e3\", debugName: \"Meta Left\"), repeat: false) and its data: RawKeyEventDataWeb#b86ed(code: MetaLeft, key: Meta, location: 1, metaState: 0, keyCode: 91)"

When the exception was thrown, this was the stack: 
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart 266:49      throw_
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart 29:3        assertFailed
packages/flutter/src/services/raw_keyboard.dart 683:49                            handleRawKeyEvent
packages/flutter/src/services/hardware_keyboard.dart 951:30                       handleRawKeyMessage
dart-sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart 84:54                runBody
dart-sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart 123:5                _async
packages/flutter/src/services/hardware_keyboard.dart 923:51                       handleRawKeyMessage
packages/flutter/src/services/platform_channel.dart 214:49                        <fn>
dart-sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart 84:54                runBody
dart-sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart 123:5                _async
packages/flutter/src/services/platform_channel.dart 213:58                        <fn>
packages/flutter/src/services/binding.dart 393:35                                 <fn>
dart-sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart 84:54                runBody
dart-sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart 123:5                _async
packages/flutter/src/services/binding.dart 390:98                                 <fn>
lib/_engine/engine/platform_dispatcher.dart 1199:13                               invoke2
lib/ui/channel_buffers.dart 25:12                                                 invoke
lib/ui/channel_buffers.dart 65:7                                                  push
lib/ui/channel_buffers.dart 131:16                                                push
lib/_engine/engine/platform_dispatcher.dart 378:25                                invokeOnPlatformMessage
lib/_engine/engine/raw_keyboard.dart 142:39                                       [_handleHtmlEvent]
lib/_engine/engine/raw_keyboard.dart 12:7                                         <fn>
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart 367:37  _checkAndCall
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart 372:39  dcall
====================================================================================================

How to responsive to the screen width (not shortest width)

Hello,

As Web CSS Media Query, we commonly make web responsive base on the current screen width regardless of orientation. So that we can render different layout for tablet portrait and tablet landscape. How to achieve this requirement with this package. Could you please advise.

Thanks

ipadOs is currently classified as Desktop

ipadOs is classified as Desktop

Since all desktop/notebook have width > height and all tablets has height > width, I think IpadOS fits better if classified as Tablet

Maybe should be nice to change this in the next update

More refined sizing for Mobile Devices

Currently we have only Desktop, Tablet, Mobile and Watch. As we know there are many different sizes in even the mobile devices. I suggest we add a Large, Medium and Small sizing within the mobile devices as an additional builder function to supply.

Pass SizingInformation to the ScreenTypeLayout builders

Hi,

I see in the build method of ScreenTypeLayout, that we have access to the SizingInformation but are not passing it to each builder:

  @override
  Widget build(BuildContext context) {
    return ResponsiveBuilder(
      breakpoints: breakpoints,
      builder: (context, sizingInformation) {
        // If we're at desktop size
        if (sizingInformation.deviceScreenType == DeviceScreenType.desktop) {
          // If we have supplied the desktop layout then display that
          if (desktop != null) return desktop!(context);
          // If no desktop layout is supplied we want to check if we have the size below it and display that
          if (tablet != null) return tablet!(context);
        }

        if (sizingInformation.deviceScreenType == DeviceScreenType.tablet) {
          if (tablet != null) return tablet!(context);
        }

        if (sizingInformation.deviceScreenType == DeviceScreenType.watch &&
            watch != null) {
          return watch!(context);
        }

        // If none of the layouts above are supplied or we're on the mobile layout then we show the mobile layout
        return mobile(context);
      },

Please pass it to the passed in builders, as right now we need to add our own ResponsiveBuilder to get the SizingInformation while the build method of ScreenTypeLayout is already doing that.

P.S. You may as well do the same for RefinedLayoutBuilder.

BTW, I've done it in a fork.

BUG: Breakpoints are not working properly

Hi,

I had a bit of a trouble on Flutter web, with the package. I needed to add custom breakpoints. But my mobile breakpoint did not seem to work.

I looked into the code, and found a bug in the _getDeviceType function.

image

If the breakpoints are matching with the type mobile, it will go through the defaults.

Proposed solution:
image

Request to support for ScreenBreakPoints 'num' Type

Hello!,
I would like to request you to support the num type . (Don't stick to the double.)

Model code

class _ScreenBreakPoints {
  num desktop = 1024;
  num tablet = 775;
  num watch = 200;
}

Controller code

// getter
  num get desktop_breakpoint => app.screenBreakpoints.desktop;
  num get tablet_breakpoint => app.screenBreakpoints.tablet;
  num get watch_breakpoint => app.screenBreakpoints.watch;

// constuctor
  Controller() {
    ResponsiveSizingConfig.instance.setCustomBreakpoints(ScreenBreakpoints(
        desktop: desktop_breakpoint,
        tablet: tablet_breakpoint,
        watch: watch_breakpoint));
  }

Thanks!

use the OrientationBuilder widget rather than MediaQuery.orientation

Hello I could see the use of
var orientation = MediaQuery.of(context).orientation;
on OrientationLayoutBuilder
on my use case I could not see the widget build on orientation changes on IPAD simulator. How about we refactor to use the [OrientationBuilder] (https://api.flutter.dev/flutter/widgets/OrientationBuilder-class.html) widget

I guess this would rebuild every time app’s current Orientation changes for current screen.

Here is the the code snippet in my case:

     ScreenTypeLayout(
  breakpoints:
      const ScreenBreakpoints(desktop: 900, tablet: 650, watch: 250),
  mobile: OrientationLayoutBuilder(

      portrait: (context) => const ProgramPortraitView(),
      landscape: (context) => const ProgramLandscapeView()),
  desktop
    : OrientationLayoutBuilder(
      portrait: (context) => const ProgramPortraitView(),
      landscape: (context) => const ProgramLandscapeView()),
)

Suggested OrinetationLayoutBuilder:

@override
Widget build(BuildContext context) {
return OrientationBuilder(
  builder: (context, deviceOrientation) {
    var orientation = deviceOrientation;

    if (mode != OrientationLayoutBuilderMode.portrait &&
        (orientation == Orientation.landscape ||
            mode == OrientationLayoutBuilderMode.landscape)) {
      if (landscape != null) {
        return landscape!(context);
      }
    }

    return portrait(context);
   },
  );
  }
}

Example with OrientationLayoutBuilder where the Screens don't reload when orientation change

Can you post an example of an orientation change that doesn't reload the entire page. If the orientation changes it shouldn't necessarily reload the entire screen, should just reload the UI. An example might be loading list of items. It may not need/require/want to reload the list of items on orientation change (if it is a network call then slow), only change the layout. This example would be really nice to have and review.

By the way, great package.

ScreenTypeLayout widgets don't rebuild on browser refresh

The StartupView of my app checks whether the user is logged in and navigates to "Home" or "LoginView".

When using responsive_builder, the widgets are not rebuilt when the user refreshes the browser.

My code:

class StartUpView extends StatelessWidget {
  const StartUpView({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    print('StartupView');
    return ScreenTypeLayout(
      breakpoints: ScreenBreakpoints(desktop: 1920, tablet: 900, watch: 375),
      mobile: StartUpViewMobile(),
      tablet: StartUpViewTablet(),
      desktop: StartupViewDesktop()
    );
  }
}

class StartUpViewDesktop extends StatelessWidget {
  const StartUpViewDesktop({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    print('StartupViewDesktop');
    return ViewModelBuilder<StartUpViewModel>.reactive(
      viewModelBuilder: () => StartUpViewModel(),
      onModelReady: (model) => model.handleStartUpLogic(),
      builder: (context, model, child) => Scaffold(
        extendBodyBehindAppBar: true,
        extendBody: true,
        body: Center(
          child: CircularProgressIndicator(
            strokeWidth: 3,
            valueColor: AlwaysStoppedAnimation(
              Theme.of(context).accentColor,
            ),
          ),
        ),
      ),
    );
  }
}

class StartUpViewModel extends BaseModel {
  final AuthenticationService _authenticationService =
      locator<AuthenticationService>();
  final NavigationService _navigationService = locator<NavigationService>();

  Future handleStartUpLogic() async {
    bool firstTime = true;
    _authenticationService.authChanges.listen((user) async {
      if (user != null) {
        _navigationService.clearStackAndShow(Routes.homeView);
      }
      if (!firstTime && user == null) {
        if (_authenticationService.platform == 'WEB') {
          _navigationService.clearStackAndShow(Routes.loginView);
        } else {
          _navigationService.clearStackAndShow(Routes.welcomeView);
        }
      }
      firstTime = false;
    });
  }
}

The console output on startup:

StartupView
StartupViewDesktop

When I refresh the browser, the StartupViewDesktop widget isn't rebuilt. The console output is:

StartupView

and it adds the page to the navigation stack which makes the widget
Navigator.of(context).canPop() == true

Screenshot 2021-03-21 at 13 07 55

All works as expected when using

class StartUpView extends StatelessWidget {
  const StartUpView({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    print('StartupView');
    return StartupViewDesktop();
  }
}

then, the StartupViewDesktop is rebuilt on refreshing the browser and
Navigator.of(context).canPop() == false

Screenshot 2021-03-21 at 13 15 21

Looks like responsive_builder doesn't handle the widget state appropriately?

Thanks for your help!

Unable to find modules for some sources, how to fix it?

pubspec.yaml:
dependencis:
.......
responsive_builder: ^0.1.5

console print error:
Unable to find modules for some sources, this is usually the result of either a
bad import, a missing dependency in a package (or possibly a dev_dependency
needs to move to a real dependency), or a build failure (if importing a
generated file).

Please check the following imports:

import 'package:responsive_builder/responsive_builder.dart'; from web_router_demo|lib/widgets/navigation_bar/navigation_bar.dart at 2:1

Failed after 88ms

in file import :

import 'package:flutter/material.dart';
import 'package:responsive_builder/responsive_builder.dart';
import 'package:web_router_demo/widgets/navigation_bar/navigation_bar_mobile.dart';
import 'package:web_router_demo/widgets/navigation_bar/navigation_bar_tablet_desktop.dart';

class NavigationBar extends StatelessWidget {
@OverRide
Widget build(BuildContext context) {
return ScreenTypeLayout(
mobile: NavigationBarMobile(),
tablet: NavigationBarTableDesktop(),
);
}
}

?????

Best way to handle onTap in DrawerOption to change Widget

What's the best way to handle the onTap event from DrawerOption to change the Widget in the HomeView pages?

I was able to get it working using a StreamBuilder that is listening on the home_view_mobile.dart and home_view_tablet.dart pages. Then in drawer_option.dart I added an InkWell with the onTap event adding events to the stream. Is this the best way? It works but when I add a TextField the FutureBuilder is reloading due to the rebuild of the page when the keyboard opens. I changed the future to be in initState and while that usually works it didn't here and I found out it was because of the StreamBuilder. Thoughts?

My current workaround is changing the onTap to navigate to the page instead of changing out the widget. Now the AppDrawer isn't shown.

https://stackoverflow.com/questions/73330084/there-is-a-problem-that-is-rebuild-when-i-click-textfield-in-flutter

[!] Flutter (Channel @upstream, 3.7.3, on Microsoft Windows [Version 10.0.19044.2604], locale en-US)
    • Flutter version 3.7.3 on channel @upstream at C:\src\flutter
    ! Unknown upstream repository.
      Reinstall Flutter by following instructions at https://flutter.dev/docs/get-started/install.
    • Framework revision 9944297138 (5 weeks ago), 2023-02-08 15:46:04 -0800
    • Engine revision 248290d6d5
    • Dart version 2.19.2
    • DevTools version 2.20.1
    • If those were intentional, you can disregard the above warnings; however it is recommended to use "git" directly to perform update checks and upgrades.

[√] Windows Version (Installed version of Windows is version 10 or higher)

[√] Android toolchain - develop for Android devices (Android SDK version 33.0.0)
    • Android SDK at C:\Users\tsqui\AppData\Local\Android\Sdk
    • Platform android-33, build-tools 33.0.0
    • ANDROID_HOME = C:\Users\tsqui\AppData\Local\Android\Sdk
    • Java binary at: C:\Program Files\Android\Android Studio\jre\bin\java
    • Java version OpenJDK Runtime Environment (build 11.0.13+0-b1751.21-8125866)
    • All Android licenses accepted.

[√] Chrome - develop for the web
    • Chrome at C:\Program Files (x86)\Google\Chrome\Application\chrome.exe

[√] Visual Studio - develop for Windows (Visual Studio Build Tools 2019 16.11.20)
    • Visual Studio at C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools
    • Visual Studio Build Tools 2019 version 16.11.32929.386
    • Windows 10 SDK version 10.0.19041.0

[√] Android Studio (version 2021.3)
    • Android Studio at C:\Program Files\Android\Android Studio
    • Flutter plugin can be installed from:
       https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
       https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build 11.0.13+0-b1751.21-8125866)

[√] VS Code (version 1.76.1)
    • VS Code at C:\Users\tsqui\AppData\Local\Programs\Microsoft VS Code
    • Flutter extension version 3.60.0

[√] Connected device (4 available)
    • sdk gphone64 x86 64 (mobile) • emulator-5554 • android-x64    • Android 13 (API 33) (emulator)
    • Windows (desktop)            • windows       • windows-x64    • Microsoft Windows [Version 10.0.19044.2604]
    • Chrome (web)                 • chrome        • web-javascript • Google Chrome 110.0.5481.178
    • Edge (web)                   • edge          • web-javascript • Microsoft Edge 110.0.1587.69

[√] HTTP Host Availability
    • All required HTTP hosts are available

iPhone 12 Mini landscape

If I turn my iPhone 12 Mini to landscape, isMobile=false. How can I handle this or how could I do a workaround?

RefinedSize { small, normal, large, extraLarge } improvements

Hi @FilledStacks first of all, you have made a great lib that really helped with adapting UI for different devices.

Second, I wanted to highlite the possible improvement for the library which will, IMO make it way more usefull.

Right now screen sizes are stored as an enum, which prevents us from adding any logic related variables to those objects.
And also makes library really hard to scale and repetitive, in some places.

For example you have the same repetitive code for all device types:

    if (deviceScreenType == DeviceScreenType.tablet) {
      if (deviceWidth >= ResponsiveSizingConfig.instance.refinedBreakpoints.tabletExtraLarge) {
        return RefinedSizeExtraLarge();
      }

      if (deviceWidth >= ResponsiveSizingConfig.instance.refinedBreakpoints.tabletLarge) {
        return RefinedSizeLarge();
      }

      if (deviceWidth >= ResponsiveSizingConfig.instance.refinedBreakpoints.tabletNormal) {
        return RefinedSizeNormal();
      }
    }

Existing enums are really limiting the library.

As I see it, thise can be replaced by abstract class + child class with this function @override.
Just like this:


abstract class RefinedSize {
  RefinedSize(this.mDeviceScreenTypeWidgetSizeMultiplier, this.mDeviceScreenTypeTextSizeMultiplier,
      this.mDeviceWithinCategoryWidgetScaleFactor, this.mDeviceWithinCategoryTextScaleFactor);

  final double mDeviceScreenTypeWidgetSizeMultiplier;
  final double mDeviceScreenTypeTextSizeMultiplier;

  final double mDeviceWithinCategoryWidgetScaleFactor;
  final double mDeviceWithinCategoryTextScaleFactor;
}

class RefinedSizeSmall extends RefinedSize {
  RefinedSizeSmall(super.mDeviceScreenTypeMultiplier, super.mDeviceScreenTypeTextSizeMultiplier,
      super.mDeviceWithinCategoryWidgetScaleFactor, super.mDeviceWithinCategoryTextScaleFactor);
}

class RefinedSizeNormal extends RefinedSize {
  RefinedSizeNormal(super.mDeviceScreenTypeMultiplier, super.mDeviceScreenTypeTextSizeMultiplier,
      super.mDeviceWithinCategoryWidgetScaleFactor, super.mDeviceWithinCategoryTextScaleFactor);
}

class RefinedSizeLarge extends RefinedSize {
  RefinedSizeLarge(super.mDeviceScreenTypeMultiplier, super.mDeviceScreenTypeTextSizeMultiplier,
      super.mDeviceWithinCategoryWidgetScaleFactor, super.mDeviceWithinCategoryTextScaleFactor);
}

class RefinedSizeExtraLarge extends RefinedSize {
  RefinedSizeExtraLarge(super.mDeviceScreenTypeMultiplier, super.mDeviceScreenTypeTextSizeMultiplier,
      super.mDeviceWithinCategoryWidgetScaleFactor, super.mDeviceWithinCategoryTextScaleFactor);
}

// Usage 
// Mobile
    if (deviceScreenType == DeviceScreenType.mobile) {
      if (deviceWidth >= ResponsiveSizingConfig.instance.refinedBreakpoints.mobileExtraLarge) {
        return RefinedSizeExtraLarge(MOBILE_WIDGET_SIZE_MULTIPLIER, MOBILE_TEXT_SIZE_MULTIPLIER,
            MOBILE_EXTRA_LARGE_WIDGET_SIZE_MULTIPLIER, MOBILE_EXTRA_LARGE_TEXT_SIZE_MULTIPLIER);
      }

      if (deviceWidth >= ResponsiveSizingConfig.instance.refinedBreakpoints.mobileLarge) {
        return RefinedSizeLarge(MOBILE_WIDGET_SIZE_MULTIPLIER, MOBILE_TEXT_SIZE_MULTIPLIER, MOBILE_LARGE_WIDGET_SIZE_MULTIPLIER,
            MOBILE_LARGE_TEXT_SIZE_MULTIPLIER);
      }

      if (deviceWidth >= ResponsiveSizingConfig.instance.refinedBreakpoints.mobileNormal) {
        return RefinedSizeNormal(MOBILE_WIDGET_SIZE_MULTIPLIER, MOBILE_TEXT_SIZE_MULTIPLIER, MOBILE_NORMAL_WIDGET_SIZE_MULTIPLIER,
            MOBILE_NORMAL_TEXT_SIZE_MULTIPLIER);
      }
    }

As you can see RefinedSize is holding all the necessary information to scale the UI any way we want.

Now we can use a unified scaling function to scale your widget to corresponding screen size:

mixin SizeHelperMixin {

  static double getScaledWidgetSize(double widgetSize, RefinedSize size) {
    return size.mDeviceScreenTypeWidgetSizeMultiplier * size.getWidgetSizeMultiplier() * widgetSize;
  }

  static double getScaledTextSize(BuildContext context, double textSize, RefinedSize size) {
    return size.mDeviceScreenTypeTextSizeMultiplier *
        size.getTextSizeMultiplier() *
        MediaQuery.of(context).textScaleFactor *
        textSize;
  }
}


If all this would be implemented, any user of this library will be able to extend it for his needs.

That allowed me to create a common mixin for all size scaling function. And now I can scale not only by device type, but also by small/normal/large/xlarge devices.

Overall pros:

  1. I don't really have to remember, or search for scale factors.
  2. I don't need multiple dimens constans for each screen size.
  3. It became way more scalebale, I can add new strange screen scale factor(in case I will need to open it on an unusual device)
  4. Now we can scale not only by device "dimension" but also by small/normal/large/xlarge.
  5. In case if we have the same layout for both mobile/tablet/etc devices we can use a size scaling functon instead of copying the layout.
// Usage 

return getDataWidget(
                data: data,
                logoWidth: SizeHelperMixin.getScaledWidgetSize(Dimens.size200, sizingInformation.refinedSize),
                profileBorderRadius: SizeHelperMixin.getScaledWidgetSize(Dimens.size32, sizingInformation.refinedSize),
                profileImageRadius: SizeHelperMixin.getScaledWidgetSize(Dimens.size20, sizingInformation.refinedSize),
                profileNamePadding: EdgeInsets.only(top: SizeHelperMixin.getScaledWidgetSize(Dimens.size20, sizingInformation.refinedSize)),
                profileNameText: "Alisa",
                profileNameTextStyle: QuizTimeStyles.getScaledTextStyleWhite15(context),
                profileStatImageWidth: SizeHelperMixin.getScaledWidgetSize(Dimens.size20, sizingInformation.refinedSize),
                profileStartImagePadding: EdgeInsets.only(right: Dimens.size12),
                );

It's a lot to cover, so it seems to be a bit raw, tell me if you will have any questions/ideas, I can also share the changes I have made.

Migrate to sound null safety

Description:

  • Migrate to sound null safety
  • Bump up package version to stable (1.2.0 or 2.0.0)

Hi I would like to know what is the state of the null safety pre-release. When it will be available as stable release.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.