4(b) . Flutter for Android Developer — Basic Widget (Building block)

Nitish Prasad
11 min readMay 27, 2019

--

In the last article, we have covered

  1. Text
  2. Padding
  3. Container
  4. Center
  5. TextField
  6. Image
  7. Icon
  8. Card
  9. Radio
  10. Opacity

Now , it’s time to explore rest of them.

source : Tenor.com

11. Column

In most of our previous example , we just use one widget at a time. This is kind of OK for demo purpose, but in any real app , we are definitely going to have more than one widget. For this purpose Flutter provide several widgets and column is one of them.

Column accepts list of widget which are aligned vertically. We can think of column as vertical LinearLayout. For column , main axis is vertical and cross section is horizontal. We can optionally specify size and child position (gravity) for these axis.

Axis of Column

Let’s code.

Widget getBody() {
return Column(


mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.max,

// if it is VerticalDirection.up then children will be shown in upword
// direction, i.e, first child at bottom next above it and so on
verticalDirection: VerticalDirection.down,

crossAxisAlignment: CrossAxisAlignment.start,

// note that it accept children not child and a list([...])
// of type widget
children: <Widget>[

Text("Hello world",
style: TextStyle(fontSize: 30.0,
fontWeight: FontWeight.bold),),

Card(
margin: const EdgeInsets.only(top: 20.0),
elevation: 10.0,
shape: RoundedRectangleBorder(),
child: Icon(Icons.person,size: 50.0,),

),

Padding(padding: const EdgeInsets.only(top: 50),),


TextField(decoration: InputDecoration(

icon: Icon(Icons.search),
suffixIcon: Icon(Icons.mic),

border: OutlineInputBorder(),
labelText: "Enter some text here",
contentPadding: const EdgeInsets.all(5.0),
),)



],
);
}

Points to note:

  1. It accepts children : list of widget
  2. It contain a card , which contain another child. Remember , i always say , in flutter everything is widget. So, you can possibly have anything as child as long as it remain widget.

That means i can also have column as a child of column.

Does it make any sense. If you think give it a try.

Output:

Other Properties:

mainAxisAligment : It specify the vertical alignment in the column. There are serveral possible values of it.

mainAxisAligment : center

crossSectionAligment : start

mainAxisSize : max

verticalDirection : down

verticalDirection : up

mainAxisAlignment : start

mainAxisAligment : start

crossSectionAligment : center

mainAxisAligment : end

crossSectionAligment : center

mainAxisAligment: spaceAround

// space around means space is evenly distributed between child and also to start and end. You see different spacing because of padding

mainAxisAligment: spaceAround

// it means avaiable space is evenly distributed but not to start and end. Uneven space is due to padding.( see code)

crossSectionAligment : stretch

// it means all the child are stretched from one point to another.

There is a interesting fact.

Textview always wrap to it’s content.Card first consult with its parent for any layout constraint, in this case parent instruct t to match parent. Textfield always match parent.

12. Row

This widget is same as column widget with only difference in its children alignment. Row lay out it’s children in horizontal direction. So, it’s mainAxis is horizontal and crossSection is vertical. Rest is same.

13. Button

Flutter has 3 basic type of button

1. Flat Button

2. Raised Button

3. MaterialButton

All the button are almost same only difference is in their look. Below example show default button of each type:

Widget getBody() {
return Column(

children: <Widget>[

FlatButton(onPressed:(){},
child: Text("Flat Button"),
),

RaisedButton(onPressed:(){},
child: Text("Raised Button"),
),

MaterialButton(
onPressed: (){},
child: Text("Material Button"),
)
],
);
}
}
Default look and feel of different kind of button

Please note that , i have provided a empty callback for onPressed. This is important otherwise button will be disabled.

It accept a child which is a widget. 😍

Other Properties:

Properties are almost same for all type of button. Therefore i am going to explain properties for only one.

Widget getBody() {
return Column(
children: <Widget>[
RaisedButton(
onPressed: () {},
child: Text("Raised Button"),

// text color for any text in its child if child
// don't define any color. sort of inherited color in css
textColor: Colors.white,

// text color when disabled.
disabledColor: Colors.grey,

// color of container
color: Colors.teal,

// ripple effect color shown when we click button
// small circular effect animation
splashColor: Colors.blue,

// Color show when button is kept pressed. Note that
// it is not same as splashColor. It appear without
// any animation.. solid color
highlightColor: Colors.amber,

// when button is pressed, button is elevated to this value..
highlightElevation: 20,

// button elevation, bigger the elevation, wider will be its
// shadow
elevation: 5,

padding: const EdgeInsets.all(20),

// border style
shape: RoundedRectangleBorder(
side: BorderSide(
color: Colors.black, width: 5, style: BorderStyle.solid),
// borderRadius: BorderRadius.only(topRight:Radius.circular(40)),
// borderRadius: BorderRadius.circular(40),
borderRadius: BorderRadius.all(Radius.circular(40)),
),
),
],
);
}
Splash color and Highlight color difference

