Flutter Button Formatting and Passing Call back Function

We had already created a new widget for questions. Now, we’ll create a new widget for answers. 

Create a new file answer.dart besides main.dart and add the following code there.

//FileName: answer.dart
import 'package:flutter/material.dart';

class Answer extends StatelessWidget {
  final Function selectHandler;

  Answer(this.selectHandler);

  @override
  Widget build(BuildContext context) {
    return Container(
      width: double.infinity, ////double.infinity means occupy the whole screen (width in this case)
      margin: EdgeInsets.all(10), //apply margin of 10 pts to all 4 sides
      /*
      * We have provided 3 named arguments here to ElevatedButton()
      * 1. child: which is a Text() widget
      * 2. onPressed: which is a function we get via constructor
      * 3. style: where we change the color, padding and text style
       */
      child: ElevatedButton(
        child: Text('Answer1'),
        //onPressed takes a function
        onPressed: selectHandler,
        style: ElevatedButton.styleFrom(
          primary: Colors.blue, //the button's background color
          onPrimary: Colors.white, //the button's text color

          padding: EdgeInsets.symmetric(horizontal: 50, vertical: 20),
          textStyle: TextStyle(fontSize: 30, fontWeight: FontWeight.bold),
        ), //.styleFrom
      ), //ElevatedButton
    ); //Container
  }
}

Here is question.dart file previously created.

//FileName: question.dart
import 'package:flutter/material.dart';

class Question extends StatelessWidget {
  /*
  * final keywords tells dart that this value will never change after its
  * initialization here int he constructor
   */
  final String questionText;

  /* Lets have a constructor to initialize this widget class questionText
  *  Now the first positional argument passed to this constructor will be stored in
  *  questionText variable
   */
  Question(this.questionText);

  @override
  Widget build(BuildContext context) {
    return Container(
      width: double.infinity, //double.infinity means occupy the whole screen (width in this case)
      margin: EdgeInsets.all(10), //apply margin of 10 pts to all 4 sides
      child: Text(
        questionText,
        style: TextStyle(fontSize: 26),
        textAlign: TextAlign.center,
      ), //Text
    ); //Container()
  } //build
} //Question

In our main.dart file we’ll add the import for answer.dart and will replace ElevatedButton() code with this Answer() code and will add SizedBox() for spacing.

Now, our main.dart file’s code is simple and easy to understand.

//File Name: main.dart
import 'package:flutter/material.dart';

/* ./ means look in the main folder where main.dart resides and then the
*  name of the file which you wana import
 */

import './question.dart';
import './answer.dart';

/*
* The arrow function allows us to create a simplified function consisting of a single expression.
* We can omit the curly brackets and the return keyword
*/

void main() => runApp(MyApp());

class MyApp extends StatefulWidget {
  /*
   * createState() is a method that takes no arguments but returns a State object
   * which is connected to a StatefulWidget
   */
  @override
  State<StatefulWidget> createState() {
    return _MyAppState();
  } //createState()
} //StatefulWidget

/* A leading underscore makes the property private, here leading underscore will turn
 * this public class in to private class. Now MyAppState class can only be used in
 * main.dart file, in our case in MyApp class.
 */
class _MyAppState extends State<MyApp> {
  var _questionIndex = 0;

  void _answerQuestion() {
    setState(() {
      _questionIndex++;
    });
    print(_questionIndex);
  }

  @override
  Widget build(BuildContext context) {
    var questions = [
      'What\'s your favorite color?',
      'What\'s your favorite animal?'
    ];
    return MaterialApp(
      /*
      * A Scaffold Widget provides a framework which implements the basic material design visual
      * layout structure of the flutter app.
       */
      home: Scaffold(
        appBar: AppBar(
          title: Text('First Flutter App'),
        ),
        body: Column(
          children: <Widget>[
            Question(
              questions[_questionIndex],
            ),
            Answer(_answerQuestion),
            SizedBox(height: 16),
            Answer(_answerQuestion),
            SizedBox(height: 16),
            Answer(_answerQuestion),
          ],
        ),
      ),
    );
  } //build()
} //MyApp()
Output

This is a lot to digest but I have made things easy to understand by taking you along using step by step approach.

Happy Coding!

Flutter Widget Formatting

//FileName: question.dart
import 'package:flutter/material.dart';

