Setup the Project
cmd + shift + p
Create a new folder on your desktop called DevPortfolio
Select the newly created folder to create your project in
Use lowercase to enter a project name.
Finally, you should see your project being created.
Delete the iOS and Android folders
The project should have been created successfully. If you see that creation process hangs because its still downloading, cancel it. Open the terminal and in the project directory type:
flutter pub get
Open up lib/main.dart.
Delete everything below class MyApp.
type stl, then tab. Let’s create a Stateless Widget called DesktopView.
should give you code generation like so:
1 2 3 4 5 6 7 8 |
class DesktopView extends StatelessWidget { @override Widget build(BuildContext context) { return Container( ); } } |
replace Container with Scaffold, which is a Material Design Layout.
Let’s instantiate our DesktopView class for property home
1 2 3 4 5 6 7 8 9 10 11 12 |
class MyApp extends StatelessWidget { // This widget is the root of your application. @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', ... ... home: DesktopView(), ); } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 |
class DesktopView extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( body: Column( children: [ Container(), Container(), ], ), ); } } |
Media Query returns us the size of the current media. i.e the window containing our app.
Put this at the beginning of the over-ride build function.
1 2 |
final height = MediaQuery.of(context).size.height; print(height); |
Run > Start Debugging
Make sure you use Chrome as your browser. Wait a while. A browser will pop up. Try to resize it. You will see that our output will be updated with the new window size.
build method will only refresh when size is changed.
Make it Scrollable
Let’s add two containers with different colors. But since our body Column is not scrollable, our 2nd container will overflow. In order to solve this, we simply our Column in SingleChildScrollView.
So now, our body is the SingleChildScrollView, which has a child of Column. Within the column, we have two containers.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
class DesktopView extends StatelessWidget { @override Widget build(BuildContext context) { final height = MediaQuery.of(context).size.height; final width = MediaQuery.of(context).size.width; print(height); return Scaffold( body: SingleChildScrollView( child: Column( children: [ Container(height: height, width: width, color: Colors.red), Container(height: height, width: width, color: Colors.blue), ], ), ), ); } } |
Now, when you save, the project will hot save, and we’re able to see the two containers and scroll up and down.
Under lib, create folder called desktop. Then create desktop_view.dart file.
When you copy and pasted the desktop view code into our desktop_view.dart, we’ll see a bunch of errors. This is because we need to import material.dart from the flutter package.
go ahead and do: cmd + .
Now the errors will be gone.
Do the same in main.dart and import our desktop_view.dart file. So that DesktopView() can be used.
Layout of the Site
Let’s layout the text and logo for the site.
So for the first Container on top, let’s give it a static height and width. That way we control it to be smaller than the bottom (blue) region.
Then we put a Row, and specify its children to be a Column and a logo.
In the column, we have children of texts. And in order to align them, we use axis alignments.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
import 'package:flutter/material.dart'; const text = "Hi, I'm a Web Dev"; class DesktopView extends StatelessWidget { @override Widget build(BuildContext context) { final height = MediaQuery.of(context).size.height; final width = MediaQuery.of(context).size.width; print(height); return Scaffold( body: SingleChildScrollView( child: Column( children: [ Container( height: 640, width: 800, child: Row( children: [ Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(text), Text('Developer < / >'), Text('I have two years of Web and Mobile experience. Please hire me for a cheap rate!'), TextButton(onPressed: () {}, child: Text('Contact Me')), ], ), FlutterLogo(size: 300) ], ), ), Container(height: height, width: width, color: Colors.blue), ], ), ), ); } } |
Google Fonts
Let’s download google_fonts using our pubspec.yaml file.
Open it up and underneath dependencies, let’s download google_fonts 2.0.0
1 2 3 4 5 6 7 8 |
dependencies: css_colors: ^1.1.0 google_fonts: ^2.0.0 flutter: sdk: flutter ... ... ... |
Save and in your project directory: flutter pub get
Your google fonts are now available as dependencies, instead of resources.
In our text, let’s use the following to apply montserrat font style to our text:
1 |
Text(text, style: GoogleFonts.montserrat()), |
then put some spaces between our texts:
1 2 3 4 5 6 7 8 |
children: [ Text(text, style: GoogleFonts.montserrat()), SizedBox( height: 26,), Text('Developer < / >'), SizedBox( height: 18 ), Text('I have two years of Web and Mobile experience. Please hire me for a cheap rate!'), TextButton(onPressed: () {}, child: Text('Contact Me')), ], |
Create rounded red button
There is a named property in TextButton called style. We assign a ButtonStyle instance to it. Within the ButtonStyle class, there is a shape property.
We call MaterialSTateProperty.all because its just a convenience method for creating a [MaterialStateProperty] that resolves to a single value for all states. For every state of this button, we use this shape, which is 18.0 border Radius, and side of color Red.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 |
import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; const text = "Hi, I'm a Web Dev"; class DesktopView extends StatelessWidget { @override Widget build(BuildContext context) { final height = MediaQuery.of(context).size.height; final width = MediaQuery.of(context).size.width; return Scaffold( body: SingleChildScrollView( child: Column( children: [ Container( height: 640, width: 800, child: Row( children: [ Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(text, style: GoogleFonts.montserrat()), SizedBox( height: 26, ), Text('Developer < / >'), SizedBox( height: 18, ), Text( 'I have two years of Web and Mobile experience. Please hire me for a cheap rate!'), SizedBox( height: 18, ), TextButton( style: ButtonStyle( shape: MaterialStateProperty.all< RoundedRectangleBorder>( RoundedRectangleBorder( borderRadius: BorderRadius.circular(18.0), side: BorderSide(color: Colors.red))), backgroundColor: MaterialStateProperty.all(Colors.redAccent), foregroundColor: MaterialStateProperty.all(Colors.black)), onPressed: () {}, child: Padding( padding: const EdgeInsets.symmetric( horizontal: 12.0, vertical: 18.0), child: Text( 'Contact Me', style: TextStyle(fontSize: 24), ))), ], ), FlutterLogo(size: 300) ], ), ), Container(height: height, width: width, color: Colors.blue), ], ), ), ); } } |
Refactor our code
So we have two Containers. The top Container contains our text and logo that introduces this site. We want to extract this code and create a class out of it. Let’s make it into a header. Highlight the Container keyword, then cmd + period. Select extract widget.
Type in the name of this extraction, say HeaderView.
Then we see that class HeaderView is created and that our Container has been replaced by an instantiation of that HeaderView class.
Now let’s replace our DesktopView name with PortfolioView. We use rename symbol. That way, any usage of this symbol will also be changed.
Finally, let’s cut the PortfolioView code and place it into main.dart. We do this because it is the main view that we will see. The SingleChildScrollView will house the HeaderView, BodyView, sidebars and what not. We will continuously create Containers and then refactor them into different sections of the site.
main.dart
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
import 'package:dev_portolio/desktop/desktop_view.dart'; import 'package:flutter/material.dart'; class PortfolioView extends StatelessWidget { @override Widget build(BuildContext context) { final height = MediaQuery.of(context).size.height; final width = MediaQuery.of(context).size.width; return Scaffold( body: SingleChildScrollView( child: Column( children: [ HeaderView(), Container(height: height, width: width, color: Colors.blue), ], ), ), ); } } void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { // This widget is the root of your application. @override Widget build(BuildContext context) { return MaterialApp( title: 'Rick Rolled', theme: ThemeData( primarySwatch: Colors.blue, ), home: PortfolioView(), ); } } |
Now let’s rename the folder to header, and the file that holds the header code to header_view.dart