I am new in flutter web I want to create a website that is fully responsive I use from many packages but it is not desirable for me. I used from screen uttil pacakge and also screen, but the are useful for mobile apps it doesn't suitable for websites. Please guide me how to creae reponsive size like responsive fontsize, margin and padding, when I run it in desktop, tablet and mobile device it decrease the size automatically.
There are three basic ways of making your application on website in a responsive manner. (That I personally have tried )
number one ) MediaQuery. This method is the one that I usually go with as it is more understandable for me. This is an example of how you create Responsiveness through MediaQuery.
import 'package:flutter/material.dart';
class Responsive extends StatelessWidget {
final Widget mobile;
final Widget? mobileLarge;
final Widget? tablet;
final Widget desktop;
const Responsive({
Key? key,
required this.mobile,
this.tablet,
required this.desktop,
this.mobileLarge,
}) : super(key: key);
static bool isMobile(BuildContext context) =>
MediaQuery.of(context).size.width <= 500;
static bool isMobileLarge(BuildContext context) =>
MediaQuery.of(context).size.width <= 700;
static bool isTablet(BuildContext context) =>
MediaQuery.of(context).size.width < 1024;
static bool isDesktop(BuildContext context) =>
MediaQuery.of(context).size.width >= 1024;
#override
Widget build(BuildContext context) {
final Size _size = MediaQuery.of(context).size;
if (_size.width >= 1024) {
return desktop;
} else if (_size.width >= 700 && tablet != null) {
return tablet!;
} else if (_size.width >= 500 && mobileLarge != null) {
return mobileLarge!;
} else {
return mobile;
}
}
}
Through the basic use of ternary Operators we can modify the size. a basic example.
Text('Hello World', style: TextStyle(fontsize: Responsive.tablet ? 41 : 12),),
A link to a little tutorial.
https://www.youtube.com/watch?v=QAHqlsAky_4
number two) Layout Builder. You call this method in main and then create 3-4 (depending on the scenario) widgets with each different size in them.
import 'package:flutter/material.dart';
class LayoutBuildResp extends StatelessWidget {
final Widget mobileScreenLayout;
final Widget tabletScreenLayout;
final Widget webScreenLayout;
LayoutBuildResp(
{required this.mobileScreenLayout,
required this.tabletScreenLayout,
required this.webScreenLayout});
#override
Widget build(BuildContext context) {
return LayoutBuilder(
builder: (context, constraints) {
if (constraints.maxWidth < 600) {
return mobileScreenLayout;
} else if (constraints.maxWidth < 900) {
return tabletScreenLayout;
} else {
return webScreenLayout;
}
},
);
}
}
And in main.dart or any other page.
Scaffold(
body: LayoutBuilderResp(
mobileBody: MyMobileBody(),
desktopBody: MyDesktopBody(),
tabletBody: MyTabletBOdy(),
),
);
a Youtube tutorial: https://www.youtube.com/watch?v=MrPJBAOzKTQ
number 3) Packages. https://pub.dev/packages/responsive_layout_builder
Although I am leaving my github code where I have both layoutBuilder and MediaQuery applied you can check it out. you have to change the code in main.dart accordingly.
https://github.com/ALIJAad/web-sample.
Happy Coding.
Related
I'm making a responsive widget in Flutter (this question was asked on Stack Overflow). My app shows the mobile screen when using a mobile device, the tablet screen when using a tablet device, and the desktop screen when using a desktop device. However, my mobile device shows the tablet screen when I rotate it, even though I'm using a mobile.
I tried this package but still get the same result.
My code:
import 'package:flutter/material.dart';
import 'package:sizer/sizer.dart';
class Responsive extends StatelessWidget {
const Responsive({required this.mobile, required this.tablet, required this.desktop, super.key});
final Widget mobile;
final Widget tablet;
final Widget desktop;
static bool isMobile(BuildContext context) => SizerUtil.deviceType == DeviceType.mobile && SizerUtil.deviceType != DeviceType.tablet;
static bool isTablet(BuildContext context) => SizerUtil.deviceType != DeviceType.mobile && SizerUtil.deviceType == DeviceType.tablet;
static bool isDesktop(BuildContext context) => SizerUtil.deviceType != DeviceType.mobile && SizerUtil.deviceType != DeviceType.tablet;
#override
Widget build(BuildContext context) => LayoutBuilder(
builder: (context, constraints) {
debugPrint("isMobile: ${isMobile(context)}");
debugPrint("isTablet: ${isTablet(context)}");
debugPrint("isDesktop: ${isDesktop(context)}");
return isDesktop(context)
? desktop
: isTablet(context)
? tablet
: mobile;
},
);
}
import 'package:flutter/material.dart';
import 'package:project/desktop_screen.dart';
import 'package:project/mobile_screen.dart';
import 'package:project/tablet_screen.dart';
class MainScreen extends ConsumerWidget {
const MainScreen({super.key});
#override
Widget build(BuildContext context, WidgetRef ref) {
return Responsive(
mobile: const MobileScreen(),
tablet: const TabletScreen(),
desktop: const DesktopScreen(),
);
}
}
Feel free to leave a comment if you need more information.
Why does my mobile device show a tablet screen when rotated, even though I'm using a mobile device? I would appreciate any help. Thank you in advance!
You will have to make separate widgets for landscape and portrait for it to work properly. You can read from the package suggestion for orientation.
Here is also an example to use if you need more references to make orientation work.
For example, you can have this below, it should check and return the widget base on the orientation.
SizerUtil.orientation == Orientation.portrait
? SizedBox(
height: 30.h,
child: Image.network("https://m.media-amazon.com/images/I/518fAl617rL._AC_SY1000_.jpg"),
)
: SizedBox(
height: 10.h,
child: Image.network("https://m.media-amazon.com/images/I/518fAl617rL._AC_SY1000_.jpg"),
),
I want to force a child widget to have a max aspect ratio of e.g. 2.0: in other words, it is no wider than 2:1, but is as tall as possible. So in a tall skinny parent it would behave like SizedBox.expand(child: child), and in a short wide parent it would behave like AspectRatio(aspectRatio: 2.0, child: child).
Is there a widget that does this, like ConstrainedAspectRatio(maxAspectRatio: 2.0, child: child)? Or do I have to choose between (1) using a LayoutBuilder or (2) writing a custom SingleChildLayoutDelegate / SingleChildRenderObjectWidget?
Edit: In case there is no good answer out there, here's my SingleChildLayoutDelegate implementation. It is probably brittle.
import 'dart:math';
import 'package:flutter/material.dart';
class ConstrainedAspectRatio extends StatelessWidget {
const ConstrainedAspectRatio({required this.child, required this.maxAspectRatio, super.key});
final Widget child;
final double maxAspectRatio;
#override
Widget build(BuildContext context) => CustomSingleChildLayout(delegate: _CARDelegate(maxAspectRatio), child: child);
}
class _CARDelegate extends SingleChildLayoutDelegate {
_CARDelegate(this.maxAspectRatio);
final double maxAspectRatio;
Size _size = Size.zero;
#override
Size getSize(BoxConstraints constraints) {
// Full height, wide as allowed
final double w = constraints.maxWidth, h = constraints.maxHeight;
if (h.isInfinite) {
// Container infinitely tall; use max aspect ratio as exact aspect ratio
assert(w.isFinite, () => "Need at least one bounded constraint for $runtimeType.");
return _size = Size(w, w / maxAspectRatio);
} else {
// Finite height. Use all of it, and go as wide as maxAspectRatio allows.
return _size = Size(min(h * maxAspectRatio, w), h);
}
}
#override
BoxConstraints getConstraintsForChild(BoxConstraints constraints) {
return BoxConstraints.tight(_size);
}
#override
bool shouldRelayout(covariant _CARDelegate oldDelegate) {
return oldDelegate.maxAspectRatio != maxAspectRatio;
}
}
I'm planning to make an application which should be responsive to all mobile devices.
Suggest some methods.
To make the application responsive, you need to use the MediaQuery.of(context).size to get the dimensions of the device on which the application is running and accordingly you can make some end points at which you want to have some different view according to the size and content.
i´ve used this Tutorial to build a responsive flutter app: https://www.filledstacks.com/post/building-a-responsive-ui-architecture-in-flutter/
The idea behind it is to create one Widget which can hold 3 different Widgets for mobile, tablet and desktop.
I am also using the responsive_framework package https://pub.dev/packages/responsive_framework
With that package you can define different breakpoints:
import 'package:responsive_framework/responsive_framework.dart';
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
builder: (context, child) => ResponsiveWrapper.builder(
child,
maxWidth: 1200,
minWidth: 480,
defaultScale: true,
breakpoints: [
ResponsiveBreakpoint.resize(480, name: MOBILE),
ResponsiveBreakpoint.autoScale(800, name: TABLET),
ResponsiveBreakpoint.resize(1000, name: DESKTOP),
],
background: Container(color: Color(0xFFF5F5F5))),
initialRoute: "/",
);
}
}
And then u can use this breakpoints to decide which layout should be shown:
class ScreenTypeFrame extends StatelessWidget {
final Widget mobile;
final Widget? tablet;
final Widget? desktop;
ScreenTypeFrame({
Key? key,
required this.mobile,
this.tablet,
this.desktop,
}) : super(key: key);
#override
Widget build(BuildContext context) {
if (desktop != null && _isDesktop(context)) {
return desktop!;
} else if (tablet != null && _isTablet(context)) {
return tablet!;
} else {
return mobile;
}
}
bool _isDesktop(BuildContext context) {
return ResponsiveWrapper.of(context).isLargerThan(TABLET);
}
bool _isTablet(BuildContext context) {
return ResponsiveWrapper.of(context).isLargerThan(MOBILE);
}
}
class ResponsivePage extends StatelessWidget {
const ResponsivePage({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return ScreenTypeFrame(
mobile: Text("Mobil"),
tablet: Text("Tablet"),
desktop: Text("Desktop"),
);
}
}
This is not the whole code. There are also helper layout to create different scaffolds for mobile, tablet and desktop with different menus and so on.
The ScreenTypeFrame Widget can be enhanced like this:
#override
Widget build(BuildContext context) {
Widget bodyWidget = _getBodyWidget(context);
if (_isDesktop(context)) {
return DesktopScaffold(
body: bodyWidget,
title: title,
);
} else if (_isTablet(context)) {
return TabletScaffold(
body: bodyWidget,
title: title,
);
}
return MobileScaffold(
body: bodyWidget,
title: title,
);
}
Widget _getBodyWidget(BuildContext context) {
if (desktop != null && _isDesktop(context)) {
return desktop!;
} else if (tablet != null && _isTablet(context)) {
return tablet!;
} else {
return mobile;
}
}
Avoid using fixed height and width values.
Prefer using Expanded, Flexible, SizedBox.expand() in Columns, Rows or Stacks.
If possible develop and test also with flutter web. There you can easily check the responsiveness.
In addition to the previous answer from jannik:
You also might want to take a look into the following resources:
auto_size_text => automatically scale your fontSize up or down
this medium article providing a nice approach for your problem
I've been using flutter_redux for only very few days and I'm wondering what's the difference between:
class BtnCustom extends StatelessWidget {
#override
Widget build(BuildContext context) {
final store = StoreProvider.of<AppState>(context);
return FlatButton(
onPressed: store.dispatch(MyCustomAction),
child: Text(store.state.MyCustomTxt),
);
}
}
and
class BtnCustom extends StatelessWidget {
#override
Widget build(BuildContext context) {
return StoreConnector<AppState, _ViewModel>(
converter: (store) => _ViewModel(
txt: store.state.MyCustomTxt,
onPressed: store.dispatch(MyCustomAction)),
builder: (BuildContext context, _ViewModel vm) {
return FlatButton(
onPressed: vm.onPressed,
child: Text(vm.txt),
);
},
);
}
}
class _ViewModel {
final String txt;
final void Function() onPressed;
_ViewModel({this.txt, this.onPressed});
}
?
The first one seems so handy to use. Are they any advantages or drawbacks of using one over another I should be aware of?
According to the documentation, the StoreConnector will rebuild the widget in it so:
Is it ok to not use a StoreConnector when you don't need to rebuild a widget?
Is it ok to have multiple widgets within a StoreConnector?
StoreConnector gives you more control over widget, especially when you don't want to rebuild it. StoreConnector:
lets you detect whether the ViewModel has changed (whether widget should be rebuilt) if you use distinct: true and override hashCode and == in your ViewModel;
lets you skip widget rebuild altogether by quickly checking some specific store.state:
StoreConnector<AppState, MyViewModel>(
distinct: true,
ignoreChange: (state) {
return state.someVariable == theValueIDontCareAbout;
},
...
),
class MyViewModel{
#override
bool operator ==(other) {
return (other is MyViewModel) && (this.someVmVariable == other.someVmVariable);
}
#override
int get hashCode {
int result = 17;
result = 37 * result + someVmVariable.hashCode;
return result;
}
}
And some more fine-grained controls. Take a look at the documentation of StoreConnector's constructor. If multiple widgets inside store sonnector share the same ViewModel it is natural to have them like that. However, if it's possible to prevent them from rebulding by separating their ViewModels you can use separate StoreConnectors.
am new to Flutter development, and this might be a naive question, but i was following the beginner tutorial on flutter dev site, and my listview is not showing. I have changed some class/function names,and put the code in different files, but am not sure what is being wrong here, This is supposed to be a list of infinite list of random words.
Here is the complete code:
//File name: main.dart
import 'package:english_words/english_words.dart';
import 'package:flutter/material.dart';
import 'package:flutter_app_as/StatefulWidgetStates.dart';
class StatefulRandomWordsWidget extends StatefulWidget {
#override
State<StatefulWidget> createState() {
return RandomWordsState();
}
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
var wordWidget = StatefulRandomWordsWidget();
return MaterialApp(
title: 'Useless Title',
home: Scaffold(
appBar: AppBar(title: Text('Welcome to Flutter')),
body: wordWidget));
}
}
void main() {
runApp(MyApp());
}
and
//File name: StatefulWidgetStates.dart
import 'package:english_words/english_words.dart';
import 'package:flutter/material.dart';
import 'package:flutter_app_as/main.dart';
class RandomWordsState extends State<StatefulRandomWordsWidget> {
final dataList = <WordPair>[];
#override
Widget build(BuildContext context) {
return getListView();
}
Widget getListView() {
ListView listViewWidget = ListView.builder(
itemCount: dataList.length,
padding: EdgeInsets.all(8.0),
itemBuilder: (context, pos) {
if (pos.isOdd) {
return Divider();
}
else {
final index = pos ~/ 2;
if (index >= dataList.length) {
List<WordPair> pairs=generateWordPairs().take(10);
dataList.addAll(pairs);
}
WordPair childData = dataList[index];
return ListTile(title: Text(childData.asCamelCase, style: TextStyle(fontSize: 12.0)));
}
});
return listViewWidget;
}
}
I also don't understand whats this final index = pos ~/ 2; logic about. The official docs say:
The expression i ~/ 2 divides i by 2 and returns an integer result. For example: 1, 2, 3, 4, 5 becomes 0, 1, 1, 2, 2. This calculates the actual number of word pairings in the ListView, minus the divider widgets.
But am guessing am using it wrong.
Remember that when you are working with StateFul Widgets, you need to tell the framework that some state(date) in that widget has changed and it needs to be rebuild. So when you are adding thing to te list, the state changes and it needs to be re-builded. You tell the framework to rebuild by calling the setState((){
}); method.
example:
List<WordPair> pairs = generateWordPairs().take(10);
dataList.addAll(pairs);
setState(() {});