class Question extends StatelessWidget {
  /*
  * final keywords tells dart that this value will never change after its
  * initialization here int he constructor
   */
  final String questionText;

  /* Lets have a constructor to initialize this widget class questionText
  *  Now the first positional argument passed to this constructor will be stored in
  *  questionText variable
   */
  Question(this.questionText);

  @override
  Widget build(BuildContext context) {
    return Container(
      width: double.infinity, //double.infinity means occupy the whole screen (width in this case)
      margin: EdgeInsets.all(10), //apply margin of 10 pts to all 4 sides
      child: Text(
        questionText,
        style: TextStyle(fontSize: 26),
        textAlign: TextAlign.center,
      ), //Text
    ); //Container()
  } //build
} //Question
Output – Formatted Flutter Widget

Happy Coding!

Flutter Private Properties

Unlike Java, Dart doesn’t have the keywords public, protected, and private. If an identifier starts with an underscore _, it’s private to its library. Libraries not only provide APIs, but are a unit of privacy: identifiers that start with an underscore _ are visible only inside the library.

Every Dart app is a library, even if it doesn’t use a library directive. The import and library directives can help you create a modular and shareable code base.

//File Name: main.dart
import 'package:flutter/material.dart';

/*
* The arrow function allows us to create a simplified function consisting of a single expression.
* We can omit the curly brackets and the return keyword
*/

void main() => runApp(MyApp());

class MyApp extends StatefulWidget {
  /*
   * createState() is a method that takes no arguments but returns a State object
   * which is connected to a StatefulWidget
   */
  @override
  State<StatefulWidget> createState() {
    return _MyAppState();
  } //createState()
} //StatefulWidget

/* A leading underscore makes the property private, here leading underscore will turn
 * this public class in to private class. Now MyAppState class can only be used in
 * main.dart file, in our case in MyApp class.
 */
class _MyAppState extends State<MyApp>{
  var _questionIndex = 0;

  void _answerQuestion() {
    setState( () {
      _questionIndex++;
    } );
    print(_questionIndex);
  }

  @override
  Widget build(BuildContext context) {
    var questions = [
      'What\'s your favorite color?',
      'What\'s your favorite animal?'
    ];
    return MaterialApp(
      /*
      * A Scaffold Widget provides a framework which implements the basic material design visual
      * layout structure of the flutter app.
       */
      home: Scaffold(
        appBar: AppBar(
          title: Text('First Flutter App'),
        ),
        body: Column(
          children: <Widget>[
            Text(questions[_questionIndex]),
            ElevatedButton(
              child: Text('Answer1'),
              //onPressed takes a function
              onPressed: _answerQuestion,
            ),
            ElevatedButton(
              child: Text('Answer2'),
              onPressed: () => print('Answer2 chosen!'),
            ),
            ElevatedButton(
              child: Text('Answer3'),
              onPressed: () {
                //...multiline function body
                print('Answer3 chosen');
              },
            ),
          ],
        ),
      ),
    );
  } //build()
} //MyApp()

Output

Output

Happy Coding!

Flutter StatefulWidget

State is data/information used by your App or widgets in our App. State can be things like username or in our case, index of the question we want to show.

App State can be Authenticated Users

Widget State can be Current User Input or which question is currently selected.

StatefulWidget has some internal state which is the core about this widget.

We’ll inherit/extend MyApp class from StatefulWidget instead of StatelessWidget and will override createState() method. Then we’ll create another class that will hold all the previous code.

class MyAppState extends State<MyApp>
and in answerQuestion() function we have now used setState() function that takes an anonymous function where we increment questionIndex variable. Here is the complete code snippet.

 

//File Name: main.dart
import 'package:flutter/material.dart';

/*
* The arrow function allows us to create a simplified function consisting of a single expression.
* We can omit the curly brackets and the return keyword
*/

void main() => runApp(MyApp());

class MyApp extends StatefulWidget {
  /*
   * createState() is a method that takes no arguments but returns a State object
   * which is connected to a StatefulWidget
   */
  @override
  State<StatefulWidget> createState() {
    return MyAppState();
  } //createState()
} //StatefulWidget

class MyAppState extends State<MyApp>{
  var questionIndex = 0;

  void answerQuestion() {
    setState( () {
      questionIndex++;
    } );
    print(questionIndex);
  }

