Skip to content

Commit

Permalink
Added Widgets for Clean and Clear Responsive Design
Browse files Browse the repository at this point in the history
  -  Added Responsive Builder
  -  Added Orientation Layout
  -  Added Base Widget with Abstract class  for passing data models across different views

Currently what is rendered is just an example of creatinga responsive design for a tablet and mobile device.
  • Loading branch information
Tajcore committed Jul 28, 2020
1 parent 50d618f commit 7365f3b
Show file tree
Hide file tree
Showing 22 changed files with 608 additions and 108 deletions.
117 changes: 11 additions & 106 deletions lib/main.dart
Original file line number Diff line number Diff line change
@@ -1,117 +1,22 @@
import 'package:device_preview/device_preview.dart';
import 'package:flutter/material.dart';

void main() {
runApp(MyApp());
}
import 'package:fst_app_flutter/screens/homescreen/home_view.dart';

class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
// This is the theme of your application.
//
// Try running your application with "flutter run". You'll see the
// application has a blue toolbar. Then, without quitting the app, try
// changing the primarySwatch below to Colors.green and then invoke
// "hot reload" (press "r" in the console where you ran "flutter run",
// or simply save your changes to "hot reload" in a Flutter IDE).
// Notice that the counter didn't reset back to zero; the application
// is not restarted.
primarySwatch: Colors.blue,
// This makes the visual density adapt to the platform that you run
// the app on. For desktop platforms, the controls will be smaller and
// closer together (more dense) than on mobile platforms.
visualDensity: VisualDensity.adaptivePlatformDensity,
void main() => runApp(
DevicePreview(
child: FSTApp(),
),
home: MyHomePage(title: 'FST App'),
);
}
}

class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);

// This widget is the home page of your application. It is stateful, meaning
// that it has a State object (defined below) that contains fields that affect
// how it looks.

// This class is the configuration for the state. It holds the values (in this
// case the title) provided by the parent (in this case the App widget) and
// used by the build method of the State. Fields in a Widget subclass are
// always marked "final".

final String title;

@override
_MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;

void _incrementCounter() {
setState(() {
// This call to setState tells the Flutter framework that something has
// changed in this State, which causes it to rerun the build method below
// so that the display can reflect the updated values. If we changed
// _counter without calling setState(), then the build method would not be
// called again, and so nothing would appear to happen.
_counter++;
});
}

class FSTApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
// This method is rerun every time setState is called, for instance as done
// by the _incrementCounter method above.
//
// The Flutter framework has been optimized to make rerunning build methods
// fast, so that you can just rebuild anything that needs updating rather
// than having to individually change instances of widgets.
return Scaffold(
appBar: AppBar(
// Here we take the value from the MyHomePage object that was created by
// the App.build method, and use it to set our appbar title.
title: Text(widget.title),
),
body: Center(
// Center is a layout widget. It takes a single child and positions it
// in the middle of the parent.
child: Column(
// Column is also a layout widget. It takes a list of children and
// arranges them vertically. By default, it sizes itself to fit its
// children horizontally, and tries to be as tall as its parent.
//
// Invoke "debug painting" (press "p" in the console, choose the
// "Toggle Debug Paint" action from the Flutter Inspector in Android
// Studio, or the "Toggle Debug Paint" command in Visual Studio Code)
// to see the wireframe for each widget.
//
// Column has various properties to control how it sizes itself and
// how it positions its children. Here we use mainAxisAlignment to
// center the children vertically; the main axis here is the vertical
// axis because Columns are vertical (the cross axis would be
// horizontal).
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headline4,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
), // This trailing comma makes auto-formatting nicer for build methods.
return MaterialApp(
builder: DevicePreview.appBuilder,
title: 'Flutter Demo',
home: HomeView(),
);
}
}
11 changes: 11 additions & 0 deletions lib/models/drawer_item_data.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import 'package:flutter/material.dart';

class DrawerItemData {
final String title;
final IconData iconData;

DrawerItemData({
this.title,
this.iconData,
});
}
1 change: 1 addition & 0 deletions lib/models/enums/device_screen_type.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
enum DeviceScreenType { Mobile, Tablet, Desktop }
17 changes: 17 additions & 0 deletions lib/models/home_view_model.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import 'package:flutter/material.dart';

class HomeViewModel extends ChangeNotifier {
String title = 'default';

void initialise() {
title = 'initialised';
notifyListeners();
}

int counter = 0;
void updateTitle() {
counter++;
title = '$counter';
notifyListeners();
}
}
24 changes: 24 additions & 0 deletions lib/screens/homescreen/home_view.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import 'package:flutter/material.dart';
import 'package:fst_app_flutter/models/home_view_model.dart';
import 'package:fst_app_flutter/screens/homescreen/home_view_mobile.dart';
import 'package:fst_app_flutter/screens/homescreen/home_view_tablet.dart';
import 'package:fst_app_flutter/widgets/base_widget.dart';
import 'package:fst_app_flutter/widgets/orientation_layout.dart';
import 'package:fst_app_flutter/widgets/screen_type_layout.dart';

