Last updated:
0 purchases
flutter adaptive ui
Flutter Adaptive UI #
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.
For more informations follow this link.
Documentation #
Quick start API tour #
Overview
Breakpoint
AdaptiveBuilder
PlatformBuilder
AdaptiveDesign
Screen
Helpers
Overview #
This package helps you for building Adaptive UI.For this purpose, we are going to use the following params:
Platform Type
android
fuchsia
iOS
windows
macOS
linux
web
Screen Size
X Small
Small
Medium
Large
X Lagre
Screen Type
Small Handset
Medium Handset
Large Handset
Small Tablet
Large Tablet
Small Desktop
Medium Desktop
Large Desktop
Design Language
Material
Cupertino
Fluent
Then we are going to use the following widgets for building Adaptive UI based on these params:
AdaptiveBuilder
PlatformBuilder
AdaptiveDesign
But before we focus on above widgets, let's talk about Breakpoint.
Breakpoint #
By default the Screen Size and the Screen Type are obtained based on the following values:
Screen Width Range
Screen Size
Screen Type
0-359
X Small
Small Handset
360-399
X Small
Medium Handset
400-599
X Small
Large Handset
600-719
Small
Small Tablet
720-1023
Small
Large Tablet
1023-1439
Medium
Small Desktop
1440-1919
Large
Medium Desktop
1920+
X Large
Large Desktop
And the Design language :
Platform
Design Language
Android - Fuchsia
Material
IOS - MacOs
Cupertino
Windows
Fluent
Others
Material
You can change the default sizes by wrapping your MaterialApp in a Breakpoint widget:
import 'package:flutter/material.dart';
import 'package:flutter_adaptive_ui/flutter_adaptive_ui.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return const Breakpoint(
child: MaterialApp(
home: HomePage(),
),
);
}
}
copied to clipboard
Now you can change the default sizes by pass a breakpoint Data to the Breakpoint's constructor:
import 'package:flutter/material.dart';
import 'package:flutter_adaptive_ui/flutter_adaptive_ui.dart';
main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return const Breakpoint(
// Use default sizes or override.
breakpointData: BreakpointData(
// Based on [ScreenSize] (xSmall , small , medium , large , xLarge)
minSmallScreenWidth: 600,
minMediumScreenWidth: 1024,
minLargeScreenWidth: 1440,
minXLargeScreenWidth: 1920,
// Based on [ScreenType] (smallHandset , mediumHandset , largeHandset , smallTablet , largetablet , smallDesktop , mediumDesktop , largeDesktop)
minMediumHandsetWith: 360,
minLargeHandsetWith: 400,
minSmallTabletWidth: 600,
minLargeTabletWidth: 720,
minSmallDesktopWidth: 1024,
minMediumDesktopWidth: 1440,
minLargeDesktopWidth: 1920,
),
child: MaterialApp(
home: HomePage(),
),
);
}
}
copied to clipboard
All params are optional.
Param
Definition
Default value
minSmallScreenWidth
The Minimum Width of the small Screen
600
minMediumScreenWidth
The Minimum Width of the medium Screen
1024
minLargeScreenWidth
The Minimum Width of the large Screen
1440
minXLargeScreenWidth
The Minimum Width of the xLarge Screen
1920
minMediumHandsetWith
The Minimum Width of the medium handset
360
minLargeHandsetWith
The Minimum Width of the large hanset
400
minSmallTabletWidth
The Minimum Width of the small tablet
600
minLargeTabletWidth
The Minimum Width of the large tablet
720
minSmallDesktopWidth
The Minimum Width of the small desktop
1024
minMediumDesktopWidth
The Minimum Width of the medium desktop
1440
minLargeDesktopWidth
The Minimum Width of the large desktop
1920
If the screen width is less than the minSmallScreenWidth (default = 600),the Screen Size will be xSmall.
If the screen width is less than the minMediumHandsetWith (default = 360), the Screen Type will be smallHandset.
Breakpoint.of(context)
The Breakpoint widget is an InheritedWidget and so you can use the Breakpoint.of(context) (static method) to obtain the BreakpointData.
After talking about the Breakpoint, Now is the time that we talk about the AdaptiveBuilder widget for building Adaptive UI.
let's go.
AdaptiveBuilder #
You should use the AdaptiveBuilder widget to build an adaptive UI.
Wrap your entire screen with this widget:
class HomePage extends StatefulWidget {
const HomePage({Key? key}) : super(key: key);
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
@override
Widget build(BuildContext context) {
return AdaptiveBuilder(
);
}
}
copied to clipboard
The AdaptiveBuilder has two contructors.
AdaptiveBuilder Default Constructor
The default constructor of the AdaptiveBuilder accepts three params:
Param
Type
defaultBuilder
AdaptiveWidgetBuilder (Required)
layoutDelegate
AdaptiveLayoutDelegate? (Optional)
breakpointData
BreakpointData? (Optional)
breakpointData #
The AdaptiveBuilder obtains the BreakpointData based on the following rules:
the breakpointData param that is passed to its constructor.
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.
If there is no Breakpoint in the widget tree above the AdaptiveBuilder, it will use the default sizes.
Use this param to change the default sizes:
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:
class HomePage extends StatefulWidget {
const HomePage({Key? key}) : super(key: key);
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
@override
Widget build(BuildContext context) {
return AdaptiveBuilder(
breakpointData: Breakpoint.of(context).copyWith(
minSmallScreenWidth: ,
minMediumScreenWidth: ,
minLargeHandsetWith: ,
minLargeDesktopWidth: ,
...
),
);
}
}
copied to clipboard
Or pass a fresh breakpointData by creating the breakpointData from scratch:
class HomePage extends StatefulWidget {
const HomePage({Key? key}) : super(key: key);
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
@override
Widget build(BuildContext context) {
return AdaptiveBuilder(
breakpointData: BreakpointData(
minSmallScreenWidth: 350,
minMediumScreenWidth: 700,
minLargeScreenWidth: 1200,
minXLargeScreenWidth: 1800,
minMediumHandsetWith: 350,
minLargeHandsetWith: 420,
minSmallTabletWidth: 600,
minLargeTabletWidth: 900,
minSmallDesktopWidth: 1100,
minMediumDesktopWidth: 1400,
minLargeDesktopWidth: 1900,
),
);
}
}
copied to clipboard
layoutDelegate #
You can use this param to build your UI based on your purpose.
You must pass an object of AdaptiveLayoutDelegate to this param.
The AdaptiveLayoutDelegate is an abstract class and so you must implement a custom class.
don't worry!!!
I have provided some custom implementations for you.
AdaptiveLayoutDelegateWithScreenType #
This delegate builds layout based on the ScreenType (smallHandset , mediumhandset , largeHandset , smallTablet , largeTablet , smallDesktop , mediumDesktop , largeDesktop).
All params are optional.
You must pass a AdaptiveWidgetBuilder to the all params.
class HomePage extends StatefulWidget {
const HomePage({Key? key}) : super(key: key);
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
@override
Widget build(BuildContext context) {
return AdaptiveBuilder(
defaultBuilder: (BuildContext context, Screen screen) {
return const Center(
child: Text('Default Builder'),
);
},
layoutDelegate: AdaptiveLayoutDelegateWithScreenType(
smallHandset: (BuildContext context, Screen screen) {
return const Center(
child: Text('Small Handset'),
);
},
mediumHandset: (BuildContext context, Screen screen) {
return const Center(
child: Text('Medium Handset'),
);
},
largeHandset: (BuildContext context, Screen screen) {
return const Center(
child: Text('Large Handset'),
);
},
smallTablet: (BuildContext context, Screen screen) {
return const Center(
child: Text('Small Tablet'),
);
},
largeTablet: (BuildContext context, Screen screen) {
return const Center(
child: Text('Large Tablet'),
);
},
smallDesktop: (BuildContext context, Screen screen) {
return const Center(
child: Text('Small Desktop'),
);
},
mediumDesktop: (BuildContext context, Screen screen) {
return const Center(
child: Text('Medium Desktop'),
);
},
largeDesktop: (BuildContext context, Screen screen) {
return const Center(
child: Text('Large Desktop'),
);
},
),
);
}
}
copied to clipboard
AdaptiveLayoutDelegateWithMinimallScreenType #
This delegate builds layout based on the minimall ScreenType (handset , tablet , desktop).
All params are optional.
smallHandsrt , mediumHandset and largeHandset are interpreted as handset.
smallTablet and largeTablet are interpreted as tablet.
smallDesktop , mediumDesktop and largeDesktop are interpreted as desktop.
You must pass a AdaptiveWidgetBuilder to the all params.
class HomePage extends StatefulWidget {
const HomePage({Key? key}) : super(key: key);
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
@override
Widget build(BuildContext context) {
return AdaptiveBuilder(
defaultBuilder: (BuildContext context, Screen screen) {
return const Center(
child: Text('Default Builder'),
);
},
layoutDelegate: AdaptiveLayoutDelegateWithMinimallScreenType(
handset: (BuildContext context, Screen screen) {
return const Center(
child: Text('Handset'),
);
},
tablet: (BuildContext context, Screen screen) {
return const Center(
child: Text('Tablet'),
);
},
desktop: (BuildContext context, Screen screen) {
return const Center(
child: Text('Desktop'),
);
},
));
}
}
copied to clipboard
AdaptiveLayoutDelegateWithScreenSize #
This delegate builds layout based on the ScreenSize (xSmall , small , medium , large , xLarge).
All params are optional.
You must pass a AdaptiveWidgetBuilder to the all params.
class HomePage extends StatefulWidget {
const HomePage({Key? key}) : super(key: key);
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
@override
Widget build(BuildContext context) {
return AdaptiveBuilder(
defaultBuilder: (BuildContext context, Screen screen) {
return const Center(
child: Text('Default Builder'),
);
},
layoutDelegate: AdaptiveLayoutDelegateWithScreenSize(
xSmall: (BuildContext context, Screen screen) {
return const Center(
child: Text('XSmall Window'),
);
},
small: (BuildContext context, Screen screen) {
return const Center(
child: Text('Small Window'),
);
},
medium: (BuildContext context, Screen screen) {
return const Center(
child: Text('Medium Window'),
);
},
large: (BuildContext context, Screen screen) {
return const Center(
child: Text('large Window'),
);
},
xLarge: (BuildContext context, Screen screen) {
return const Center(
child: Text('XLarge Window'),
);
},
),
);
}
}
copied to clipboard
AdaptiveLayoutDelegateWithMinimallScreenSize #
This delegate builds layout based on the minimall ScreenSize (small , medium , large).
All params are optional.
xSmall and small are interpreted as small.
large and xLarge are interpreted as large.
AdaptiveLayoutDelegateWithDesignLanguage #
This delegate builds layout based on the DesignLaguage (material , cupertino , fluent).
All params are optional.
You must pass a AdaptiveWidgetBuilder to the all params.
class HomePage extends StatefulWidget {
const HomePage({Key? key}) : super(key: key);
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
@override
Widget build(BuildContext context) {
return AdaptiveBuilder(
defaultBuilder: (BuildContext context, Screen screen) {
return const Center(
child: Text('Default Builder'),
);
},
allOsDelegate: AdaptiveLayoutDelegateWithDesignLanguage(
material: (BuildContext context, Screen screen) {
return const Center(
child: Text('Material'),
);
},
cupertino: (BuildContext context, Screen screen) {
return const Center(
child: Text('Cupertino'),
);
},
fluent: (BuildContext context, Screen screen) {
return const Center(
child: Text('Fluent'),
);
},
),
);
}
}
copied to clipboard
AdaptiveLayoutDelegateWithSingleBuilder #
This delegate takes a builder and builds layout for all types by that single builder.
defaultBuilder #
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.
You must pass a AdaptiveWidgetBuilder to this param.
AdaptiveWidgetBuilder #
This builder gives you a BuildContext and a Screen and you must return a widget.
typedef AdaptiveWidgetBuilder = Widget Function(
BuildContext context, Screen screen);
copied to clipboard
For more information about the Screen follow this
AdaptiveBuilder Custom Constructor (AdaptiveBuilder.custom) #
The custom constructor of the AdaptiveBuilder accepts following params:
Param
Type
defaultBuilder
AdaptiveWidgetBuilder (Required)
androidDelegate
AdaptiveLayoutDelegate? (Optional)
fuchsiaDelegate
AdaptiveLayoutDelegate? (Optional)
iosDelegate
AdaptiveLayoutDelegate? (Optional)
windowsDelegate
AdaptiveLayoutDelegate? (Optional)
macosDelegate
AdaptiveLayoutDelegate? (Optional)
linuxDelegate
AdaptiveLayoutDelegate? (Optional)
webDelegate
AdaptiveLayoutDelegate? (Optional)
allPlatformsDelegate
AdaptiveLayoutDelegate? (Optional)
breakpointData
BreakpointData? (Optional)
androidDelegate #
By this param you can build your custom UI for android platform.
You must pass a AdaptiveLayoutDelegate to this param.
fuchsiaDelegate #
By this param you can build your custom UI for fuchsia platform.
You must pass a AdaptiveLayoutDelegate to this param.
iosDelegate #
By this param you can build your custom UI for iOS platform.
You must pass a AdaptiveLayoutDelegate to this param.
windowsDelegate #
By this param you can build your custom UI for windows platform.
You must pass a AdaptiveLayoutDelegate to this param.
macosDelegate #
By this param you can build your custom UI for macOS platform.
You must pass a AdaptiveLayoutDelegate to this param.
linuxDelegate #
By this param you can build your custom UI for linux platform.
You must pass a AdaptiveLayoutDelegate to this param.
webDelegate #
By this param you can build your custom UI for web platform.
You must pass a AdaptiveLayoutDelegate to this param.
For all these params you can use the following implementations:
AdaptiveLayoutDelegateWithScreenType
AdaptiveLayoutDelegateWithMinimallScreenType
AdaptiveLayoutDelegateWithScreenSize
AdaptiveLayoutDelegateWithMinimallScreenSize
AdaptiveLayoutDelegateWithDesignLanguage
AdaptiveLayoutDelegateWithSingleBuilder.
allPlatformsDelegate #
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.
You must pass a AdaptiveLayoutDelegate to this param.
This parm is like the layoutDelegate in the default constructor.For more information you can see the layoutDelegate.
defaultBuilder #
If custom delegates (androidDelegate , ...) and allPlatformsDelegate can not build UI, then this param is used to build UI.
You must pass a AdaptiveWidgetBuilder to this param.
class HomePage extends StatefulWidget {
const HomePage({Key? key}) : super(key: key);
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
@override
Widget build(BuildContext context) {
return AdaptiveBuilder(
defaultBuilder: (BuildContext context, Screen screen) {
return const Center(
child: Text('Default Builder'),
);
},
);
}
copied to clipboard
Summary #
First of all, the AdaptiveBuilder obtains the ScreenSize , ScreenType and Designlanguage and then builds UI based on the following rules:
PlatformType
The PlatformType is android , fuchsia , iOS , windows , linux , macOS or web .
First of all, this widget uses a custom delegate based on the PaltformType (androidDelegate , fuchsiaDelegate , iosDelegate , windowsDelegate , macOSDelegate , linuxDelegate or webDelegate) to building UI.
allPlatformsDelagate
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.
defaultBuilder
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
and the allPlatformDelegate also does not provide that builder ,it will use the builder param for building UI.
PlatformBuilder #
The documents will be written in the future.
AdaptiveDesign #
@override
Widget build(BuildContext context) {
return AdaptiveDesign(
defaultBuilder: (BuildContext context, Screen screen) {
return const Center(
child: Text('Default Builder'),
);
},
material: (BuildContext context, Screen screen) {
return const Center(
child: Text('Material'),
);
},
cupertino: (BuildContext context, Screen screen) {
return const Center(
child: Text('Cupertino'),
);
},
fluent: (BuildContext context, Screen screen) {
return const Center(
child: Text('Fluent'),
);
},
);
}
copied to clipboard
Screen #
Screen is an object that gives you some informations from the Window.
I called it Screen, not Window, because of there is an Object with this name (Window) in Flutter(see **WidgetsBinding.window).
The Screen has following params:
Param
Type
Definition
mediaQueryData
MediaQueryData
The mediaQueryData from the closest MediaQuery instance that encloses the given context.
breakpointData
BreakpointData
_
screenSize
ScreenSize
xSmall , small , medium , large , xLarge
screenType
ScreenType
(small,medium,large)Handset , (small,large)Tablet , (small,medium,large)Desktop
designLanguage
DesignLanguage
material , cupertino , fluent
platform
PlatformType
android , fuchsia , ios , windows , macos , linux , web
This object is passed to the AdaptiveWidgetBuilder and then you can use that to obtain some information about your window.
You can also use following constructors to create a *Screen by yourself.
Screen.fromContext(BuildContext context)
This factory constructor takes a context and then obtains the mediaQueryData and the breakpointData based on.
Screen.fromWindow()
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.
Helpers #
getDefaultPlatform()
getDefaultPlatform() is a top level function that gives you the PlatformType.(web , android , fuchsia , iOS , windows , macOS , linux)
getDefaultDesignLanguage()
getDefaultDesignLanguage() is a top level function that gives you the DesignLanguage.(material , cupertino , fluent)
MIT License
Copyright (c) 2022 Mohammad Taheri
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
copied to clipboard
For personal and professional use. You cannot resell or redistribute these repositories in their original state.
There are no reviews.