  @override
  Widget build(BuildContext context) {
    var questions = [
      'What\'s your favorite color?',
      'What\'s your favorite animal?'
    ];
    return MaterialApp(
      /*
      * A Scaffold Widget provides a framework which implements the basic material design visual
      * layout structure of the flutter app.
       */
      home: Scaffold(
        appBar: AppBar(
          title: Text('First Flutter App'),
        ),
        body: Column(
          children: <Widget>[
            Text(questions[questionIndex]),
            ElevatedButton(
              child: Text('Answer1'),
              //onPressed takes a function
              onPressed: answerQuestion,
            ),
            ElevatedButton(
              child: Text('Answer2'),
              onPressed: () => print('Answer2 chosen!'),
            ),
            ElevatedButton(
              child: Text('Answer3'),
              onPressed: () {
                //...multiline function body
                print('Answer3 chosen');
              },
            ), //ElevatedButton()
          ], //<Widget>[]
        ), //Column()
      ), //Scaffold()
    ); //MaterialApp()
  } //build()
} //MyApp()

 

What Flutter actually does when setState() is executed?

setState() is a function that forces Flutter to re-render user interface, however not the entire user interface but instead part of it that requires updations, question text in our case. setState() updates the widget by calling its build method again.

StatefulWidget Output

Pressing the Answer1 button will now change the question, thus we are maintaining the state which in this case is the questionIndex of questions list.

Output Second Question

If we press Answer1 button second time, we’ll get an error and our app will crash because our questions list contains only two list items. We’ll solve this problem somewhere later. 

Output App Crashed

At the moment the point of this blog post was to break the ice to understand the concept of Flutter StatefulWidget.
If you have any question, please ask in the comments section.

Happy Coding!

Flutter Need for StatefulWidget

Continuing from our last blog post “Flutter/Dart Anonymous Function” , in this post we have added a list of questions in build() for now, with only two questions.

 var questions = [
      'What\'s your favorite color?',
      'What\'s your favorite animal?'
    ];

We have introduced a variable ‘questionIndex’ to keep track and change the question on the go. We increment this variable questionIndex in answerQuestion() function in MyApp class.

var questionIndex = 0;

  void answerQuestion() {
    questionIndex++;
    print(questionIndex);
    //print('Answer chosen!');
  }

Instead of display a static question in the Text() widget, we now display a question from questions list using questionIndex.

Text(questions[questionIndex]

Here is the full application code snippet.

//File Name: main.dart
import 'package:flutter/material.dart';

/*
* The arrow function allows us to create a simplified function consisting of a single expression.
* We can omit the curly brackets and the return keyword
*/

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  var questionIndex = 0;

  void answerQuestion() {
    questionIndex++;
    print(questionIndex);
    //print('Answer chosen!');
  }

  @override
  Widget build(BuildContext context) {
    var questions = [
      'What\'s your favorite color?',
      'What\'s your favorite animal?'
    ];
    return MaterialApp(
      /*
      * A Scaffold Widget provides a framework which implements the basic material design visual
      * layout structure of the flutter app.
       */
      home: Scaffold(
        appBar: AppBar(
          title: Text('First Flutter App'),
        ),
        body: Column(
          children: <Widget>[
            Text(questions[questionIndex]),
            ElevatedButton(
              child: Text('Answer1'),
              //onPressed takes a function
              onPressed: answerQuestion,
            ),
            ElevatedButton(
              child: Text('Answer2'),
              onPressed: () => print('Answer2 chosen!'),
            ),
            ElevatedButton(
              child: Text('Answer3'),
              onPressed: () {
                //...multiline function body
                print('Answer3 chosen');
              },
            ),
          ],
        ),
      ),
    );
  } //build()
} //MyApp()

Output

Output

What happens if we first Answer1 button? The question should change, right? but it doesn’t change because we are trying to change the internal state of the widget.

Remember, we can’t manage the state of a StatelessWidget, for that we need StatefulWidget which we’ll cover in next blog post.

Flutter/Dart Anonymous Function

Anonymous function is called anonymous because it has no name. Anonymous function is always a good idea if you never need to call it from anywhere else, it has no name and you can’t call it from anywhere else.

//File Name: main.dart
import 'package:flutter/material.dart';