When I click button you can see that blue splash color is visible, also yellow color highlight color as button is selected.

When I keep button pressed then you can see yellow color clearly and also notice button is elevated on selection. This is due to highlightElevation property.

14. Wrap

For starting wrap, let’s me quickly explain why we need it. We just learn row/column widget. I am going to make a layout nothing special just a bunch of button displayed in row.

5 button in a row

There is sometime wrong with above image. I have added 5 button in a row, but there is no enough space for 5th button and it overflow. This conditional is highly undesirable. To cope up with overflow Flutter provide many widget and wrap is one of them.

Wrap tries to place its children adjacent to each other along main axis but when there is no enough space , wrap create a new row (called run) and place new child in it.

Let’s try to replace row with wrap.

Button in a warp. Gif source : Tenor.com

Other Properties

Widget getBody() {
return Wrap(
// direction in which children will be place.
direction: Axis.horizontal,

// gravity. position of child in the wrap
alignment: WrapAlignment.center,

// space between two children along main axis
spacing: 10.0,

// spacing between two children along cross axis
runSpacing: 5.0,

children: <Widget>[
RaisedButton(onPressed: (){},child:Text("Button 1")),
RaisedButton(onPressed: (){},child: Text("Button 2"),),
RaisedButton(onPressed: (){},child: Text("Button 3"),),
RaisedButton(onPressed: (){},child: Text("Button 4"),),
RaisedButton(onPressed: (){},child: Text("Button 5"),),

],
);
}

15. ListView

Listview is just like row/column in but it is scrollable. When content of list is greater than it’s side, listview start scrolling.

In Flutter , list can be created in 3 differnt style.

  1. ListView()
  2. ListView.Builder()
  3. ListView.custom()

Here we will just study about 1st and 2nd.

ListView()

This form is more like Scrollview but here we can also change scrolling direction.

This constructor is used when we know the no. of children there gonna be in the list. For example , we can make filter menu which show 4–5 types of filter. As we know the no. of item we can put it inside our listview.

Other use case scenario is in place of row and column. We know row and column are not scrollable. Now, suppose we have to make a registration form with name,emailId,password, confirm password, street address, landmark, credit card details + don’t forget open soft keyboard which cover almost half of the screen. Now if we put all these widget together in a column , it is definitely going to overflow + you can’t scroll to next field after typing 😨.

Let’s code.

For simplicity, i have created a function getField which return me a TextField. It takes all the essential parameter and return fully baked TextField. In that manner,

i) I have broken my long code into smaller pieces

ii) As i need a lot of TextField in this example I can reuse it.

Widget getField(String hint,{TextInputType type = TextInputType.text,bool obscure = false,
IconData icons = Icons.person}){

return TextField(
keyboardType: type,
obscureText: obscure,

decoration: InputDecoration(labelText: hint,icon: Icon(icons)),


);

}

Let’s have our getBody()

Widget getBody() {
return Padding(
padding: const EdgeInsets.all(8.0),
child: ListView(

children: <Widget>[

Text("Registration Form",textAlign:TextAlign.center, style: TextStyle(fontSize:25.0),),
Padding(padding: const EdgeInsets.only(bottom: 10.0),),

getField("Enter Name",type :TextInputType.text,icons: Icons.person),
getField("Enter Phone No",type: TextInputType.phone,icons: Icons.phone),
getField("Enter email Id",type: TextInputType.emailAddress,icons: Icons.email),
getField("Enter Password",obscure: true,icons: Icons.lock),
getField("Re-enter Password",obscure: true,icons: Icons.lock),
getField("Enter street Address",icons: Icons.location_on),
getField("Enter your pin code",type: TextInputType.number,icons: Icons.location_on),
getField("Enter your card details",type: TextInputType.number,icons:Icons.credit_card),

Padding(padding: const EdgeInsets.symmetric(vertical: 10),),

RaisedButton(onPressed: (){},
child: Text("Submit"),
)

],

),
);
}
}

Output is :

But if you change list with column then we get:

Column

Other Properties.

Other properties include :

  1. Direction

2. reverse

3. padding

4. physics

See the below video to check how they affect.

Listview.builder()

One of the most basic use of a list view is to show list of item which are dynamic like loaded from network or from local storage. In that case you don’t know size of data. Therefore we have to use this constructor. It allows us to dynamically build a list.

This accept a builder which is more like a Adapter in Android.

Let’s code.

In the first example , I am going to display no from 1 to 10 using this constructor.