class HomeView extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BaseWidget<HomeViewModel>(
viewModel: HomeViewModel(),
onModelReady: (model) => model.initialise(),
builder: (context) => ScreenTypeLayout(
mobile: OrientationLayout(
portrait: (context) => HomeMobilePortrait(),
landscape: (context) => HomeMobileLandscape(),
),
tablet: HomeTablet(),
),
);
}
}
56 changes: 56 additions & 0 deletions lib/screens/homescreen/home_view_mobile.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import 'package:flutter/material.dart';
import 'package:fst_app_flutter/models/home_view_model.dart';
import 'package:fst_app_flutter/widgets/app_drawer/app_drawer.dart';
import 'package:fst_app_flutter/widgets/base_data_model_widget.dart';

class HomeMobilePortrait extends BaseModelWidget<HomeViewModel> {
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();

@override
Widget build(BuildContext context, HomeViewModel model) {
return Scaffold(
key: _scaffoldKey,
drawer: AppDrawer(),
floatingActionButton: FloatingActionButton(
onPressed: () {
model.updateTitle();
},
),
body: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Padding(
padding: const EdgeInsets.all(16),
child: IconButton(
icon: Icon(Icons.menu, size: 30),
onPressed: () {
_scaffoldKey?.currentState?.openDrawer();
},
),
),
Expanded(
child: Center(
child: Text(model.title),
),
)
],
),
);
}
}

class HomeMobileLandscape extends BaseModelWidget<HomeViewModel> {
@override
Widget build(BuildContext context, HomeViewModel model) {
return Scaffold(
floatingActionButton: FloatingActionButton(
onPressed: () {
model.updateTitle();
},
),
body: Row(
children: <Widget>[AppDrawer()],
),
);
}
}
31 changes: 31 additions & 0 deletions lib/screens/homescreen/home_view_tablet.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import 'package:flutter/material.dart';
import 'package:fst_app_flutter/models/home_view_model.dart';
import 'package:fst_app_flutter/widgets/app_drawer/app_drawer.dart';
import 'package:fst_app_flutter/widgets/base_data_model_widget.dart';

class HomeTablet extends BaseModelWidget<HomeViewModel> {
@override
Widget build(BuildContext context, HomeViewModel model) {
var children = [
Expanded(
child: Container(),
),
AppDrawer()
];
var orientation = MediaQuery.of(context).orientation;
return Scaffold(
floatingActionButton: FloatingActionButton(
onPressed: () {
model.updateTitle();
},
),
body: orientation == Orientation.portrait
? Column(
children: children,
)
: Row(
children: children.reversed.toList(),
),
);
}
}
36 changes: 36 additions & 0 deletions lib/utils/sizinginformation.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import 'package:flutter/widgets.dart';
import 'package:fst_app_flutter/models/enums/device_screen_type.dart';

class SizingInformation {
final Orientation orientation;
final DeviceScreenType deviceType;
final Size screenSize;
final Size localWidgetSize;
final DeviceScreenType deviceScreenType;
SizingInformation({
this.orientation,
this.deviceType,
this.screenSize,
this.localWidgetSize,
this.deviceScreenType,
});

@override
String toString() {
return 'Orientation:$orientation DeviceType:$deviceType ScreenSize:$screenSize LocalWidgetSize:$localWidgetSize';
}
}

DeviceScreenType getDeviceType(MediaQueryData mediaQuery) {
double deviceWidth = mediaQuery.size.shortestSide;

if (deviceWidth > 950) {
return DeviceScreenType.Desktop;
}

if (deviceWidth > 600) {
return DeviceScreenType.Tablet;
}

return DeviceScreenType.Mobile;
}
41 changes: 41 additions & 0 deletions lib/widgets/app_drawer/app_drawer.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import 'package:flutter/material.dart';
import 'package:fst_app_flutter/widgets/app_drawer/app_drawer_mobile.dart';
import 'package:fst_app_flutter/widgets/app_drawer/app_drawer_tablet.dart';
import 'package:fst_app_flutter/widgets/drawer_option/drawer_option.dart';
import 'package:fst_app_flutter/widgets/orientation_layout.dart';
import 'package:fst_app_flutter/widgets/screen_type_layout.dart';

class AppDrawer extends StatelessWidget {
const AppDrawer({Key key}) : super(key: key);
static List<Widget> getDrawerOptions() {
return [
DrawerOption(
title: 'Images',
iconData: Icons.image,
),
DrawerOption(
title: 'Reports',
iconData: Icons.photo_filter,
),
DrawerOption(
title: 'Incidents',
iconData: Icons.message,
),
DrawerOption(
title: 'Settings',
iconData: Icons.settings,
),
];
}

@override
Widget build(BuildContext context) {
return ScreenTypeLayout(
mobile: const AppDrawerMobileLayout(),
tablet: OrientationLayout(
portrait: (context) => AppDrawerTabletPortrait(),
landscape: (context) => AppDrawerTabletLandscape(),
),
);
}
}
26 changes: 26 additions & 0 deletions lib/widgets/app_drawer/app_drawer_mobile.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import 'package:flutter/material.dart';
import 'package:fst_app_flutter/widgets/app_drawer/app_drawer.dart';

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

@override
Widget build(BuildContext context) {
return OrientationBuilder(
builder: (context, orientation) => Container(
width: orientation == Orientation.portrait ? 250 : 100,
decoration: BoxDecoration(
color: Colors.white,
boxShadow: [
BoxShadow(
blurRadius: 16,
color: Colors.black12,
)
],
),
child: Column(
children: AppDrawer.getDrawerOptions(),
)),
);
}
}
Loading

0 comments on commit 7365f3b

Please sign in to comment.