├── README.md ├── packages └── flutter_adaptive_ui │ ├── analysis_options.yaml │ ├── .metadata │ ├── lib │ ├── flutter_adaptive_ui.dart │ └── src │ │ ├── constants.dart │ │ ├── utils.dart │ │ ├── extensions.dart │ │ ├── types.dart │ │ ├── screen.dart │ │ ├── breakpoint.dart │ │ └── widget_builders.dart │ ├── .gitignore │ ├── LICENSE │ ├── pubspec.yaml │ ├── CHANGELOG.md │ ├── example │ └── main.dart │ └── README.md └── LICENSE /README.md: -------------------------------------------------------------------------------- 1 | # flutter_flexible_ui 2 | -------------------------------------------------------------------------------- /packages/flutter_adaptive_ui/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:flutter_lints/flutter.yaml 2 | 3 | # Additional information about this file can be found at 4 | # https://dart.dev/guides/language/analysis-options 5 | -------------------------------------------------------------------------------- /packages/flutter_adaptive_ui/.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: fb57da5f945d02ef4f98dfd9409a72b7cce74268 8 | channel: stable 9 | 10 | project_type: package 11 | -------------------------------------------------------------------------------- /packages/flutter_adaptive_ui/lib/flutter_adaptive_ui.dart: -------------------------------------------------------------------------------- 1 | library flutter_adaptive_ui; 2 | 3 | import 'package:flutter/foundation.dart'; 4 | import 'package:flutter/material.dart'; 5 | 6 | part './src/constants.dart'; 7 | part './src/utils.dart'; 8 | part './src/types.dart'; 9 | part 'src/screen.dart'; 10 | part './src/breakpoint.dart'; 11 | part './src/widget_builders.dart'; 12 | part './src/extensions.dart'; 13 | -------------------------------------------------------------------------------- /packages/flutter_adaptive_ui/lib/src/constants.dart: -------------------------------------------------------------------------------- 1 | part of flutter_adaptive_ui; 2 | 3 | const double defaultMinSmallScreenWidth = 600; 4 | const double defaultMinMediumScreenWidth = 1024; 5 | const double defaultMinLargeScreenWidth = 1440; 6 | const double defaultMinXLargeScreenWidth = 1920; 7 | 8 | const double defaultMinMediumHandsetWidth = 360; 9 | const double defaultMinLargeHandsetWidth = 400; 10 | const double defaultMinSmallTabletWidth = 600; 11 | const double defaultMinLargeTabletWidth = 720; 12 | const double defaultMinSmallDesktopWidth = 1024; 13 | const double defaultMinMediumDesktopWidth = 1440; 14 | const double defaultMinLargeDesktopWidth = 1920; 15 | -------------------------------------------------------------------------------- /packages/flutter_adaptive_ui/.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | migrate_working_dir/ 12 | 13 | # IntelliJ related 14 | *.iml 15 | *.ipr 16 | *.iws 17 | .idea/ 18 | 19 | # The .vscode folder contains launch configuration and tasks you configure in 20 | # VS Code which you may wish to be included in version control, so this line 21 | # is commented out by default. 22 | #.vscode/ 23 | 24 | # Flutter/Dart/Pub related 25 | # Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock. 26 | /pubspec.lock 27 | **/doc/api/ 28 | .dart_tool/ 29 | .packages 30 | build/ 31 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Mohammad Taheri 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /packages/flutter_adaptive_ui/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Mohammad Taheri 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /packages/flutter_adaptive_ui/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: flutter_adaptive_ui 2 | description: A library that helps implement adaptive UI (based on OS , Screen size , ...) . 3 | version: 0.8.0+1 4 | repository: https://github.com/mohammadtaherri/flutter_flexible_ui/tree/main/packages/flutter_adaptive_ui 5 | homepage: 6 | 7 | environment: 8 | sdk: ">=2.12.0 <3.0.0" 9 | flutter: ">=1.17.0" 10 | 11 | dependencies: 12 | flutter: 13 | sdk: flutter 14 | 15 | dev_dependencies: 16 | flutter_test: 17 | sdk: flutter 18 | flutter_lints: ^2.0.0 19 | 20 | # For information on the generic Dart part of this file, see the 21 | # following page: https://dart.dev/tools/pub/pubspec 22 | 23 | # The following section is specific to Flutter packages. 24 | flutter: 25 | 26 | # To add assets to your package, add an assets section, like this: 27 | # assets: 28 | # - images/a_dot_burr.jpeg 29 | # - images/a_dot_ham.jpeg 30 | # 31 | # For details regarding assets in packages, see 32 | # https://flutter.dev/assets-and-images/#from-packages 33 | # 34 | # An image asset can refer to one or more resolution-specific "variants", see 35 | # https://flutter.dev/assets-and-images/#resolution-aware 36 | 37 | # To add custom fonts to your package, add a fonts section here, 38 | # in this "flutter" section. Each entry in this list should have a 39 | # "family" key with the font family name, and a "fonts" key with a 40 | # list giving the asset and other descriptors for the font. For 41 | # example: 42 | # fonts: 43 | # - family: Schyler 44 | # fonts: 45 | # - asset: fonts/Schyler-Regular.ttf 46 | # - asset: fonts/Schyler-Italic.ttf 47 | # style: italic 48 | # - family: Trajan Pro 49 | # fonts: 50 | # - asset: fonts/TrajanPro.ttf 51 | # - asset: fonts/TrajanPro_Bold.ttf 52 | # weight: 700 53 | # 54 | # For details regarding fonts in packages, see 55 | # https://flutter.dev/custom-fonts/#from-packages 56 | -------------------------------------------------------------------------------- /packages/flutter_adaptive_ui/lib/src/utils.dart: -------------------------------------------------------------------------------- 1 | part of flutter_adaptive_ui; 2 | 3 | /// A top level function that obtains [PlatformType] based on 4 | /// the [TargetPlatform] and the [kIsWeb]. 5 | /// 6 | /// If the [kIsWeb] is true, it will be web. 7 | /// If the [kIsWeb] is false, it will be obtained based on the [TargetPlatform]. 8 | /// 9 | /// See also: 10 | /// 11 | /// * [Screen] 12 | /// * [PlatformType] 13 | PlatformType getDefaultPlatform() { 14 | if (kIsWeb) return PlatformType.web; 15 | 16 | switch (defaultTargetPlatform) { 17 | case TargetPlatform.android: 18 | return PlatformType.android; 19 | case TargetPlatform.fuchsia: 20 | return PlatformType.fuchsia; 21 | case TargetPlatform.iOS: 22 | return PlatformType.iOS; 23 | case TargetPlatform.macOS: 24 | return PlatformType.macOS; 25 | case TargetPlatform.windows: 26 | return PlatformType.windows; 27 | case TargetPlatform.linux: 28 | return PlatformType.linux; 29 | } 30 | } 31 | 32 | /// A top level function that obtains [DesignLanguage] based on 33 | /// the [PlatformType]. 34 | /// 35 | /// If the [PlatformType] is android or fuchsia, it will be material. 36 | /// If the [PlatformType] is iOS or macOS, it will be cupertino. 37 | /// If the [PlatformType] is windows, it will be fluent. 38 | /// If the [PlatformType] is linux or web, it will be material. 39 | /// 40 | /// See also: 41 | /// 42 | /// * [Screen] 43 | /// * [DesignLanguage] 44 | DesignLanguage getDefaultDesignLanguage() { 45 | if (kIsWeb) return DesignLanguage.material; 46 | 47 | switch (defaultTargetPlatform) { 48 | case TargetPlatform.android: 49 | case TargetPlatform.fuchsia: 50 | return DesignLanguage.material; 51 | case TargetPlatform.iOS: 52 | case TargetPlatform.macOS: 53 | return DesignLanguage.cupertino; 54 | case TargetPlatform.windows: 55 | return DesignLanguage.fluent; 56 | default: 57 | return DesignLanguage.material; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /packages/flutter_adaptive_ui/lib/src/extensions.dart: -------------------------------------------------------------------------------- 1 | part of flutter_adaptive_ui; 2 | 3 | /// Extension methods to get the current breakpoint to a BuildContext. 4 | extension BreakpointX on BuildContext { 5 | /// Get the current [BreakpointData]. This is a shortcut for `Breakpoint.of(context)`. 6 | BreakpointData? get breakpoint => Breakpoint.of(this); 7 | } 8 | 9 | /// Extension methods on [Screen] 10 | extension ScreenX on Screen { 11 | bool get isHandset => isSmallHandset || isMediumHandset || isLargeHandset; 12 | bool get isSmallHandset => screenType == ScreenType.smallHandset; 13 | bool get isMediumHandset => screenType == ScreenType.mediumHandset; 14 | bool get isLargeHandset => screenType == ScreenType.largeHandset; 15 | 16 | bool get isTablet => isSmallTablet || isLargeTablet; 17 | bool get isSmallTablet => screenType == ScreenType.smallTablet; 18 | bool get isLargeTablet => screenType == ScreenType.largeTablet; 19 | 20 | bool get isDesktop => isSmallDesktop || isMediumDesktop || isLargeDesktop; 21 | bool get isSmallDesktop => screenType == ScreenType.smallDesktop; 22 | bool get isMediumDesktop => screenType == ScreenType.mediumDesktop; 23 | bool get isLargeDesktop => screenType == ScreenType.largeDesktop; 24 | 25 | bool get isXSmall => screenSize == ScreenSize.xsmall; 26 | bool get isSmall => screenSize == ScreenSize.small; 27 | bool get isMedium => screenSize == ScreenSize.medium; 28 | bool get isLarge => screenSize == ScreenSize.large; 29 | bool get isXLarge => screenSize == ScreenSize.xlarge; 30 | 31 | bool get isWeb => platform == PlatformType.web; 32 | bool get isAndroid => platform == PlatformType.android; 33 | bool get isFuchsia => platform == PlatformType.fuchsia; 34 | bool get isIOS => platform == PlatformType.iOS; 35 | bool get isWindows => platform == PlatformType.windows; 36 | bool get isLinux => platform == PlatformType.linux; 37 | bool get isMacOS => platform == PlatformType.macOS; 38 | } 39 | -------------------------------------------------------------------------------- /packages/flutter_adaptive_ui/lib/src/types.dart: -------------------------------------------------------------------------------- 1 | part of flutter_adaptive_ui; 2 | 3 | /// Screen Size based on screen width. 4 | /// 5 | /// By default, If screen width is 0-599 px, it will be xSmall. 6 | /// If screen width is 600-1023 px, it will be small. 7 | /// If screen width is 1024-1439 px, it will be medium. 8 | /// If screen width is 1440-1919 px, it will be large. 9 | /// If screen width is 1920+ px, it will be xLarge. 10 | /// 11 | /// See also: 12 | /// 13 | /// * [BreakpointData] 14 | /// * [Breakpoint] 15 | /// * [Screen] 16 | enum ScreenSize { 17 | xsmall, 18 | small, 19 | medium, 20 | large, 21 | xlarge, 22 | } 23 | 24 | /// Screen Type based on the screen width. 25 | /// 26 | /// By default, If screen width is 0-359 px, it will be smallHandset. 27 | /// If the screen width is 360-399 px, it will be mediumHandset. 28 | /// If the screen width is 400-599 px, it will be largeHandset. 29 | /// If the screen width is 600-719 px, it will be smallTablet. 30 | /// If the screen width is 720-1023 px, it will be largeTablet. 31 | /// If the screen width is 1024-1439 px, it will be smallDesktop. 32 | /// If the screen width is 1440-1919 px, it will be mediumDesktop. 33 | /// If the screen width is 1920+ px, it will be largeDesktop. 34 | /// 35 | /// See also: 36 | /// 37 | /// * [BreakpointData] 38 | /// * [Breakpoint] 39 | /// * [Screen] 40 | enum ScreenType { 41 | smallHandset, 42 | mediumHandset, 43 | largeHandset, 44 | smallTablet, 45 | largeTablet, 46 | smallDesktop, 47 | mediumDesktop, 48 | largeDesktop, 49 | } 50 | 51 | /// Design Language based on the [PlatformType]. 52 | /// 53 | /// If the [PlatformType] is android or fuchsia, it will be material. 54 | /// If the [PlatformType] is iOS or macOS, it will be cupertino. 55 | /// If the [PlatformType] is windows, it will be fluent. 56 | /// If the [PlatformType] is linux or web, it will be material. 57 | /// 58 | /// See also: 59 | /// 60 | /// * [Screen] 61 | /// * [getDefaultDesignLanguage] 62 | enum DesignLanguage { 63 | material, 64 | cupertino, 65 | fluent, 66 | } 67 | 68 | /// Platform Type based on the [TargetPlatform] and the[kIsWeb] 69 | /// 70 | /// If the [kIsWeb] is true, it will be web. 71 | /// If the [kIsWeb] is false, it will be obtained based on the [TargetPlatform]. 72 | /// 73 | /// See also: 74 | /// 75 | /// * [Screen] 76 | /// * [getDefaultPlatform] 77 | enum PlatformType { 78 | android, 79 | fuchsia, 80 | iOS, 81 | macOS, 82 | windows, 83 | linux, 84 | web, 85 | } 86 | -------------------------------------------------------------------------------- /packages/flutter_adaptive_ui/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 0.8.0+1 2 | 3 | * **docs**: Update README 4 | 5 | ## 0.8.0 6 | 7 | * **BREAKING**:feat: Add Screen.fromContext (factory) to Screen 8 | * **BREAKING**:feat: Add Screen.fromWindow (factory) to Screen 9 | * **BREAKING**:refactor: Make Screen's default constructor private 10 | * **BREAKING**:fix: Remove LayoutBuilder from AdaptiveBuilder and remove layoutConstraints field from Screen 11 | * **DEPRECATE**: Screen.of(context) deprecated in favor of Screen.fromContext 12 | 13 | ## 0.8.0-dev.2 14 | 15 | * **BREAKING**:feat: Add PlatformBuilder (widget) 16 | * **BREAKING**:feat: Add AdaptiveDesign (widget) 17 | * **BREAKING**:feat: Add AdaptiveBuilder.custom constructor to AdaptiveBuilder widget 18 | - **DEPRECATE**:fix: some params in AdaptiveBuilder constructor deprecated in favor of AdaptiveBuilder.custom constructor. 19 | 20 | ## 0.8.0-dev.1 21 | 22 | - **BREAKING**:refactor: Rename BreakpointData's fields 23 | - small to minSmallScreenWidth 24 | - medium to minMediumScreenWidth 25 | - large to minLargeScreenWidht 26 | - xLarge to minXLargeScreenWidht 27 | - mediumHandset to minMediumHandsetwidth 28 | - ... 29 | 30 | ## 0.7.0 31 | 32 | * **BREAKING**:feat: Add some extension methods to Screen 33 | * **Fix**: Update -Min Dart SDK- version to 2.12.0 34 | 35 | ## 0.6.0+1 36 | 37 | * Add persian README 38 | 39 | ## 0.6.0 40 | 41 | * **BREAKING**:feat: Add AdaptiveLayoutDelegateWithMinimallScreenSize 42 | * **BREAKING**:feat: Add AdaptiveLayoutDelegateWithSingleBuilder 43 | * **BREAKING**:refactor: Rename builder to defaultBuilder in AdaptiveBuilder 44 | * **BREAKING**:feat: Add defaultBuilder field to AdaptiveLayoutDelegate(s) 45 | 46 | ## 0.5.1+3 47 | 48 | ## 0.5.1+2 49 | 50 | * **Doc**: Add some documents. 51 | * Update README 52 | 53 | ## 0.5.1+1 54 | 55 | ## 0.5.1 56 | 57 | * **BREAKING**:refactor: Rename allOsDelegate to allPlatformsDelegate (AdaptiveBuilder) 58 | * Update README 59 | 60 | ## 0.5.0+1 61 | 62 | * Put an example 63 | 64 | ## 0.5.0 65 | 66 | * **BREAKING**:refactor: Rename DeviceConfig to Screen 67 | * **BREAKING**:feat: Add mediaQUeryData , breakpointData and layoutConstraints to Screen 68 | * **BREAKING**:feat: Obtain ScreenType and ScreenSize base on layoutConstraint and then media query 69 | * **BREAKING**:feat: Wrap AdaptiveBuilder result in LayoutBuilder 70 | * **BREAKING**:refactor: Remove maybeOf from Breakpoint 71 | * **BREAKING**:feat: Add of(context) method to Screen 72 | 73 | ## 0.4.0+1 74 | 75 | * **BREAKING**:feat: Add some extension methods to BuildContext (breakpoint , mabybreakpoint) 76 | * **Fix**: Rename builder to delegate in AdaptiveBuilder fields 77 | * **Fix**: Change AdaptiveLayoutDelegates fields to name params. 78 | * Doc: Add some documents. 79 | * Add README 80 | 81 | ## 0.4.0 82 | 83 | * Update AdaptiveBuilder: get breakpointData in constructor. 84 | * **BREAKING**:feat: Add PlatformType (enum). 85 | * **BREAKING**:feat: Add getDefaultPlatform top level function. 86 | * **BREAKING**:feat: Add getDefaultDesignLanguage top level function. 87 | 88 | ## 0.3.0 89 | 90 | * **BREAKING**:feat: Add BreakpointData. 91 | * **BREAKING**:feat: Add Breakpoint (InheritedWidget). 92 | * **BREAKING**:feat: Update DeviceConfig to use breakpoint. 93 | 94 | ## 0.2.0 95 | 96 | * **BREAKING**:refactor:Rename WindowType to ScreenType. 97 | * **BREAKING**:refactor:Rename WindowSize to ScreenSize. 98 | 99 | ## 0.1.1+3 100 | 101 | * **Doc**: Add some documents. 102 | 103 | ## 0.1.1+2 104 | 105 | ## 0.1.1+1 106 | 107 | * Update README.md 108 | 109 | ## 0.1.1 110 | 111 | * Add description to pubsepc.yaml 112 | * Add repository to pubsepc.yaml 113 | * **Fix**: Update -Min Dart SDK- version to 2.17.0 114 | 115 | ## 0.1.0 116 | 117 | * TODO: Describe initial release. 118 | 119 | -------------------------------------------------------------------------------- /packages/flutter_adaptive_ui/lib/src/screen.dart: -------------------------------------------------------------------------------- 1 | part of flutter_adaptive_ui; 2 | 3 | /// An object that gives some information about device's screen. 4 | /// 5 | /// See also: 6 | /// 7 | /// * [BreakpointData] 8 | /// * [MediaQueryData] 9 | /// * [AdaptiveBuilder] 10 | /// * [AdaptiveLayoutDelegate] 11 | class Screen { 12 | Screen._({ 13 | required this.mediaQueryData, 14 | required this.breakpointData, 15 | }) { 16 | final double width = mediaQueryData.size.width; 17 | 18 | platform = getDefaultPlatform(); 19 | designLanguage = getDefaultDesignLanguage(); 20 | screenSize = breakpointData._getScreenSize(width); 21 | screenType = breakpointData._getScreenType(width); 22 | } 23 | 24 | factory Screen.fromContext(BuildContext context) => Screen._( 25 | mediaQueryData: MediaQuery.of(context), 26 | breakpointData: Breakpoint.of(context) ?? const BreakpointData(), 27 | ); 28 | 29 | factory Screen.fromWindow() { 30 | WidgetsFlutterBinding.ensureInitialized(); 31 | return Screen._( 32 | mediaQueryData: MediaQueryData.fromWindow(WidgetsBinding.instance.window), 33 | breakpointData: const BreakpointData(), 34 | ); 35 | } 36 | 37 | final MediaQueryData mediaQueryData; 38 | final BreakpointData breakpointData; 39 | 40 | /// Screen Size based on screen width. 41 | /// This field is obtained by [BreakpointData._getScreenSize]. 42 | /// 43 | /// By default, If screen width is 0-599 px, it will be xSmall. 44 | /// If screen width is 600-1023 px, it will be small. 45 | /// If screen width is 1024-1439 px, it will be medium. 46 | /// If screen width is 1440-1919 px, it will be large. 47 | /// If screen width is 1920+ px, it will be xLarge. 48 | /// 49 | /// You can override the default sizes by wrapping your [MaterialApp] 50 | /// (or [WidgetsApp]) in a [Breakpoint]. 51 | /// 52 | /// See also: 53 | /// 54 | /// * [BreakpointData] 55 | /// * [Breakpoint] 56 | late final ScreenSize screenSize; 57 | 58 | /// Screen Type based on the screen width. 59 | /// This field is obtained by [BreakpointData._getScreenType]. 60 | /// 61 | /// By default, If screen width is 0-359 px, it will be smallHandset. 62 | /// If the screen width is 360-399 px, it will be mediumHandset. 63 | /// If the screen width is 400-599 px, it will be largeHandset. 64 | /// If the screen width is 600-719 px, it will be smallTablet. 65 | /// If the screen width is 720-1023 px, it will be largeTablet. 66 | /// If the screen width is 1024-1439 px, it will be smallDesktop. 67 | /// If the screen width is 1440-1919 px, it will be mediumDesktop. 68 | /// If the screen width is 1920+ px, it will be largeDesktop. 69 | /// 70 | /// You can override the default sizes by wrapping your [MaterialApp] 71 | /// (or [WidgetsApp]) in a [Breakpoint]. 72 | /// 73 | /// See also: 74 | /// 75 | /// * [BreakpointData] 76 | /// * [Breakpoint] 77 | late final ScreenType screenType; 78 | 79 | /// Design Language based on the [PlatformType]. 80 | /// This field is obtained by [getDefaultDesignLanguage]. 81 | /// 82 | /// If the [PlatformType] is android or fuchsia, it will be material. 83 | /// If the [PlatformType] is iOS or macOS, it will be cupertino. 84 | /// If the [PlatformType] is windows, it will be fluent. 85 | /// If the [PlatformType] is linux or web, it will be material. 86 | /// 87 | /// See also: 88 | /// 89 | /// * [getDefaultDesignLanguage] 90 | late final DesignLanguage designLanguage; 91 | 92 | /// Platform Type based on the [TargetPlatform] and the [kIsWeb] 93 | /// This field is obtained by the [getDefaultPlatform]. 94 | /// 95 | /// If the [kIsWeb] is true, it will be web. 96 | /// If the [kIsWeb] is false, it will be obtained based on the [TargetPlatform]. 97 | /// 98 | /// See also: 99 | /// 100 | /// * [getDefaultPlatform] 101 | late final PlatformType platform; 102 | 103 | @Deprecated('Use `Screen.fromContext` instead. Will be removed in v1.0.0') 104 | static Screen of(BuildContext context) => Screen._( 105 | mediaQueryData: MediaQuery.of(context), 106 | breakpointData: Breakpoint.of(context) ?? const BreakpointData(), 107 | ); 108 | } 109 | -------------------------------------------------------------------------------- /packages/flutter_adaptive_ui/example/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_adaptive_ui/flutter_adaptive_ui.dart'; 3 | 4 | main() { 5 | runApp(const MyApp()); 6 | } 7 | 8 | class MyApp extends StatelessWidget { 9 | const MyApp({Key? key}) : super(key: key); 10 | 11 | @override 12 | Widget build(BuildContext context) { 13 | return const Breakpoint( 14 | // Use default sizes or override. 15 | breakpointData: BreakpointData( 16 | // Based on [ScreenSize] (xSmall , small , medium , large , xLarge) 17 | minSmallScreenWidth: 600, 18 | minMediumScreenWidth: 1024, 19 | minLargeScreenWidth: 1440, 20 | minXLargeScreenWidth: 1920, 21 | // Based on [ScreenType] (smallHandset , mediumHandset , largeHandset , smallTablet , largetablet , smallDesktop , mediumDesktop , largeDesktop) 22 | minMediumHandsetWith: 360, 23 | minLargeHandsetWith: 400, 24 | minSmallTabletWidth: 600, 25 | minLargeTabletWidth: 720, 26 | minSmallDesktopWidth: 1024, 27 | minMediumDesktopWidth: 1440, 28 | minLargeDesktopWidth: 1920, 29 | ), 30 | child: MaterialApp( 31 | home: HomePage(), 32 | ), 33 | ); 34 | } 35 | } 36 | 37 | class HomePage extends StatefulWidget { 38 | const HomePage({Key? key}) : super(key: key); 39 | 40 | @override 41 | _HomePageState createState() => _HomePageState(); 42 | } 43 | 44 | class _HomePageState extends State { 45 | @override 46 | Widget build(BuildContext context) { 47 | return AdaptiveBuilder( 48 | defaultBuilder: (BuildContext context, Screen screen) { 49 | return const Center( 50 | child: Text('Default Builder'), 51 | ); 52 | }, 53 | androidDelegate: _getAndroidDelegate(), 54 | windowsDelegate: _getWindowsDelegate(), 55 | linuxDelegate: _getLinuxDelegate(), 56 | webDelegate: _getWebDelegate(), 57 | allPlatformsDelegate: _getAllPlatformsDelegate(), 58 | ); 59 | } 60 | 61 | AdaptiveLayoutDelegate? _getAndroidDelegate() { 62 | return AdaptiveLayoutDelegateWithMinimallScreenType( 63 | defaultBuilder: (BuildContext context, Screen screen) { 64 | return const Center( 65 | child: Text('Android - Default'), 66 | ); 67 | }, 68 | handset: (BuildContext context, Screen screen) { 69 | return const Center( 70 | child: Text('Android - Handset'), 71 | ); 72 | }, 73 | ); 74 | } 75 | 76 | AdaptiveLayoutDelegate? _getWindowsDelegate() { 77 | return AdaptiveLayoutDelegateWithScreenType( 78 | smallHandset: (BuildContext context, Screen screen) { 79 | return const Center( 80 | child: Text('Windows - Small handset'), 81 | ); 82 | }, 83 | mediumHandset: (BuildContext context, Screen screen) { 84 | return const Center( 85 | child: Text('Windows - Medium handset'), 86 | ); 87 | }, 88 | largeHandset: (BuildContext context, Screen screen) { 89 | return const Center( 90 | child: Text('Windows - Large handset'), 91 | ); 92 | }, 93 | smallTablet: (BuildContext context, Screen screen) { 94 | return const Center( 95 | child: Text('Windows - Small Tablet'), 96 | ); 97 | }, 98 | largeTablet: (BuildContext context, Screen screen) { 99 | return const Center( 100 | child: Text('Windows - Large Tablet'), 101 | ); 102 | }, 103 | smallDesktop: (BuildContext context, Screen screen) { 104 | return const Center( 105 | child: Text('Windows - Small Desktop'), 106 | ); 107 | }, 108 | mediumDesktop: (BuildContext context, Screen screen) { 109 | return const Center( 110 | child: Text('Windows - Medium Desktop'), 111 | ); 112 | }, 113 | largeDesktop: (BuildContext context, Screen screen) { 114 | return const Center( 115 | child: Text('Windows - Large Desktop'), 116 | ); 117 | }, 118 | ); 119 | } 120 | 121 | AdaptiveLayoutDelegate? _getLinuxDelegate() { 122 | return AdaptiveLayoutDelegateWithMinimallScreenType( 123 | handset: (BuildContext context, Screen screen) { 124 | return const Center( 125 | child: Text('Linux - Handset'), 126 | ); 127 | }, 128 | tablet: (BuildContext context, Screen screen) { 129 | return const Center( 130 | child: Text('Linux - Tablet'), 131 | ); 132 | }, 133 | desktop: (BuildContext context, Screen screen) { 134 | return const Center( 135 | child: Text('Linux - Desktop'), 136 | ); 137 | }, 138 | ); 139 | } 140 | 141 | AdaptiveLayoutDelegate? _getWebDelegate() { 142 | return AdaptiveLayoutDelegateWithScreenSize( 143 | xSmall: (BuildContext context, Screen screen) { 144 | return const Center( 145 | child: Text('Web - X Small'), 146 | ); 147 | }, 148 | medium: (BuildContext context, Screen screen) { 149 | return const Center( 150 | child: Text('Web - Medium'), 151 | ); 152 | }, 153 | large: (BuildContext context, Screen screen) { 154 | return const Center( 155 | child: Text('Web - large'), 156 | ); 157 | }, 158 | ); 159 | } 160 | 161 | AdaptiveLayoutDelegate? _getAllPlatformsDelegate() { 162 | return AdaptiveLayoutDelegateWithScreenSize( 163 | xSmall: (BuildContext context, Screen screen) { 164 | return const Center( 165 | child: Text('All OS - X Small'), 166 | ); 167 | }, 168 | medium: (BuildContext context, Screen screen) { 169 | return const Center( 170 | child: Text('All OS - Medium'), 171 | ); 172 | }, 173 | large: (BuildContext context, Screen screen) { 174 | return const Center( 175 | child: Text('All OS - large'), 176 | ); 177 | }, 178 | xLarge: (BuildContext context, Screen screen) { 179 | return const Center( 180 | child: Text('All Platforms - X large'), 181 | ); 182 | }, 183 | ); 184 | } 185 | } 186 | -------------------------------------------------------------------------------- /packages/flutter_adaptive_ui/lib/src/breakpoint.dart: -------------------------------------------------------------------------------- 1 | part of flutter_adaptive_ui; 2 | 3 | /// Defines the configuration of the [Breakpoint]. 4 | /// 5 | /// See also: 6 | /// 7 | /// * [Breakpoint] 8 | class BreakpointData { 9 | const BreakpointData({ 10 | this.minSmallScreenWidth = defaultMinSmallScreenWidth, 11 | this.minMediumScreenWidth = defaultMinMediumScreenWidth, 12 | this.minLargeScreenWidth = defaultMinLargeScreenWidth, 13 | this.minXLargeScreenWidth = defaultMinXLargeScreenWidth, 14 | this.minMediumHandsetWith = defaultMinMediumHandsetWidth, 15 | this.minLargeHandsetWith = defaultMinLargeHandsetWidth, 16 | this.minSmallTabletWidth = defaultMinSmallTabletWidth, 17 | this.minLargeTabletWidth = defaultMinLargeTabletWidth, 18 | this.minSmallDesktopWidth = defaultMinSmallDesktopWidth, 19 | this.minMediumDesktopWidth = defaultMinMediumDesktopWidth, 20 | this.minLargeDesktopWidth = defaultMinLargeDesktopWidth, 21 | }); 22 | 23 | /// The minimum width of the Small Screen 24 | final double minSmallScreenWidth; 25 | 26 | /// The minimum width of the Medium window 27 | final double minMediumScreenWidth; 28 | 29 | /// The minimum width of the Large Screen 30 | final double minLargeScreenWidth; 31 | 32 | /// The minimum width of the XLarge Screen 33 | final double minXLargeScreenWidth; 34 | 35 | /// The minimum width of the Medium Handset 36 | final double minMediumHandsetWith; 37 | 38 | /// The minimum width of the Large Handset 39 | final double minLargeHandsetWith; 40 | 41 | /// The minimum width of the Small Tablet 42 | final double minSmallTabletWidth; 43 | 44 | /// The minimum width of the Large Tablet 45 | final double minLargeTabletWidth; 46 | 47 | /// The minimum width of the Small Desktop 48 | final double minSmallDesktopWidth; 49 | 50 | /// The minimum width of the Medium Desktop 51 | final double minMediumDesktopWidth; 52 | 53 | /// The minimum width of the Large Desktop 54 | final double minLargeDesktopWidth; 55 | 56 | ScreenSize _getScreenSize(double width) { 57 | debugAssertIsValid(); 58 | if (width >= minXLargeScreenWidth) return ScreenSize.xlarge; 59 | if (width >= minLargeScreenWidth) return ScreenSize.large; 60 | if (width >= minMediumScreenWidth) return ScreenSize.medium; 61 | if (width >= minSmallScreenWidth) return ScreenSize.small; 62 | return ScreenSize.xsmall; 63 | } 64 | 65 | ScreenType _getScreenType(double width) { 66 | debugAssertIsValid(); 67 | if (width >= minLargeDesktopWidth) return ScreenType.largeDesktop; 68 | if (width >= minMediumDesktopWidth) return ScreenType.mediumDesktop; 69 | if (width >= minSmallDesktopWidth) return ScreenType.smallDesktop; 70 | if (width >= minLargeTabletWidth) return ScreenType.largeTablet; 71 | if (width >= minSmallTabletWidth) return ScreenType.smallTablet; 72 | if (width >= minLargeHandsetWith) return ScreenType.largeHandset; 73 | if (width >= minMediumHandsetWith) return ScreenType.mediumHandset; 74 | return ScreenType.smallHandset; 75 | } 76 | 77 | BreakpointData copyWith({ 78 | double? minSmallScreenWidth, 79 | double? minMediumScreenWidth, 80 | double? minLargeScreenWidth, 81 | double? minXLargeScreenWidth, 82 | double? minMediumHandsetWith, 83 | double? minLargeHandsetWith, 84 | double? minSmallTabletWidth, 85 | double? minLargeTabletWidth, 86 | double? minSmallDesktopWidth, 87 | double? minMediumDesktopWidth, 88 | double? minLargeDesktopWidth, 89 | }) => 90 | BreakpointData( 91 | minSmallScreenWidth: minSmallScreenWidth ?? this.minSmallScreenWidth, 92 | minMediumScreenWidth: minMediumScreenWidth ?? this.minMediumScreenWidth, 93 | minLargeScreenWidth: minLargeScreenWidth ?? this.minLargeScreenWidth, 94 | minXLargeScreenWidth: minXLargeScreenWidth ?? this.minXLargeScreenWidth, 95 | minMediumHandsetWith: minMediumHandsetWith ?? this.minMediumHandsetWith, 96 | minLargeHandsetWith: minLargeHandsetWith ?? this.minLargeHandsetWith, 97 | minSmallTabletWidth: minSmallTabletWidth ?? this.minSmallTabletWidth, 98 | minLargeTabletWidth: minLargeTabletWidth ?? this.minLargeTabletWidth, 99 | minSmallDesktopWidth: minSmallDesktopWidth ?? this.minSmallDesktopWidth, 100 | minMediumDesktopWidth: minMediumDesktopWidth ?? this.minMediumDesktopWidth, 101 | minLargeDesktopWidth: minLargeDesktopWidth ?? this.minLargeDesktopWidth, 102 | ); 103 | 104 | @override 105 | bool operator ==(Object other) { 106 | if (other is! BreakpointData) return false; 107 | if (identical(this, other)) return true; 108 | 109 | if (minSmallScreenWidth != other.minSmallScreenWidth) return false; 110 | if (minMediumScreenWidth != other.minMediumScreenWidth) return false; 111 | if (minLargeScreenWidth != other.minLargeScreenWidth) return false; 112 | if (minXLargeScreenWidth != other.minXLargeScreenWidth) return false; 113 | if (minMediumHandsetWith != other.minMediumHandsetWith) return false; 114 | if (minLargeHandsetWith != other.minLargeHandsetWith) return false; 115 | if (minSmallTabletWidth != other.minSmallTabletWidth) return false; 116 | if (minLargeTabletWidth != other.minLargeTabletWidth) return false; 117 | if (minSmallDesktopWidth != other.minSmallDesktopWidth) return false; 118 | if (minMediumDesktopWidth != other.minMediumDesktopWidth) return false; 119 | if (minLargeDesktopWidth != other.minLargeDesktopWidth) return false; 120 | 121 | return true; 122 | } 123 | 124 | @override 125 | int get hashCode => 126 | minSmallScreenWidth.hashCode ^ 127 | minMediumScreenWidth.hashCode ^ 128 | minLargeScreenWidth.hashCode ^ 129 | minXLargeScreenWidth.hashCode ^ 130 | minMediumHandsetWith.hashCode ^ 131 | minLargeHandsetWith.hashCode ^ 132 | minSmallTabletWidth.hashCode ^ 133 | minLargeTabletWidth.hashCode ^ 134 | minSmallDesktopWidth.hashCode ^ 135 | minMediumDesktopWidth.hashCode ^ 136 | minLargeDesktopWidth.hashCode; 137 | 138 | void debugAssertIsValid() { 139 | void check(double size1, double size2, String label1, String label2) { 140 | assert(size2 > size1, '$label2 must be greater than $label1'); 141 | } 142 | 143 | check( 144 | minSmallScreenWidth, 145 | minMediumScreenWidth, 146 | 'minSmallScreenWidth', 147 | 'minMediumScreenWidth', 148 | ); 149 | check( 150 | minMediumScreenWidth, 151 | minLargeScreenWidth, 152 | 'minMediumScreenWidth', 153 | 'minLargeScreenWidth', 154 | ); 155 | check( 156 | minLargeScreenWidth, 157 | minXLargeScreenWidth, 158 | 'minLargeScreenWidth', 159 | 'minXLargeScreenWidth', 160 | ); 161 | 162 | check( 163 | minMediumHandsetWith, 164 | minLargeHandsetWith, 165 | 'minMediumHandsetWith', 166 | 'minLargeHandsetWith', 167 | ); 168 | check( 169 | minLargeHandsetWith, 170 | minSmallTabletWidth, 171 | 'minLargeHandsetWith', 172 | 'minSmallTabletWidth', 173 | ); 174 | check( 175 | minSmallTabletWidth, 176 | minLargeTabletWidth, 177 | 'minSmallTabletWidth', 178 | 'minLargeTabletWidth', 179 | ); 180 | check( 181 | minLargeTabletWidth, 182 | minSmallDesktopWidth, 183 | 'minLargeTabletWidth', 184 | 'minSmallDesktopWidth', 185 | ); 186 | check( 187 | minSmallDesktopWidth, 188 | minMediumDesktopWidth, 189 | 'minSmallDesktopWidth', 190 | 'minMediumDesktopWidth', 191 | ); 192 | check( 193 | minMediumDesktopWidth, 194 | minLargeDesktopWidth, 195 | 'minMediumDesktopWidth', 196 | 'minLargeDesktopWidth', 197 | ); 198 | } 199 | } 200 | 201 | /// Applies a [BreakpointData] to descendant widgets. 202 | /// 203 | /// Descendant widgets obtain the current [BreakpointData] object using 204 | /// [Breakpoint.of]. When a widget uses [Breakpoint.of], it is automatically rebuilt if 205 | /// the [BreakpointData] later changes, so that the changes can be applied. 206 | /// 207 | /// Typical usage is as follows: 208 | /// 209 | /// ```dart 210 | /// main() { 211 | /// runApp(const MyApp()); 212 | /// } 213 | /// 214 | /// class MyApp extends StatelessWidget { 215 | /// const MyApp({Key? key}) : super(key: key); 216 | /// 217 | /// @override 218 | /// Widget build(BuildContext context) { 219 | /// return const Breakpoint( 220 | /// // Use default sizes or override. 221 | /// breakPointData: BreakpointData( 222 | /// // Base on [ScreenSize] (xSmall , small , medium , large , xLarge) 223 | /// small: 600, 224 | /// medium: 1024, 225 | /// large: 1440, 226 | /// xlarge: 1920, 227 | /// // Base on [ScreenType] (smallHandset , mediumHandset , largeHandset , smallTablet , largetablet , smallDesktop , mediumDesktop , largeDesktop) 228 | /// mediumHandset: 360, 229 | /// largeHandset: 400, 230 | /// smallTablet: 600, 231 | /// largeTablet: 720, 232 | /// smallDesktop: 1024, 233 | /// mediumDesktop: 1440, 234 | /// largeDesktop: 1920, 235 | /// ), 236 | /// child: MaterialApp( 237 | /// home: HomePage(), 238 | /// ), 239 | /// ); 240 | /// } 241 | /// } 242 | /// ``` 243 | /// 244 | /// See also: 245 | /// 246 | /// * [AdaptiveBuilder] 247 | /// * [AdaptiveLayoutDelegate] 248 | /// * [BreakpointData] 249 | /// * [Screen] 250 | /// * [MaterialApp] 251 | /// * [WidgetsApp] 252 | class Breakpoint extends InheritedWidget { 253 | const Breakpoint({ 254 | Key? key, 255 | this.breakpointData = const BreakpointData(), 256 | required Widget child, 257 | }) : super(key: key, child: child); 258 | final BreakpointData breakpointData; 259 | 260 | @override 261 | bool updateShouldNotify(covariant Breakpoint oldWidget) { 262 | return oldWidget.breakpointData != breakpointData; 263 | } 264 | 265 | /// The [breakPointData] from the closest [Breakpoint] instance that encloses the given 266 | /// context. 267 | static BreakpointData? of(BuildContext context) { 268 | return context.dependOnInheritedWidgetOfExactType()?.breakpointData; 269 | } 270 | } 271 | -------------------------------------------------------------------------------- /packages/flutter_adaptive_ui/lib/src/widget_builders.dart: -------------------------------------------------------------------------------- 1 | part of flutter_adaptive_ui; 2 | 3 | /// The signature of the [AdaptiveBuilder] builder function. 4 | typedef AdaptiveWidgetBuilder = Widget Function(BuildContext context, Screen screen); 5 | 6 | abstract class AdaptiveLayoutDelegate { 7 | /// Abstract const constructor. This constructor enables subclasses to provide 8 | /// const constructors so that they can be used in const expressions. 9 | const AdaptiveLayoutDelegate._(); 10 | 11 | @protected 12 | AdaptiveWidgetBuilder? getBuilder(Screen screen); 13 | } 14 | 15 | class AdaptiveLayoutDelegateWithScreenType implements AdaptiveLayoutDelegate { 16 | const AdaptiveLayoutDelegateWithScreenType({ 17 | this.defaultBuilder, 18 | this.smallHandset, 19 | this.mediumHandset, 20 | this.largeHandset, 21 | this.smallTablet, 22 | this.largeTablet, 23 | this.smallDesktop, 24 | this.mediumDesktop, 25 | this.largeDesktop, 26 | }); 27 | 28 | final AdaptiveWidgetBuilder? defaultBuilder; 29 | final AdaptiveWidgetBuilder? smallHandset; 30 | final AdaptiveWidgetBuilder? mediumHandset; 31 | final AdaptiveWidgetBuilder? largeHandset; 32 | final AdaptiveWidgetBuilder? smallTablet; 33 | final AdaptiveWidgetBuilder? largeTablet; 34 | final AdaptiveWidgetBuilder? smallDesktop; 35 | final AdaptiveWidgetBuilder? mediumDesktop; 36 | final AdaptiveWidgetBuilder? largeDesktop; 37 | 38 | @override 39 | @protected 40 | AdaptiveWidgetBuilder? getBuilder(Screen screen) { 41 | AdaptiveWidgetBuilder? b; 42 | 43 | switch (screen.screenType) { 44 | case ScreenType.smallHandset: 45 | b = smallHandset; 46 | break; 47 | case ScreenType.mediumHandset: 48 | b = mediumHandset; 49 | break; 50 | case ScreenType.largeHandset: 51 | b = largeHandset; 52 | break; 53 | case ScreenType.smallTablet: 54 | b = smallTablet; 55 | break; 56 | case ScreenType.largeTablet: 57 | b = largeTablet; 58 | break; 59 | case ScreenType.smallDesktop: 60 | b = smallDesktop; 61 | break; 62 | case ScreenType.mediumDesktop: 63 | b = mediumDesktop; 64 | break; 65 | case ScreenType.largeDesktop: 66 | b = largeDesktop; 67 | break; 68 | } 69 | 70 | return b ?? defaultBuilder; 71 | } 72 | } 73 | 74 | class AdaptiveLayoutDelegateWithMinimallScreenType implements AdaptiveLayoutDelegate { 75 | const AdaptiveLayoutDelegateWithMinimallScreenType({ 76 | this.defaultBuilder, 77 | this.handset, 78 | this.tablet, 79 | this.desktop, 80 | }); 81 | 82 | final AdaptiveWidgetBuilder? defaultBuilder; 83 | final AdaptiveWidgetBuilder? handset; 84 | final AdaptiveWidgetBuilder? tablet; 85 | final AdaptiveWidgetBuilder? desktop; 86 | 87 | @override 88 | @protected 89 | AdaptiveWidgetBuilder? getBuilder(Screen screen) { 90 | AdaptiveWidgetBuilder? b; 91 | switch (screen.screenType) { 92 | case ScreenType.smallHandset: 93 | case ScreenType.mediumHandset: 94 | case ScreenType.largeHandset: 95 | b = handset; 96 | break; 97 | case ScreenType.smallTablet: 98 | case ScreenType.largeTablet: 99 | b = tablet; 100 | break; 101 | case ScreenType.smallDesktop: 102 | case ScreenType.mediumDesktop: 103 | case ScreenType.largeDesktop: 104 | b = desktop; 105 | break; 106 | } 107 | 108 | return b ?? defaultBuilder; 109 | } 110 | } 111 | 112 | class AdaptiveLayoutDelegateWithScreenSize implements AdaptiveLayoutDelegate { 113 | const AdaptiveLayoutDelegateWithScreenSize({ 114 | this.defaultBuilder, 115 | this.xSmall, 116 | this.small, 117 | this.medium, 118 | this.large, 119 | this.xLarge, 120 | }); 121 | 122 | final AdaptiveWidgetBuilder? defaultBuilder; 123 | final AdaptiveWidgetBuilder? xSmall; 124 | final AdaptiveWidgetBuilder? small; 125 | final AdaptiveWidgetBuilder? medium; 126 | final AdaptiveWidgetBuilder? large; 127 | final AdaptiveWidgetBuilder? xLarge; 128 | 129 | @override 130 | @protected 131 | AdaptiveWidgetBuilder? getBuilder(Screen screen) { 132 | AdaptiveWidgetBuilder? b; 133 | 134 | switch (screen.screenSize) { 135 | case ScreenSize.xsmall: 136 | b = xSmall; 137 | break; 138 | case ScreenSize.small: 139 | b = small; 140 | break; 141 | case ScreenSize.medium: 142 | b = medium; 143 | break; 144 | case ScreenSize.large: 145 | b = large; 146 | break; 147 | case ScreenSize.xlarge: 148 | b = xLarge; 149 | break; 150 | } 151 | 152 | return b ?? defaultBuilder; 153 | } 154 | } 155 | 156 | class AdaptiveLayoutDelegateWithMinimallScreenSize implements AdaptiveLayoutDelegate { 157 | const AdaptiveLayoutDelegateWithMinimallScreenSize({ 158 | this.defaultBuilder, 159 | this.small, 160 | this.medium, 161 | this.large, 162 | }); 163 | 164 | final AdaptiveWidgetBuilder? defaultBuilder; 165 | final AdaptiveWidgetBuilder? small; 166 | final AdaptiveWidgetBuilder? medium; 167 | final AdaptiveWidgetBuilder? large; 168 | 169 | @override 170 | @protected 171 | AdaptiveWidgetBuilder? getBuilder(Screen screen) { 172 | AdaptiveWidgetBuilder? b; 173 | 174 | switch (screen.screenSize) { 175 | case ScreenSize.xsmall: 176 | case ScreenSize.small: 177 | b = small; 178 | break; 179 | case ScreenSize.medium: 180 | b = medium; 181 | break; 182 | case ScreenSize.large: 183 | case ScreenSize.xlarge: 184 | b = large; 185 | break; 186 | } 187 | 188 | return b ?? defaultBuilder; 189 | } 190 | } 191 | 192 | class AdaptiveLayoutDelegateWithSingleBuilder implements AdaptiveLayoutDelegate { 193 | const AdaptiveLayoutDelegateWithSingleBuilder(this.builder); 194 | final AdaptiveWidgetBuilder builder; 195 | 196 | @override 197 | AdaptiveWidgetBuilder? getBuilder(Screen screen) { 198 | return builder; 199 | } 200 | } 201 | 202 | class AdaptiveLayoutDelegateWithDesignLanguage implements AdaptiveLayoutDelegate { 203 | const AdaptiveLayoutDelegateWithDesignLanguage({ 204 | this.defaultBuilder, 205 | this.material, 206 | this.cupertino, 207 | this.fluent, 208 | }); 209 | 210 | final AdaptiveWidgetBuilder? defaultBuilder; 211 | final AdaptiveWidgetBuilder? material; 212 | final AdaptiveWidgetBuilder? cupertino; 213 | final AdaptiveWidgetBuilder? fluent; 214 | 215 | @override 216 | @protected 217 | AdaptiveWidgetBuilder? getBuilder(Screen screen) { 218 | AdaptiveWidgetBuilder? b; 219 | 220 | switch (screen.designLanguage) { 221 | case DesignLanguage.material: 222 | b = material; 223 | break; 224 | case DesignLanguage.cupertino: 225 | b = cupertino; 226 | break; 227 | case DesignLanguage.fluent: 228 | b = fluent; 229 | break; 230 | } 231 | 232 | return b ?? defaultBuilder; 233 | } 234 | } 235 | 236 | /// Typical usage is as follows: 237 | /// 238 | /// ```dart 239 | /// class HomePage extends StatefulWidget { 240 | /// const HomePage({Key? key}) : super(key: key); 241 | /// 242 | /// @override 243 | /// _HomePageState createState() => _HomePageState(); 244 | /// } 245 | /// 246 | /// class _HomePageState extends State { 247 | /// @override 248 | /// Widget build(BuildContext context) { 249 | /// return AdaptiveBuilder( 250 | /// builder: (BuildContext context, Screen screen) { 251 | /// return const Center( 252 | /// child: Text('Default Builder'), 253 | /// ); 254 | /// }, 255 | /// androidDelegate: _getAndroidDelegate(), 256 | /// windowsDelegate: _getWindowsDelegate(), 257 | /// linuxDelegate: _getLinuxDelegate(), 258 | /// webDelegate: _getWebDelegate(), 259 | /// allPlatformsDelegate: _getAlllatformsDelegate(), 260 | /// ); 261 | /// } 262 | /// 263 | /// AdaptiveLayoutDelegate? _getAndroidDelegate() { 264 | /// return AdaptiveLayoutDelegateWithMinimallScreenType( 265 | /// handset: (BuildContext context, Screen screen) { 266 | /// return const Center( 267 | /// child: Text('Android - Handset'), 268 | /// ); 269 | /// }, 270 | /// ); 271 | /// } 272 | /// 273 | /// AdaptiveLayoutDelegate? _getWindowsDelegate() { 274 | /// return AdaptiveLayoutDelegateWithScreenType( 275 | /// smallHandset: (BuildContext context, Screen screen) { 276 | /// return const Center( 277 | /// child: Text('Windows - Small handset'), 278 | /// ); 279 | /// }, 280 | /// mediumHandset: (BuildContext context, Screen screen) { 281 | /// return const Center( 282 | /// child: Text('Windows - Medium handset'), 283 | /// ); 284 | /// }, 285 | /// largeHandset: (BuildContext context, Screen screen) { 286 | /// return const Center( 287 | /// child: Text('Windows - Large handset'), 288 | /// ); 289 | /// }, 290 | /// smallTablet: (BuildContext context, Screen screen) { 291 | /// return const Center( 292 | /// child: Text('Windows - Small Tablet'), 293 | /// ); 294 | /// }, 295 | /// largeTablet: (BuildContext context, Screen screen) { 296 | /// return const Center( 297 | /// child: Text('Windows - Large Tablet'), 298 | /// ); 299 | /// }, 300 | /// smallDesktop: (BuildContext context, Screen screen) { 301 | /// return const Center( 302 | /// child: Text('Windows - Small Desktop'), 303 | /// ); 304 | /// }, 305 | /// mediumDesktop: (BuildContext context, Screen screen) { 306 | /// return const Center( 307 | /// child: Text('Windows - Medium Desktop'), 308 | /// ); 309 | /// }, 310 | /// largeDesktop: (BuildContext context, Screen screen) { 311 | /// return const Center( 312 | /// child: Text('Windows - Large Desktop'), 313 | /// ); 314 | /// }, 315 | /// ); 316 | /// } 317 | /// 318 | /// AdaptiveLayoutDelegate? _getLinuxDelegate() { 319 | /// return AdaptiveLayoutDelegateWithMinimallScreenType( 320 | /// handset: (BuildContext context, Screen screen) { 321 | /// return const Center( 322 | /// child: Text('Linux - Handset'), 323 | /// ); 324 | /// }, 325 | /// tablet: (BuildContext context, Screen screen) { 326 | /// return const Center( 327 | /// child: Text('Linux - Tablet'), 328 | /// ); 329 | /// }, 330 | /// desktop: (BuildContext context, Screen screen) { 331 | /// return const Center( 332 | /// child: Text('Linux - Desktop'), 333 | /// ); 334 | /// }, 335 | /// ); 336 | /// } 337 | /// 338 | /// AdaptiveLayoutDelegate? _getWebDelegate() { 339 | /// return AdaptiveLayoutDelegateWithScreenSize( 340 | /// xSmall: (BuildContext context, Screen screen) { 341 | /// return const Center( 342 | /// child: Text('Web - X Small'), 343 | /// ); 344 | /// }, 345 | /// medium: (BuildContext context, Screen screen) { 346 | /// return const Center( 347 | /// child: Text('Web - Medium'), 348 | /// ); 349 | /// }, 350 | /// large: (BuildContext context, Screen screen) { 351 | /// return const Center( 352 | /// child: Text('Web - large'), 353 | /// ); 354 | /// }, 355 | /// ); 356 | /// } 357 | /// 358 | /// AdaptiveLayoutDelegate? _getAlllatformsDelegate() { 359 | /// return AdaptiveLayoutDelegateWithScreenSize( 360 | /// xSmall: (BuildContext context, Screen screen) { 361 | /// return const Center( 362 | /// child: Text('All OS - X Small'), 363 | /// ); 364 | /// }, 365 | /// medium: (BuildContext context, Screen screen) { 366 | /// return const Center( 367 | /// child: Text('All OS - Medium'), 368 | /// ); 369 | /// }, 370 | /// large: (BuildContext context, Screen screen) { 371 | /// return const Center( 372 | /// child: Text('All OS - large'), 373 | /// ); 374 | /// }, 375 | /// xLarge: (BuildContext context, Screen screen) { 376 | /// return const Center( 377 | /// child: Text('All Platforms - X large'), 378 | /// ); 379 | /// }, 380 | /// ); 381 | /// } 382 | /// } 383 | /// ``` 384 | /// 385 | /// See also: 386 | /// 387 | /// * [AdaptiveLayoutDelegate] 388 | /// * [Breakpoint] 389 | /// * [BreakpointData] 390 | /// * [Screen] 391 | class AdaptiveBuilder extends StatelessWidget { 392 | const AdaptiveBuilder({ 393 | Key? key, 394 | required this.defaultBuilder, 395 | AdaptiveLayoutDelegate? layoutDelegate, 396 | @Deprecated('Use `AdaptiveBuilder.custom` constructor instead. Will be removed in v1.0.0') 397 | this.androidDelegate, 398 | @Deprecated('Use `AdaptiveBuilder.custom` constructor instead. Will be removed in v1.0.0') 399 | this.fuchsiaDelegate, 400 | @Deprecated('Use `AdaptiveBuilder.custom` constructor instead. Will be removed in v1.0.0') 401 | this.iosDelegate, 402 | @Deprecated('Use `AdaptiveBuilder.custom` constructor instead. Will be removed in v1.0.0') 403 | this.windowsDelegate, 404 | @Deprecated('Use `AdaptiveBuilder.custom` constructor instead. Will be removed in v1.0.0') 405 | this.macosDelegate, 406 | @Deprecated('Use `AdaptiveBuilder.custom` constructor instead. Will be removed in v1.0.0') 407 | this.linuxDelegate, 408 | @Deprecated('Use `AdaptiveBuilder.custom` constructor instead. Will be removed in v1.0.0') 409 | this.webDelegate, 410 | @Deprecated('Use `layoutDelegate` instead. Will be removed in v1.0.0') 411 | AdaptiveLayoutDelegate? allPlatformsDelegate, 412 | this.breakpointData, 413 | }) : allPlatformsDelegate = layoutDelegate ?? allPlatformsDelegate, 414 | super(key: key); 415 | 416 | const AdaptiveBuilder.custom({ 417 | Key? key, 418 | required this.defaultBuilder, 419 | this.androidDelegate, 420 | this.fuchsiaDelegate, 421 | this.iosDelegate, 422 | this.windowsDelegate, 423 | this.macosDelegate, 424 | this.linuxDelegate, 425 | this.webDelegate, 426 | this.allPlatformsDelegate, 427 | this.breakpointData, 428 | }) : super(key: key); 429 | 430 | final AdaptiveWidgetBuilder defaultBuilder; 431 | final AdaptiveLayoutDelegate? androidDelegate; 432 | final AdaptiveLayoutDelegate? fuchsiaDelegate; 433 | final AdaptiveLayoutDelegate? iosDelegate; 434 | final AdaptiveLayoutDelegate? windowsDelegate; 435 | final AdaptiveLayoutDelegate? linuxDelegate; 436 | final AdaptiveLayoutDelegate? macosDelegate; 437 | final AdaptiveLayoutDelegate? webDelegate; 438 | final AdaptiveLayoutDelegate? allPlatformsDelegate; 439 | final BreakpointData? breakpointData; 440 | 441 | @override 442 | Widget build(BuildContext context) { 443 | Screen screen = Screen._( 444 | mediaQueryData: MediaQuery.of(context), 445 | breakpointData: breakpointData ?? Breakpoint.of(context) ?? const BreakpointData(), 446 | ); 447 | 448 | AdaptiveWidgetBuilder? b; 449 | 450 | switch (screen.platform) { 451 | case PlatformType.web: 452 | b = webDelegate?.getBuilder(screen); 453 | break; 454 | case PlatformType.android: 455 | b = androidDelegate?.getBuilder(screen); 456 | break; 457 | case PlatformType.fuchsia: 458 | b = fuchsiaDelegate?.getBuilder(screen); 459 | break; 460 | case PlatformType.iOS: 461 | b = iosDelegate?.getBuilder(screen); 462 | break; 463 | case PlatformType.windows: 464 | b = windowsDelegate?.getBuilder(screen); 465 | break; 466 | case PlatformType.macOS: 467 | b = macosDelegate?.getBuilder(screen); 468 | break; 469 | case PlatformType.linux: 470 | b = linuxDelegate?.getBuilder(screen); 471 | break; 472 | } 473 | 474 | return b?.call(context, screen) ?? 475 | allPlatformsDelegate?.getBuilder(screen)?.call(context, screen) ?? 476 | defaultBuilder.call(context, screen); 477 | } 478 | } 479 | 480 | class PlatformBuilder extends StatelessWidget { 481 | const PlatformBuilder({ 482 | Key? key, 483 | required this.defaultBuilder, 484 | this.androidBuilder, 485 | this.fuchsiaBuilder, 486 | this.iosBuilder, 487 | this.windowsBuilder, 488 | this.macosBuilder, 489 | this.linuxBuilder, 490 | this.webBuilder, 491 | }) : super(key: key); 492 | 493 | final AdaptiveWidgetBuilder defaultBuilder; 494 | final AdaptiveWidgetBuilder? androidBuilder; 495 | final AdaptiveWidgetBuilder? fuchsiaBuilder; 496 | final AdaptiveWidgetBuilder? iosBuilder; 497 | final AdaptiveWidgetBuilder? windowsBuilder; 498 | final AdaptiveWidgetBuilder? macosBuilder; 499 | final AdaptiveWidgetBuilder? linuxBuilder; 500 | final AdaptiveWidgetBuilder? webBuilder; 501 | 502 | @override 503 | Widget build(BuildContext context) { 504 | Screen screen = Screen._( 505 | mediaQueryData: MediaQuery.of(context), 506 | breakpointData: Breakpoint.of(context) ?? const BreakpointData(), 507 | ); 508 | 509 | AdaptiveWidgetBuilder? b; 510 | 511 | switch (screen.platform) { 512 | case PlatformType.web: 513 | b = webBuilder; 514 | break; 515 | case PlatformType.android: 516 | b = androidBuilder; 517 | break; 518 | case PlatformType.fuchsia: 519 | b = fuchsiaBuilder; 520 | break; 521 | case PlatformType.iOS: 522 | b = iosBuilder; 523 | break; 524 | case PlatformType.windows: 525 | b = windowsBuilder; 526 | break; 527 | case PlatformType.macOS: 528 | b = macosBuilder; 529 | break; 530 | case PlatformType.linux: 531 | b = linuxBuilder; 532 | break; 533 | } 534 | 535 | return b?.call(context, screen) ?? defaultBuilder.call(context, screen); 536 | } 537 | } 538 | 539 | class AdaptiveDesign extends StatelessWidget { 540 | const AdaptiveDesign({ 541 | Key? key, 542 | required this.defaultBuilder, 543 | this.material, 544 | this.cupertino, 545 | this.fluent, 546 | }) : super(key: key); 547 | 548 | final AdaptiveWidgetBuilder defaultBuilder; 549 | final AdaptiveWidgetBuilder? material; 550 | final AdaptiveWidgetBuilder? cupertino; 551 | final AdaptiveWidgetBuilder? fluent; 552 | 553 | @override 554 | Widget build(BuildContext context) { 555 | Screen screen = Screen._( 556 | mediaQueryData: MediaQuery.of(context), 557 | breakpointData: Breakpoint.of(context) ?? const BreakpointData(), 558 | ); 559 | 560 | AdaptiveWidgetBuilder? b; 561 | 562 | switch (screen.designLanguage) { 563 | case DesignLanguage.material: 564 | b = material; 565 | break; 566 | case DesignLanguage.cupertino: 567 | b = cupertino; 568 | break; 569 | case DesignLanguage.fluent: 570 | b = fluent; 571 | break; 572 | } 573 | 574 | return b?.call(context, screen) ?? defaultBuilder.call(context, screen); 575 | } 576 | } 577 | -------------------------------------------------------------------------------- /packages/flutter_adaptive_ui/README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # Flutter Adaptive UI 4 | 5 | 6 | ![0_t8MtUq5ko9abs0TD](https://user-images.githubusercontent.com/44123678/170714501-28c21458-4447-469c-8975-f14b64fc31f4.jpg) 7 | 8 | Flutter provides new opportunities to build apps that can run on mobile, desktop, and the web from a single codebase. However, with these opportunities, come new challenges. You want your app to feel familiar to users, adapting to each platform by maximizing usability and ensuring a comfortable and seamless experience. That is, you need to build apps that are not just multiplatform, but are fully platform adaptive. 9 | 10 | For more informations follow this [link](https://docs.flutter.dev/development/ui/layout/building-adaptive-apps). 11 | 12 | # Documentation 13 | 14 | 15 | 16 | # Quick start API tour 17 | 18 | * [Overview](#overview) 19 | * [Breakpoint](#breakpoint) 20 | * [AdaptiveBuilder](#adaptivebuilder) 21 | * [PlatformBuilder](#platformbuilder) 22 | * [AdaptiveDesign](#adaptivedesign) 23 | * [Screen](#screen) 24 | * [Helpers](#helpers) 25 | 26 | 27 | ## Overview 28 | 29 | This package helps you for building **Adaptive UI**.For this purpose, we are going to use the following params: 30 | 31 | #### Platform Type 32 | * android 33 | * fuchsia 34 | * iOS 35 | * windows 36 | * macOS 37 | * linux 38 | * web 39 | 40 | #### Screen Size 41 | * X Small 42 | * Small 43 | * Medium 44 | * Large 45 | * X Lagre 46 | 47 | #### Screen Type 48 | * Small Handset 49 | * Medium Handset 50 | * Large Handset 51 | * Small Tablet 52 | * Large Tablet 53 | * Small Desktop 54 | * Medium Desktop 55 | * Large Desktop 56 | 57 | #### Design Language 58 | * Material 59 | * Cupertino 60 | * Fluent 61 | 62 | Then we are going to use the following widgets for building **Adaptive UI** based on these params: 63 | 64 | * [AdaptiveBuilder](#adaptivebuilder) 65 | * [PlatformBuilder](#platformbuilder) 66 | * [AdaptiveDesign](#adaptivedesign) 67 | 68 | But before we focus on above widgets, let's talk about [Breakpoint](#breakpoint). 69 | 70 | ## Breakpoint 71 | 72 | By default the **Screen Size** and the **Screen Type** are obtained based on the following values: 73 | 74 | | Screen Width Range | Screen Size | Screen Type | 75 | | -------------------| ------------- | ------------- | 76 | | 0-359 | X Small | Small Handset | 77 | | 360-399 | X Small | Medium Handset| 78 | | 400-599 | X Small | Large Handset | 79 | | 600-719 | Small | Small Tablet | 80 | | 720-1023 | Small | Large Tablet | 81 | | 1023-1439 | Medium | Small Desktop | 82 | | 1440-1919 | Large | Medium Desktop| 83 | | 1920+ | X Large | Large Desktop | 84 | 85 | 86 | 87 | And the **_Design language_** : 88 | 89 | | Platform | Design Language | 90 | | -------------------| ----------------| 91 | | Android - Fuchsia | Material | 92 | | IOS - MacOs | Cupertino | 93 | | Windows | Fluent | 94 | | Others | Material | 95 | 96 | 97 | You can change the default sizes by wrapping your **MaterialApp** in a **Breakpoint** widget: 98 | 99 | ```dart 100 | import 'package:flutter/material.dart'; 101 | import 'package:flutter_adaptive_ui/flutter_adaptive_ui.dart'; 102 | 103 | void main() => runApp(const MyApp()); 104 | 105 | class MyApp extends StatelessWidget { 106 | const MyApp({Key? key}) : super(key: key); 107 | 108 | @override 109 | Widget build(BuildContext context) { 110 | return const Breakpoint( 111 | child: MaterialApp( 112 | home: HomePage(), 113 | ), 114 | ); 115 | } 116 | } 117 | ``` 118 | 119 | Now you can change the default sizes by pass a **breakpoint Data** to the **Breakpoint**'s constructor: 120 | 121 | 122 | ```dart 123 | import 'package:flutter/material.dart'; 124 | import 'package:flutter_adaptive_ui/flutter_adaptive_ui.dart'; 125 | 126 | main() { 127 | runApp(const MyApp()); 128 | } 129 | 130 | class MyApp extends StatelessWidget { 131 | const MyApp({Key? key}) : super(key: key); 132 | 133 | @override 134 | Widget build(BuildContext context) { 135 | return const Breakpoint( 136 | // Use default sizes or override. 137 | breakpointData: BreakpointData( 138 | // Based on [ScreenSize] (xSmall , small , medium , large , xLarge) 139 | minSmallScreenWidth: 600, 140 | minMediumScreenWidth: 1024, 141 | minLargeScreenWidth: 1440, 142 | minXLargeScreenWidth: 1920, 143 | // Based on [ScreenType] (smallHandset , mediumHandset , largeHandset , smallTablet , largetablet , smallDesktop , mediumDesktop , largeDesktop) 144 | minMediumHandsetWith: 360, 145 | minLargeHandsetWith: 400, 146 | minSmallTabletWidth: 600, 147 | minLargeTabletWidth: 720, 148 | minSmallDesktopWidth: 1024, 149 | minMediumDesktopWidth: 1440, 150 | minLargeDesktopWidth: 1920, 151 | ), 152 | child: MaterialApp( 153 | home: HomePage(), 154 | ), 155 | ); 156 | } 157 | } 158 | ``` 159 | 160 | All params are optional. 161 | 162 | | Param | Definition | Default value | 163 | | --------------------------| ---------------------------------------------------- | ------------- | 164 | | minSmallScreenWidth | The Minimum Width of the small Screen | 600 | 165 | | minMediumScreenWidth | The Minimum Width of the medium Screen | 1024 | 166 | | minLargeScreenWidth | The Minimum Width of the large Screen | 1440 | 167 | | minXLargeScreenWidth | The Minimum Width of the xLarge Screen | 1920 | 168 | | minMediumHandsetWith | The Minimum Width of the medium handset | 360 | 169 | | minLargeHandsetWith | The Minimum Width of the large hanset | 400 | 170 | | minSmallTabletWidth | The Minimum Width of the small tablet | 600 | 171 | | minLargeTabletWidth | The Minimum Width of the large tablet | 720 | 172 | | minSmallDesktopWidth | The Minimum Width of the small desktop | 1024 | 173 | | minMediumDesktopWidth | The Minimum Width of the medium desktop | 1440 | 174 | | minLargeDesktopWidth | The Minimum Width of the large desktop | 1920 | 175 | 176 | 177 | - If the screen width is less than the **_minSmallScreenWidth_** (default = 600),the **Screen Size** will be **xSmall**. 178 | - If the screen width is less than the **_minMediumHandsetWith_** (default = 360), the **Screen Type** will be **smallHandset**. 179 | 180 | 181 | #### Breakpoint.of(context) 182 | 183 | The **Breakpoint** widget is an **InheritedWidget** and so you can use the **Breakpoint.of(context)** (static method) to obtain the **BreakpointData**. 184 | 185 | After talking about the **Breakpoint**, Now is the time that we talk about the **AdaptiveBuilder** widget for building **Adaptive UI**. 186 | 187 | let's go. 188 | 189 | ## AdaptiveBuilder 190 | 191 | You should use the `AdaptiveBuilder` widget to build an adaptive UI. 192 | 193 | Wrap your entire screen with this widget: 194 | ```dart 195 | class HomePage extends StatefulWidget { 196 | const HomePage({Key? key}) : super(key: key); 197 | 198 | @override 199 | _HomePageState createState() => _HomePageState(); 200 | } 201 | 202 | class _HomePageState extends State { 203 | @override 204 | Widget build(BuildContext context) { 205 | return AdaptiveBuilder( 206 | 207 | ); 208 | } 209 | } 210 | ``` 211 | 212 | The **AdaptiveBuilder** has two contructors. 213 | 214 | #### AdaptiveBuilder Default Constructor 215 | 216 | The default constructor of the **AdaptiveBuilder** accepts three params: 217 | 218 | | Param | Type | 219 | | ----------------------| ----------------------------------------- | 220 | | defaultBuilder | AdaptiveWidgetBuilder (Required) | 221 | | [layoutDelegate](#layoutdelegate) | AdaptiveLayoutDelegate? (Optional) | 222 | | [breakpointData](#breakpointdata) | BreakpointData? (Optional) | 223 | 224 | ### breakpointData 225 | 226 | The **AdaptiveBuilder** obtains the **BreakpointData** based on the following rules: 227 | 228 | 1. the **breakpointData** param that is passed to its constructor. 229 | 2. If the **breakpointData** param is null(no param is passed to its constructor), The **breakPointData** is obtained from the closest **Breakpoint** instance that encloses its context. 230 | 3. If there is no **Breakpoint** in the widget tree above the **AdaptiveBuilder**, it will use the default sizes. 231 | 232 | 233 | Use this param to change the default sizes: 234 | 235 | 1. Use the ***Breakpoint.of(context)** to obtain The **breakPointData** from the closest **Breakpoint** instance that encloses the given context and then change sizes by calling the **copyWith()** method: 236 | 237 | ```dart 238 | class HomePage extends StatefulWidget { 239 | const HomePage({Key? key}) : super(key: key); 240 | 241 | @override 242 | _HomePageState createState() => _HomePageState(); 243 | } 244 | 245 | 246 | class _HomePageState extends State { 247 | @override 248 | Widget build(BuildContext context) { 249 | return AdaptiveBuilder( 250 | breakpointData: Breakpoint.of(context).copyWith( 251 | minSmallScreenWidth: , 252 | minMediumScreenWidth: , 253 | minLargeHandsetWith: , 254 | minLargeDesktopWidth: , 255 | ... 256 | ), 257 | ); 258 | } 259 | } 260 | ``` 261 | 262 | 2. Or pass a fresh **breakpointData** by creating the **breakpointData** from scratch: 263 | 264 | ```dart 265 | class HomePage extends StatefulWidget { 266 | const HomePage({Key? key}) : super(key: key); 267 | 268 | @override 269 | _HomePageState createState() => _HomePageState(); 270 | } 271 | 272 | class _HomePageState extends State { 273 | @override 274 | Widget build(BuildContext context) { 275 | return AdaptiveBuilder( 276 | breakpointData: BreakpointData( 277 | minSmallScreenWidth: 350, 278 | minMediumScreenWidth: 700, 279 | minLargeScreenWidth: 1200, 280 | minXLargeScreenWidth: 1800, 281 | minMediumHandsetWith: 350, 282 | minLargeHandsetWith: 420, 283 | minSmallTabletWidth: 600, 284 | minLargeTabletWidth: 900, 285 | minSmallDesktopWidth: 1100, 286 | minMediumDesktopWidth: 1400, 287 | minLargeDesktopWidth: 1900, 288 | ), 289 | ); 290 | } 291 | } 292 | ``` 293 | 294 | ### layoutDelegate 295 | 296 | You can use this param to build your UI based on your purpose. 297 | 298 | You must pass an object of **AdaptiveLayoutDelegate** to this param. 299 | 300 | The **AdaptiveLayoutDelegate** is an abstract class and so you must implement a custom class. 301 | 302 | don't worry!!! 303 | 304 | I have provided some custom implementations for you. 305 | 306 | ### AdaptiveLayoutDelegateWithScreenType 307 | 308 | This delegate builds layout based on the **ScreenType** (smallHandset , mediumhandset , largeHandset , smallTablet , largeTablet , smallDesktop , mediumDesktop , largeDesktop). 309 | 310 | All params are **optional**. 311 | 312 | You must pass a [AdaptiveWidgetBuilder](#adaptivewidgetbuilder) to the all params. 313 | 314 | 315 | 316 | ```dart 317 | class HomePage extends StatefulWidget { 318 | const HomePage({Key? key}) : super(key: key); 319 | 320 | @override 321 | _HomePageState createState() => _HomePageState(); 322 | } 323 | 324 | class _HomePageState extends State { 325 | @override 326 | Widget build(BuildContext context) { 327 | return AdaptiveBuilder( 328 | defaultBuilder: (BuildContext context, Screen screen) { 329 | return const Center( 330 | child: Text('Default Builder'), 331 | ); 332 | }, 333 | layoutDelegate: AdaptiveLayoutDelegateWithScreenType( 334 | smallHandset: (BuildContext context, Screen screen) { 335 | return const Center( 336 | child: Text('Small Handset'), 337 | ); 338 | }, 339 | mediumHandset: (BuildContext context, Screen screen) { 340 | return const Center( 341 | child: Text('Medium Handset'), 342 | ); 343 | }, 344 | largeHandset: (BuildContext context, Screen screen) { 345 | return const Center( 346 | child: Text('Large Handset'), 347 | ); 348 | }, 349 | smallTablet: (BuildContext context, Screen screen) { 350 | return const Center( 351 | child: Text('Small Tablet'), 352 | ); 353 | }, 354 | largeTablet: (BuildContext context, Screen screen) { 355 | return const Center( 356 | child: Text('Large Tablet'), 357 | ); 358 | }, 359 | smallDesktop: (BuildContext context, Screen screen) { 360 | return const Center( 361 | child: Text('Small Desktop'), 362 | ); 363 | }, 364 | mediumDesktop: (BuildContext context, Screen screen) { 365 | return const Center( 366 | child: Text('Medium Desktop'), 367 | ); 368 | }, 369 | largeDesktop: (BuildContext context, Screen screen) { 370 | return const Center( 371 | child: Text('Large Desktop'), 372 | ); 373 | }, 374 | ), 375 | ); 376 | } 377 | } 378 | ``` 379 | 380 | 381 | 382 | 383 | ### AdaptiveLayoutDelegateWithMinimallScreenType 384 | 385 | This delegate builds layout based on the minimall **ScreenType** (handset , tablet , desktop). 386 | 387 | All params are **optional**. 388 | 389 | smallHandsrt , mediumHandset and largeHandset are interpreted as **handset**. 390 | 391 | smallTablet and largeTablet are interpreted as **tablet**. 392 | 393 | smallDesktop , mediumDesktop and largeDesktop are interpreted as **desktop**. 394 | 395 | You must pass a [AdaptiveWidgetBuilder](#adaptivewidgetbuilder) to the all params. 396 | 397 | 398 | 399 | 400 | ```dart 401 | class HomePage extends StatefulWidget { 402 | const HomePage({Key? key}) : super(key: key); 403 | 404 | @override 405 | _HomePageState createState() => _HomePageState(); 406 | } 407 | 408 | class _HomePageState extends State { 409 | @override 410 | Widget build(BuildContext context) { 411 | return AdaptiveBuilder( 412 | defaultBuilder: (BuildContext context, Screen screen) { 413 | return const Center( 414 | child: Text('Default Builder'), 415 | ); 416 | }, 417 | layoutDelegate: AdaptiveLayoutDelegateWithMinimallScreenType( 418 | handset: (BuildContext context, Screen screen) { 419 | return const Center( 420 | child: Text('Handset'), 421 | ); 422 | }, 423 | tablet: (BuildContext context, Screen screen) { 424 | return const Center( 425 | child: Text('Tablet'), 426 | ); 427 | }, 428 | desktop: (BuildContext context, Screen screen) { 429 | return const Center( 430 | child: Text('Desktop'), 431 | ); 432 | }, 433 | )); 434 | } 435 | } 436 | 437 | ``` 438 | 439 | 440 | 441 | 442 | ### AdaptiveLayoutDelegateWithScreenSize 443 | 444 | This delegate builds layout based on the **ScreenSize** (xSmall , small , medium , large , xLarge). 445 | 446 | All params are **optional**. 447 | 448 | You must pass a [AdaptiveWidgetBuilder](#adaptivewidgetbuilder) to the all params. 449 | 450 | 451 | 452 | 453 | ```dart 454 | class HomePage extends StatefulWidget { 455 | const HomePage({Key? key}) : super(key: key); 456 | 457 | @override 458 | _HomePageState createState() => _HomePageState(); 459 | } 460 | 461 | class _HomePageState extends State { 462 | @override 463 | Widget build(BuildContext context) { 464 | return AdaptiveBuilder( 465 | defaultBuilder: (BuildContext context, Screen screen) { 466 | return const Center( 467 | child: Text('Default Builder'), 468 | ); 469 | }, 470 | layoutDelegate: AdaptiveLayoutDelegateWithScreenSize( 471 | xSmall: (BuildContext context, Screen screen) { 472 | return const Center( 473 | child: Text('XSmall Window'), 474 | ); 475 | }, 476 | small: (BuildContext context, Screen screen) { 477 | return const Center( 478 | child: Text('Small Window'), 479 | ); 480 | }, 481 | medium: (BuildContext context, Screen screen) { 482 | return const Center( 483 | child: Text('Medium Window'), 484 | ); 485 | }, 486 | large: (BuildContext context, Screen screen) { 487 | return const Center( 488 | child: Text('large Window'), 489 | ); 490 | }, 491 | xLarge: (BuildContext context, Screen screen) { 492 | return const Center( 493 | child: Text('XLarge Window'), 494 | ); 495 | }, 496 | ), 497 | ); 498 | } 499 | } 500 | 501 | ``` 502 | 503 | 504 | 505 | ### AdaptiveLayoutDelegateWithMinimallScreenSize 506 | 507 | This delegate builds layout based on the minimall **ScreenSize** (small , medium , large). 508 | 509 | All params are **optional**. 510 | 511 | xSmall and small are interpreted as **small**. 512 | 513 | large and xLarge are interpreted as **large**. 514 | 515 | 516 | 517 | ### AdaptiveLayoutDelegateWithDesignLanguage 518 | 519 | This delegate builds layout based on the **DesignLaguage** (material , cupertino , fluent). 520 | 521 | All params are **optional**. 522 | 523 | You must pass a [AdaptiveWidgetBuilder](#adaptivewidgetbuilder) to the all params. 524 | 525 | 526 | 527 | 528 | ```dart 529 | class HomePage extends StatefulWidget { 530 | const HomePage({Key? key}) : super(key: key); 531 | 532 | @override 533 | _HomePageState createState() => _HomePageState(); 534 | } 535 | 536 | class _HomePageState extends State { 537 | @override 538 | Widget build(BuildContext context) { 539 | return AdaptiveBuilder( 540 | defaultBuilder: (BuildContext context, Screen screen) { 541 | return const Center( 542 | child: Text('Default Builder'), 543 | ); 544 | }, 545 | allOsDelegate: AdaptiveLayoutDelegateWithDesignLanguage( 546 | material: (BuildContext context, Screen screen) { 547 | return const Center( 548 | child: Text('Material'), 549 | ); 550 | }, 551 | cupertino: (BuildContext context, Screen screen) { 552 | return const Center( 553 | child: Text('Cupertino'), 554 | ); 555 | }, 556 | fluent: (BuildContext context, Screen screen) { 557 | return const Center( 558 | child: Text('Fluent'), 559 | ); 560 | }, 561 | ), 562 | ); 563 | } 564 | } 565 | 566 | ``` 567 | 568 | 569 | 570 | 571 | ### AdaptiveLayoutDelegateWithSingleBuilder 572 | 573 | This delegate takes a builder and builds layout for all types by that single builder. 574 | 575 | ### defaultBuilder 576 | 577 | If the **layoutDelegate** is not passed or it is passed but a custom builder for the desired purpos (ScreenSize , ScreenType , DesignLanguage) is not provided, then the **defaultBuilder** is used to build UI. 578 | 579 | You must pass a [AdaptiveWidgetBuilder](#adaptivewidgetbuilder) to this param. 580 | 581 | 582 | 583 | 584 | ### AdaptiveWidgetBuilder 585 | 586 | This builder gives you a **BuildContext** and a [Screen](#screen) and you must return a widget. 587 | 588 | ```dart 589 | typedef AdaptiveWidgetBuilder = Widget Function( 590 | BuildContext context, Screen screen); 591 | ``` 592 | 593 | For more information about the **Screen** follow [this](#screen) 594 | 595 | ### AdaptiveBuilder Custom Constructor (AdaptiveBuilder.custom) 596 | 597 | The custom constructor of the **AdaptiveBuilder** accepts following params: 598 | 599 | | Param | Type | 600 | | ----------------------| ----------------------------------------- | 601 | | defaultBuilder | AdaptiveWidgetBuilder (Required) | 602 | | [androidDelegate](#androiddelegate) | AdaptiveLayoutDelegate? (Optional) | 603 | | [fuchsiaDelegate](#fuchsiadelegate) | AdaptiveLayoutDelegate? (Optional) | 604 | | [iosDelegate](#iosdelegate) | AdaptiveLayoutDelegate? (Optional) | 605 | | [windowsDelegate](#windowsdelegate) | AdaptiveLayoutDelegate? (Optional) | 606 | | [macosDelegate](#macosdelegate) | AdaptiveLayoutDelegate? (Optional) | 607 | | [linuxDelegate](#linuxdelegate) | AdaptiveLayoutDelegate? (Optional) | 608 | | [webDelegate](#webdelegate) | AdaptiveLayoutDelegate? (Optional) | 609 | | [allPlatformsDelegate](#allplatformsdelegate) | AdaptiveLayoutDelegate? (Optional) | 610 | | [breakpointData](#breakpointdata) | BreakpointData? (Optional) | 611 | 612 | 613 | ### androidDelegate 614 | 615 | By this param you can build your custom UI for android platform. 616 | 617 | You must pass a **AdaptiveLayoutDelegate** to this param. 618 | 619 | ### fuchsiaDelegate 620 | 621 | By this param you can build your custom UI for fuchsia platform. 622 | 623 | You must pass a **AdaptiveLayoutDelegate** to this param. 624 | 625 | 626 | ### iosDelegate 627 | 628 | By this param you can build your custom UI for iOS platform. 629 | 630 | You must pass a **AdaptiveLayoutDelegate** to this param. 631 | 632 | 633 | ### windowsDelegate 634 | 635 | By this param you can build your custom UI for windows platform. 636 | 637 | You must pass a **AdaptiveLayoutDelegate** to this param. 638 | 639 | 640 | ### macosDelegate 641 | 642 | By this param you can build your custom UI for macOS platform. 643 | 644 | You must pass a **AdaptiveLayoutDelegate** to this param. 645 | 646 | 647 | ### linuxDelegate 648 | 649 | By this param you can build your custom UI for linux platform. 650 | 651 | You must pass a **AdaptiveLayoutDelegate** to this param. 652 | 653 | 654 | ### webDelegate 655 | 656 | By this param you can build your custom UI for web platform. 657 | 658 | You must pass a **AdaptiveLayoutDelegate** to this param. 659 | 660 | 661 | For all these params you can use the following implementations: 662 | 663 | * [AdaptiveLayoutDelegateWithScreenType](#adaptivelayoutdelegatewithscreentype) 664 | * [AdaptiveLayoutDelegateWithMinimallScreenType](#adaptivelayoutdelegatewithminimallscreentype) 665 | * [AdaptiveLayoutDelegateWithScreenSize](#adaptivelayoutdelegatewithscreensize) 666 | * [AdaptiveLayoutDelegateWithMinimallScreenSize](#adaptivelayoutdelegatewithminimallscreensize) 667 | * [AdaptiveLayoutDelegateWithDesignLanguage](#adaptivelayoutdelegatewithdesignlanguage) 668 | * [AdaptiveLayoutDelegateWithSingleBuilder](#adaptivelayoutdelegatewithsinglebuilder). 669 | 670 | 671 | 672 | ### allPlatformsDelegate 673 | 674 | If for the desired platform is not passed a **AdaptiveLayoutDelegate** or it is passed but a custom builder for the desired purpos (ScreenSize , ScreenType , DesignLanguage) is not provided, then the **AdaptiveBuilder** uses this param to build UI. 675 | 676 | You must pass a **AdaptiveLayoutDelegate** to this param. 677 | 678 | This parm is like the [layoutDelegate](#layoutdelegate) in the default constructor.For more information you can see the [layoutDelegate](#layoutdelegate). 679 | 680 | ### defaultBuilder 681 | 682 | If custom delegates (androidDelegate , ...) and **allPlatformsDelegate** can not build UI, then this param is used to build UI. 683 | 684 | You must pass a [AdaptiveWidgetBuilder](#adaptivewidgetbuilder) to this param. 685 | 686 | ```dart 687 | class HomePage extends StatefulWidget { 688 | const HomePage({Key? key}) : super(key: key); 689 | 690 | @override 691 | _HomePageState createState() => _HomePageState(); 692 | } 693 | 694 | class _HomePageState extends State { 695 | @override 696 | Widget build(BuildContext context) { 697 | return AdaptiveBuilder( 698 | defaultBuilder: (BuildContext context, Screen screen) { 699 | return const Center( 700 | child: Text('Default Builder'), 701 | ); 702 | }, 703 | ); 704 | } 705 | ``` 706 | 707 | ## Summary 708 | 709 | First of all, the **AdaptiveBuilder** obtains the **ScreenSize** , **ScreenType** and **Designlanguage** and then builds UI based on the following rules: 710 | 711 | ##### PlatformType 712 | 713 | The PlatformType is _android_ , _fuchsia_ , _iOS_ , _windows_ , _linux_ , _macOS_ or _web_ . 714 | 715 | First of all, this widget uses a custom delegate based on the **PaltformType** (androidDelegate , fuchsiaDelegate , iosDelegate , windowsDelegate , macOSDelegate , linuxDelegate or webDelegate) to building UI. 716 | 717 | ##### allPlatformsDelagate 718 | 719 | If a custom delegate is not provided or the custom delegate is provided but it does not provide a custom builder for the desired size, It will use the **allPlatformsDelegate** for building UI. 720 | 721 | ##### defaultBuilder 722 | 723 | Eventually, If for the desired platform is not provided a custom delegate or the custom delegate does not provide a custom builder for the desired size 724 | and the **allPlatformDelegate** also does not provide that builder ,it will use the builder param for building UI. 725 | 726 | 727 | ## PlatformBuilder 728 | 729 | The documents will be written in the future. 730 | 731 | ## AdaptiveDesign 732 | 733 | ```dart 734 | @override 735 | Widget build(BuildContext context) { 736 | return AdaptiveDesign( 737 | defaultBuilder: (BuildContext context, Screen screen) { 738 | return const Center( 739 | child: Text('Default Builder'), 740 | ); 741 | }, 742 | material: (BuildContext context, Screen screen) { 743 | return const Center( 744 | child: Text('Material'), 745 | ); 746 | }, 747 | cupertino: (BuildContext context, Screen screen) { 748 | return const Center( 749 | child: Text('Cupertino'), 750 | ); 751 | }, 752 | fluent: (BuildContext context, Screen screen) { 753 | return const Center( 754 | child: Text('Fluent'), 755 | ); 756 | }, 757 | ); 758 | } 759 | ``` 760 | 761 | ## Screen 762 | 763 | **Screen** is an object that gives you some informations from the Window. 764 | I called it **Screen**, not **Window**, because of there is an Object with this name (Window) in Flutter(see **WidgetsBinding.window). 765 | 766 | The **Screen** has following params: 767 | 768 | | Param | Type | Definition | 769 | | ----------------------| --------------------- | ----------------| 770 | | mediaQueryData | MediaQueryData | The **mediaQueryData** from the closest **MediaQuery** instance that encloses the given context. | 771 | | breakpointData | BreakpointData | _ | 772 | | screenSize | ScreenSize | xSmall , small , medium , large , xLarge | 773 | | screenType | ScreenType | (small,medium,large)Handset , (small,large)Tablet , (small,medium,large)Desktop | 774 | | designLanguage | DesignLanguage | material , cupertino , fluent | 775 | | platform | PlatformType | android , fuchsia , ios , windows , macos , linux , web | 776 | 777 | This object is passed to the **AdaptiveWidgetBuilder** and then you can use that to obtain some information about your window. 778 | 779 | You can also use following constructors to create a **Screen* by yourself. 780 | 781 | #### Screen.fromContext(BuildContext context) 782 | 783 | This factory constructor takes a context and then obtains the **mediaQueryData** and the **breakpointData** based on. 784 | 785 | #### Screen.fromWindow() 786 | 787 | This factory constructor uses the **FlutterWindow** (WidgetsBinding.instance.window) and then obtains the **mediaQueryData** by the **MediaQueryData.fromWidow** constructor and also uses the default sizes for obtain the **breakpointData**. 788 | 789 | ## Helpers 790 | 791 | #### getDefaultPlatform() 792 | 793 | _getDefaultPlatform()_ is a top level function that gives you the **PlatformType**.(web , android , fuchsia , iOS , windows , macOS , linux) 794 | 795 | #### getDefaultDesignLanguage() 796 | 797 | _getDefaultDesignLanguage()_ is a top level function that gives you the **DesignLanguage**.(material , cupertino , fluent) 798 | 799 | 800 | 801 | ``` 802 | MIT License 803 | 804 | Copyright (c) 2022 Mohammad Taheri 805 | 806 | Permission is hereby granted, free of charge, to any person obtaining a copy 807 | of this software and associated documentation files (the "Software"), to deal 808 | in the Software without restriction, including without limitation the rights 809 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 810 | copies of the Software, and to permit persons to whom the Software is 811 | furnished to do so, subject to the following conditions: 812 | 813 | The above copyright notice and this permission notice shall be included in all 814 | copies or substantial portions of the Software. 815 | 816 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 817 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 818 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 819 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 820 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 821 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 822 | SOFTWARE. 823 | ``` 824 | --------------------------------------------------------------------------------