├── lib ├── screens │ ├── home_screen_viewmodel.dart │ └── home_screen.dart ├── utils │ └── di.dart ├── services │ └── navigation_service.dart ├── main.dart ├── router │ └── router.dart └── responsive │ └── responsive_layout.dart ├── pubspec.yaml └── README.md /lib/screens/home_screen_viewmodel.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/cupertino.dart'; 2 | 3 | class HomeScreenViewModel extends ChangeNotifier {} 4 | -------------------------------------------------------------------------------- /lib/utils/di.dart: -------------------------------------------------------------------------------- 1 | import 'package:get_it/get_it.dart'; 2 | import 'package:starter_app/services/navigation_service.dart'; 3 | 4 | GetIt locator = GetIt.instance; 5 | 6 | void setupDI() { 7 | locator.registerLazySingleton(() => NavigationService()); 8 | } 9 | -------------------------------------------------------------------------------- /lib/services/navigation_service.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/cupertino.dart'; 2 | 3 | class NavigationService { 4 | final GlobalKey navigatorKey = GlobalKey(); 5 | 6 | Future navigateTo(String routeName) { 7 | return navigatorKey.currentState.pushNamed(routeName); 8 | } 9 | 10 | void goBack() { 11 | return navigatorKey.currentState.pop(); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: starter_app 2 | description: A new Flutter application. 3 | publish_to: 'none' 4 | version: 1.0.0+1 5 | 6 | environment: 7 | sdk: ">=2.7.0 <3.0.0" 8 | 9 | dependencies: 10 | flutter: 11 | sdk: flutter 12 | cupertino_icons: ^0.1.3 13 | stacked: ^1.7.1+1 14 | get_it: 15 | 16 | dev_dependencies: 17 | flutter_test: 18 | sdk: flutter 19 | 20 | flutter: 21 | uses-material-design: true -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # FlutterStarterProject 2 | Creating a starting Flutter project which has Routing and Responsive layout boiler code already setted up so that the Flutter Devs can get a head-start on building the core components of their awesome Flutter apps and don't waste their time in setting up the boiler plate code for Routing, Responsiveness of their flutter apps. 3 | 4 | I have added a couple of dependencies like 5 | 6 | 1. Stacked - For quick and easy state mangement. 7 | 2. GetIt - For clean and easy dependency management. 8 | -------------------------------------------------------------------------------- /lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:starter_app/router/router.dart'; 3 | import 'package:starter_app/services/navigation_service.dart'; 4 | import 'package:starter_app/utils/di.dart'; 5 | 6 | void main() { 7 | setupDI(); 8 | runApp(MyApp()); 9 | } 10 | 11 | class MyApp extends StatelessWidget { 12 | @override 13 | Widget build(BuildContext context) { 14 | return MaterialApp( 15 | title: 'Beginner App', 16 | theme: ThemeData( 17 | primarySwatch: Colors.blue, 18 | visualDensity: VisualDensity.adaptivePlatformDensity, 19 | ), 20 | builder: (context, child) => child, 21 | navigatorKey: locator().navigatorKey, 22 | onGenerateRoute: generateRoute, 23 | initialRoute: HomeRoute, 24 | ); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /lib/screens/home_screen.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/cupertino.dart'; 2 | import 'package:flutter/material.dart'; 3 | import 'package:stacked/stacked.dart'; 4 | import 'package:starter_app/responsive/responsive_layout.dart'; 5 | 6 | import 'home_screen_viewmodel.dart'; 7 | 8 | /// To open a new screen use: 9 | /// locator.get().navigateTo(""); 10 | 11 | class HomeScreen extends StatelessWidget { 12 | @override 13 | Widget build(BuildContext context) { 14 | return ViewModelBuilder.reactive( 15 | viewModelBuilder: () => HomeScreenViewModel(), 16 | builder: (buildContext, model, child) { 17 | return ScreenTypeLayout( 18 | mobile: OrientationLayout( 19 | portrait: HomeMobileScreenWidget(), 20 | landscape: HomeMobileScreenWidget(), 21 | ), 22 | tablet: OrientationLayout( 23 | portrait: HomeMobileScreenWidget(), 24 | landscape: HomeLargeScreenWidget(), 25 | ), 26 | desktop: OrientationLayout( 27 | landscape: HomeLargeScreenWidget(), 28 | portrait: HomeLargeScreenWidget(), 29 | ), 30 | ); 31 | }, 32 | ); 33 | } 34 | } 35 | 36 | class HomeMobileScreenWidget extends StatelessWidget { 37 | @override 38 | Widget build(BuildContext context) { 39 | return Scaffold(); 40 | } 41 | } 42 | 43 | class HomeLargeScreenWidget extends StatelessWidget { 44 | @override 45 | Widget build(BuildContext context) { 46 | return Scaffold(); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /lib/router/router.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/widgets.dart'; 2 | import 'package:starter_app/screens/home_screen.dart'; 3 | 4 | const String HomeRoute = '/home'; 5 | const String ContactRoute = '/contact'; 6 | const String AboutRoute = '/about'; 7 | const String SubmitRoute = '/submit'; 8 | 9 | Route generateRoute(RouteSettings settings) { 10 | switch (settings.name) { 11 | case HomeRoute: 12 | return _getPageRoute(HomeScreen(), settings); 13 | default: 14 | return _getPageRoute(HomeScreen(), settings); 15 | } 16 | } 17 | 18 | Route _getPageRoute(Widget child, RouteSettings settings) { 19 | /// You can use Material Page Route or your Custom Route here 20 | return _FadeRoute(child: child, routeName: settings.name); 21 | } 22 | 23 | class _FadeRoute extends PageRouteBuilder { 24 | final Widget child; 25 | final String routeName; 26 | 27 | _FadeRoute({this.child, this.routeName}) 28 | : super( 29 | settings: RouteSettings(name: routeName), 30 | pageBuilder: ( 31 | BuildContext context, 32 | Animation animation, 33 | Animation secondaryAnimation, 34 | ) => 35 | child, 36 | transitionsBuilder: ( 37 | BuildContext context, 38 | Animation animation, 39 | Animation secondaryAnimation, 40 | Widget child, 41 | ) => 42 | FadeTransition( 43 | opacity: animation, 44 | child: child, 45 | ), 46 | ); 47 | } 48 | -------------------------------------------------------------------------------- /lib/responsive/responsive_layout.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/cupertino.dart'; 2 | import 'package:flutter/material.dart'; 3 | 4 | /// Enums for different screen sizes 5 | enum DeviceScreenType { Mobile, Tablet, Desktop } 6 | 7 | /// GetDeviceType Function 8 | /// This is where we define our screen widths for different layouts 9 | DeviceScreenType getDeviceType(MediaQueryData mediaQueryData) { 10 | var orientation = mediaQueryData.orientation; 11 | 12 | double deviceWidth = 0; 13 | 14 | if (orientation == Orientation.landscape) { 15 | deviceWidth = mediaQueryData.size.height; 16 | } else { 17 | deviceWidth = mediaQueryData.size.width; 18 | } 19 | 20 | if (deviceWidth > 950) { 21 | return DeviceScreenType.Desktop; 22 | } 23 | 24 | if (deviceWidth > 600) { 25 | return DeviceScreenType.Tablet; 26 | } 27 | 28 | return DeviceScreenType.Mobile; 29 | } 30 | 31 | /// Sizing Information 32 | class SizingInformation { 33 | final Orientation orientation; 34 | final DeviceScreenType deviceScreenType; 35 | final Size screenSize; 36 | final localWidgetSize; 37 | 38 | SizingInformation( 39 | {this.orientation, 40 | this.deviceScreenType, 41 | this.screenSize, 42 | this.localWidgetSize}); 43 | 44 | @override 45 | String toString() { 46 | return 'SizingInformation{orientation: $orientation, deviceScreenType: $deviceScreenType, screenSize: $screenSize, localWidgetsize: $localWidgetSize}'; 47 | } 48 | } 49 | 50 | class OrientationLayout extends StatelessWidget { 51 | final Widget landscape; 52 | final Widget portrait; 53 | 54 | OrientationLayout({Key key, this.landscape, this.portrait}) : super(key: key); 55 | 56 | @override 57 | Widget build(BuildContext context) { 58 | var orientation = MediaQuery.of(context).orientation; 59 | if (orientation == Orientation.landscape) { 60 | return landscape ?? portrait; 61 | } 62 | 63 | return portrait; 64 | } 65 | } 66 | 67 | class ResponsiveBuilder extends StatelessWidget { 68 | final Widget Function( 69 | BuildContext buildContext, SizingInformation sizingInformation) builder; 70 | 71 | const ResponsiveBuilder({Key key, this.builder}) : super(key: key); 72 | 73 | @override 74 | Widget build(BuildContext context) { 75 | var mediaQuery = MediaQuery.of(context); 76 | var sizingInformation = SizingInformation( 77 | orientation: mediaQuery.orientation, 78 | deviceScreenType: getDeviceType(mediaQuery), 79 | ); 80 | return builder(context, sizingInformation); 81 | } 82 | } 83 | 84 | class ScreenTypeLayout extends StatelessWidget { 85 | final Widget mobile; 86 | final Widget tablet; 87 | final Widget desktop; 88 | 89 | const ScreenTypeLayout({Key key, this.mobile, this.tablet, this.desktop}) 90 | : super(key: key); 91 | 92 | @override 93 | Widget build(BuildContext context) { 94 | return ResponsiveBuilder( 95 | builder: (context, sizingInformation) { 96 | if (sizingInformation.deviceScreenType == DeviceScreenType.Tablet) { 97 | if (tablet != null) { 98 | return tablet; 99 | } 100 | } 101 | 102 | if (sizingInformation.deviceScreenType == DeviceScreenType.Desktop) { 103 | if (desktop != null) { 104 | return desktop; 105 | } 106 | } 107 | return mobile; 108 | }, 109 | ); 110 | } 111 | } 112 | --------------------------------------------------------------------------------