/*
* The arrow function allows us to create a simplified function consisting of a single expression.
* We can omit the curly brackets and the return keyword
*/

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  void answerQuestion() {
    print('Answer chosen!');
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      /*
      * A Scaffold Widget provides a framework which implements the basic material design visual
      * layout structure of the flutter app.
       */
      home: Scaffold(
        appBar: AppBar(
          title: Text('First Flutter App'),
        ),
        body: Column(
          children: <Widget>[
            Text('The question'),
            ElevatedButton(
              child: Text('Answer1'),
              //onPressed takes a function
              onPressed: answerQuestion,
            ),
            ElevatedButton(
              child: Text('Answer2'),
              onPressed: () => print('Answer2 chosen!'),
            ),
            ElevatedButton(
              child: Text('Answer3'),
              onPressed: () {
                //...multiline function body
                print('Answer3 chosen');
              },
            ),
          ],
        ),
      ),
    );
  } //build()
} //MyApp()

Output

Output
Console Output

Happy Coding!

Flutter Column Layout Widget

Referring to the previous blog post First Flutter App where we used a single named argument ‘home’ for ‘MaterialApp()’ widget. ‘home’ takes Scaffold() widget as argument. We provided ‘appBar’ and ‘body’ named arguments to the Scaffold() widget.

  1. First argument ‘appBar’ takes ‘AppBar()’ as argument and this ‘AppBar’ takes ‘title’ named argument which at the end takes a ‘Text()’ widget.
  2. Second argument ‘body’ takes a Text() widget.

Here is a recap of that code snippet.

return MaterialApp(
     /*
      * A Scaffold Widget provides a framework which implements the basic material design visual 
      * layout structure of the flutter app.
       */
      home: Scaffold(
        appBar: AppBar(
          title: Text('First Flutter App'),
        ), //AppBar()
        body: Text('Welcome to Flutter'),
      ), //Scaffold()
    ); //MaterialApp()

body is the place that takes all-white screen besides appBar. We can not provide second widget to body as it takes only one widget as a parameter.

To solve this problem, we’ll use Layout widgets (Column(), Row(), etc). For the sake of understanding, we’ll use Column() widget in this blog post.

Column Class: A widget that displays its children in a vertical array.

//File Name: main.dart
import 'package:flutter/material.dart';

/*
* The arrow function allows us to create a simplified function consisting of a single expression.
* We can omit the curly brackets and the return keyword
*/

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      /*
      * A Scaffold Widget provides a framework which implements the basic material design visual
      * layout structure of the flutter app.
       */
      home: Scaffold(
        appBar: AppBar(
          title: Text('First Flutter App'),
        ),
        body: Column(
          children: <Widget>[
            Text('The question'),
            ElevatedButton(child: Text('Answer1'), onPressed: null,),
            ElevatedButton(child: Text('Answer2'), onPressed: null,),
            ElevatedButton(child: Text('Answer3'), onPressed: null,),
          ], //<Widget>[]
        ), //Column()
      ), //Scaffold()
    ); //MaterialApp()
  } //build()
} //MyApp()

Column() widget takes ‘children’ argument and we are passing a list of Widgets to that. First one is a Text() widget while rest of the three are ElevatedButton() widget.

ElevatedButton() widget takes two arguments.

  1. Text() widget shows the button text.
  2. onPressed takes a function argument but for now we are passing it null and because of null the button will be disabled to click/tap.

Output

Column() Widget output

The UI looks ugly but the point is to understand column widget. We’ll make the UI beautiful in next blog posts.

Happy coding!

Different Types of Flutter Widgets

Container Widget: There is also a very important widget that ships with Flutter, the Container() widget which kind of belongs in to both categories as you will learn once we use it because it by default is invisible but you can also give it some styling so that you can see it.

Visible & Invisible Flutter Widgets
Visible & Invisible Flutter Widgets

Container Widget: There is also a very important widget that ships with Flutter, the Container() widget which kind of belongs in to both categories as you will learn once we use it because it by default is invisible but you can also give it some styling so that you can see it.

First Flutter App

Note: This blog post is the continuation of the previous blog – First Flutter Widget

In the previous blog post, we just created a widget that shows a simple ‘Hello World!’ text which was left aligned and there was no App Bar and title in that widget. That was just to break the ice.

Remember: Everything in flutter is a Widget.

