
There are cases that
we want to reuse our widget. For example we have a padding that
contains a material button, This type of button which has the same design for
different screens has the styles except for color, title, and method.
We can extract a
widget and have its own stateless widget so that we can call it and change its properties according to what we need, take a look at our example. We have Login nad Register button but they have different title, colors and functionalities.
If we analyze, we know that we need 3 dynamic variables for it;
If we analyze, we know that we need 3 dynamic variables for it;
1. Color variable
2. String variable for button title
3. Function variable for the button's onPressed callback.
Let Us Say that the following is a widget that we're going to use multiple times.
Padding(
padding: EdgeInsets.symmetric(vertical: 16.0),
child: Material(
elevation: 5.0,
color: Colors.lightBlueAccent,
borderRadius: BorderRadius.circular(30.0),
child: MaterialButton(
onPressed: () {
//Go to login screen.
Navigator.pushNamed(context, LoginScreen.id);
},
minWidth: 200.0,
height: 42.0,
child: Text(
'Log In',
),
),
),
),
In your visual studio code find the widget you use multiple times. Clicn on it then a bulb will show at left, click the bulb then select extract widget
It will ask for the class name, in our case we named it RoundedButton
You will see that the widget will be replaced by a class RoundedButton() and a stateless widget is created at the bottom
We don't need the constructor so just remove the following
// const RoundedButton({
// Key key,
// }) : super(key: key);
We're going to create our own constructor that is going to initialize 3 properties. We need the onpressed to be required so just add @required
RoundedButton({this.title,this.colour,@required this.onPressed});
final Color colour;
final String title;
final Function onPressed;
Now We're going to update the properties of the MaterialButton to be dynamic. This is now the current child where material button is
child: Material(
elevation: 5.0,
// color: Colors.lightBlueAccent,
color: colour,
borderRadius: BorderRadius.circular(30.0),
child: MaterialButton(
onPressed: onPressed,
minWidth: 200.0,
height: 42.0,
child: Text(
title,
),
),
),
Now let us use the RoundedButton at the top, if you hover on it, it will tell you that it require an onpress as what we initialized in its constructor
Let's fill the requirements for its constructor.
Reminder, in the onPressed(), we use a different way of naming a route, just use your way of pushing the navigator.
new RoundedButton(title: 'Log In', colour: Colors.lightBlueAccent, onPressed: (){
Navigator.pushNamed(context, LoginScreen.id);
},),
Now our Button is reusable!!!
You can now call the RoundedButton with your own specific application for it.
Creating its Own File
Inside your lib, creat a folder and name it "components", inside it create a dart file rounded_buttons.dartOpen the rounded_button.dart and import material.dart
import 'package:flutter/material.dart'
Go back to your previous dart file which in my case is welcome_screen.dart and cut the RoundedButton stateless widget and paste it in your file rounded_buttons.dart
The current rounded_buttons.dart contains the following code
import 'package:flutter/material.dart'
class RoundedButton extends StatelessWidget {
// const RoundedButton({
// Key key,
// }) : super(key: key);
RoundedButton({this.title,this.colour,@required this.onPressed});
final Color colour;
final String title;
final Function onPressed;
@override
Widget build(BuildContext context) {
return Padding(
padding: EdgeInsets.symmetric(vertical: 16.0),
child: Material(
elevation: 5.0,
// color: Colors.lightBlueAccent,
color: colour,
borderRadius: BorderRadius.circular(30.0),
child: MaterialButton(
onPressed: onPressed,
minWidth: 200.0,
height: 42.0,
child: Text(
title,
),
),
),
);
}
}
Now go back to welcome_screen.dart and import the new rounded_button.dart
import '../components/rounded_button.dart';
Now we have refactor our code :)