Widget getBody() {
return
ListView.builder(
itemCount : 10,
itemBuilder: (context,index){

// we have to return item at index ,
// Here i am simply returning a text.
return getItem(index);

});
}
}
  1. This constructor accept itemCount. It denote total no of item going to be in listview.
  2. This also accept a function in itemBuilder. Listview call this function to get required widget. This function accept a index integer value.

Listview call this function starting from 0..1..2..3..4…..9 (10 times = itemCount).

3. From itemBuilder we have to return a widget.

4. I am using getItem(index) function to construct our widget at position index.

Here is our getItem() function.

Widget getItem(int index){

return Padding(padding: const EdgeInsets.all(5),
child: Text("This is item ${index+1}",
style: TextStyle(fontSize: 20),),
);

}

Android developer, does it feel somewhat similar to list adapter. If you clap.

Output:

Simple list

Hold your horses!!! You said, we use this constructor when we don’t know the size of data. But it require itemCount. How will I provide it?

I mean to say, where we initially don’t know the size of list. After loading data, we can count boss.

Let’s build something attractive.

Simple list
  1. Make your data set.
var names = ['Nitish','Rahul','Aurav','Niwan','Dipanshu','Nikhil','Prashant',
'Nishutosh','Ram',"Arvind"];

var emaildId = ['nitish@gamil.com','rahul@gmail.com','aurav@gmail.com',
'niwan@gmail.com','dipanshu@gmail.com','nikhil@gmail.com', 'prashant@gamil.com',
'nishutosh@gamil.com','ram@gmail.com','arvind@gmail.com'];

Now build item.

Widget getItem(int index){

String name = names[index];
String email = emaildId[index];

return Padding(
padding: const EdgeInsets.symmetric(horizontal: 4),
child: Card(
elevation: 2.0,
child: ListTile(
leading: CircleAvatar(
child: Text(name[0].toUpperCase(),
style: TextStyle(fontSize: 25.0),),
backgroundColor: index%2==0?Colors.amber:Colors.green,
),
title: Text(name,style: TextStyle(fontSize: 20),),
subtitle: Text(email,style: TextStyle(fontSize: 15),),
),
),
);

}

We also need to change itemCount to size of list..

itemCount : names.length

That’s all.

16. PageView

PageView is equivalent to ViewPager in Android.

Pageview allow us to show different widget on screen one at a time. This pages can be horizontally or vertically scrollable. Example of this may include a music player layout , which show music arranged in track, artist, folder and allow us to swipe right or left to check out these arrangement.

Viewpager can also show great animation while scrolling.

Checkout my friend app on google play to see what we can do with viewpager(pageview).

Ok. Enough talking let’s code.

Widget getBody() {
return

PageView(

children: <Widget>[

getPage("Flutter is fun", Colors.green),
getPage("No, it is magic",Colors.amber),
getPage("Make some noise of ", Colors.redAccent),
getPage("Flutter", Colors.blue),
],

);
}

That’s all we have to do. PageView widget accept list of widget. Just provide widget to show and pageview will take care of rest. Android programmer will be like 😱 😨 😰 😯 😦 😧 😢 😥 😪 😓 😭 😵 😲.

Widget getPage(String title,Color background){

return Container(
color: background,
child: Center(
child: Text(title,style: TextStyle(fontSize: 30),),
),
);

}

Output.

Other Properties:

scrollDirection : can be set to veritcal or horizontal. Default is horizontal. Example of vertical scroll include Tic-tok app.

physics : We have already seen this property in list.

reverse : Pages are show in reverse order.

PageView also provide a builder constructor so that pages can be added dynamically. Use case may include a News app where you want to show news by category where categor are dynamically selected by user. It’s implementation is same as ListView.builder(). So I am skipping it.

17. Divider

It is used to visibly separate widget.

Widget getBody() {

return Column(

children: <Widget>[

Text("First line "),
Divider(),
Text("Second Line"),

],

);

}
See first and second text are separated by thin line

Other Properties:

Widget getBody() {
return Column(
children: <Widget>[
getFirstGroup(),
Divider(

// color of the divider
color: Colors.red,

// height of the divider, Please note that it is not
// the thickness of the divider, we cannot change thickness
// height means , total height which include
// padding above line + padding below line + divider thickness
height: 100,

//indent means space from the starting
// if you want space on both side, you can wrap divider in
// padding widget
indent: 50,
),
getSecondGroup(),
],
);
}

Output

Divider properties. height, indent and

18. Circular Progress Bar

It show little loading widget.

Widget getBody() {
return CircularProgressIndicator();
}

That’s all for the basic widget. As I said there are tons of widget in the Flutter , we will cover all of them as we try complex layout design.

Thank you for sticking around. If you like this article please boost my moral with claps. You have 50 claps for this article. Please rate it between 1 to 50.

--

--