//File Name: main.dart
import 'package:flutter/material.dart';

/* The arrow function allows us to create a simplified function consisting of a single expression. 
 * We can omit the curly brackets and the return keyword
 */

void main() => runApp(MyApp());

class MyApp extends StatelessWidget{
  
  @override
  Widget build(BuildContext context){
    
    return MaterialApp(
     /*
      * A Scaffold Widget provides a framework which implements the basic material design visual 
      * layout structure of the flutter app.
       */
      home: Scaffold(
        appBar: AppBar(
          title: Text('First Flutter App'),
        ), //AppBar()
        body: Text('Welcome to Flutter'),
      ), //Scaffold()
    ); //MaterialApp()
  } //build()
} //MyApp()

 

MaterialApp() Widget takes a lot of named arguments. Here, we have used only ‘home’ named argument.

MaterialApp() Widget Named Arguments

Scaffold() Widget also takes a lot of named arguments. Here, we have used only appBar and body named arguments.

Named Arguments for Scaffold() Widget
  1. appBar also takes a lot of arguments. Here we have used only title argument which takes a Text() Widget.
  2. body also takes a Text() Widget.

Output: We have a nice UI based output.

First Flutter App – Output

This simple app has used many widgets but remember everything in Flutter is a Widget. Our whole app is a widget which contains many nested widgets.

If you have any question regarding above code please ask in the comments section.

Happy Coding!

Dart Named Arguments

There are two types of arguments for a constructor in dart.

  1. Positional arguments – These are commonly used. For Positional arguments you have to remember which argument goes in to which place.
  2. Named arguments – This is a new concept if you belong to C++, Java or PHP. For Named Arguments you don’t need to remember the place/position of the argument. Named Arguments are optional but can be made mandatory using @required
class Person{

  String name="";
  int age=0;
  
  Person({String inputName="", int inputAge=0}){

    this.name = inputName;
    this.age = inputAge;
  }//Person()
  
  Person.veryOld(this.name){
    age = 60;
  }//Person.veryOld()
}//Person


void main() {

  var p1 = Person(inputName: "Rizwan", inputAge: 34);
  var p2 = Person(inputName: "Ali", inputAge: 32);
  var p3 = Person.veryOld("Usama");

  print(p1.name); //Rizwan
  print(p1.age);  //34

  print(p2.name); //Ali
  print(p2.age);  //32

  print(p3.name); //Usama
  print(p3.age);  //60
  
}

Dart Constructor

class Person {

  String name="";
  int age=0;
  
  Person(String inputName, int inputAge){
    this.name = inputName;
    this.age = inputAge;
  }//Person()
}//Person

void main() {

  var p1 = Person("Rizwan", 34);
  var p2 = Person("Ali", 32);
  
  print(p1.name); //Rizwan
  print(p1.age);  //34
  
  print(p2.name); //Ali
  print(p2.age);  //32
}

In this constructor we are using positional arguments i.e, inputName and inputAge instead of named arguments.

First Flutter Widget

What is Flutter?

Flutter is Google’s UI toolkit for building beautiful, natively compiled applications for mobile, web, desktop, and embedded devices from a single codebase.

I assume that you have successfully installed flutter either with Android Studio IDE or VS Code and have successfully configured an emulator.

If you want to install flutter, kindly follow this official documentation.

https://flutter.dev/docs/get-started/install

//File Name: main.dart
//Flutter first Hello World! Widget
import 'package:flutter/material.dart';

void main() {

   runApp(MyApp());
}

class MyApp extends StatelessWidget {

   @override
   Widget build(BuildContext context){

      return MaterialApp(home: Text('Hello World!');

   }//build
}//MyApp
  1. Import Flutter package
  2. declare main function and run app i.e, runApp(MyApp)
  3. MyApp is a custom class that inherits from Stateless Widget(Later we’ll also look into StatfullWidget)
  4. MyApp class overrides build() method.
  5. build method returns a Widget and takes Build context as a parameter.
  6. MaterialApp() is a special widget that we should return. It does some base setup to turn combinational widgets into real app. The MaterialApp() takes a lot of named arguments, home is one of the named arguments where we use a text widget Text(‘Hello World!’).

Output: The output involves no UI and is a simple Hello World!

First Flutter Plugin – Output

I hope the logic and code behind the first flutter widget make sense.

Happy coding!