Let's Code Flutter: Three Useful Widgets
There are so many Widgets, and each of them does so many things. In a lot of cases, you can think of Widgets as various upgrades to other Widgets. And the way Flutter seems to be optimized, there's no limit to how many Widgets you can apply to other Widgets. Here are three Widgets that I've been using lately to help me get my work done.
GestureDetector
Personally, this one is named slightly deceptively, but that's only because I'm coming from a pure Android development background. But this handy little widget behaves like most others: it adds a behavior to its children.
In Android, to have something react to presses, you would give it an onClickListener
. Simple enough, and all Views support it. Similarly in Flutter, you would instead wrap the child you want to handle these presses in a GestureDetector
widget.
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () => handleTap(),
child: Container(),
);
}
You can also handle a million (Citation needed) other types of gestures.
Here's a small snippet of everything GestureDetector
has to offer. As well as handling taps, I've used it to handle panning, similar to how a Slider functions.
LayoutBuilder
Sometimes you need a child widget to depend on the parent's size. During the build
, this is generally not available. However, you can get what you need by wrapping the child in a LayoutBuilder
widget.
@override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Container(
margin: EdgeInsets.all(5.0),
child: LayoutBuilder(
builder: (context, BoxConstraints layout) {
return Container(
width: layout.maxWidth / 3,
height: layout.maxHeight / 3,
child: Container(),
);
},
)
)
)
);
}
Inside a Scaffold, inside a SafeArea, inside a Container with margins, we want to act on the constraints of the space we have left. The constraints contain the minimum and maximum width and height available to us.
ValueListenableBuilder
This is a new Widget for me, and I'm still trying to figure out the best/optimal use case for it. In my original post about switching to Flutter, I list a few widgets that I assume will be your "bread and butter," making up the majority of the widgets you use. In that list I mention StreamBuilder
, a Widget that takes a Stream and calls its builder every time the stream emits items.
A ValueListenableBuilder
performs almost exactly the same way, except it listens to a ValueNotifier
, then emits that value to its builder whenever it changes.
ValueNotifier<bool> _showEmptyView = ValueNotifier(false);
@override
Widget build(BuildContext context) {
return Container(
child: Column(
children: [
ValueListenableBuilder<bool>(
valueListenable: _showEmptyView,
builder: (context, _showEmptyView, child) {
if (_showEmptyView) {
return Container(
color: Colors.red,
child: ...
);
} else {
return Container(
color: Colors.blue,
child: ...
);
}
},
),
ElevatedButton(
onPressed: () {
_showEmptyView.value = !_showEmptyView.value;
},
child: Text("Press me"),
)
],
),
);
}
Depending on your layout and optimization needs, you could ignore this Widget and just call setState
, updating a show/hide boolean. Or you could create a custom StatefulWidget that handles the state, which is actually what ValueListenableBuilder is.
If you have any insight into this Widget, please share!
Head on over to the Flutter official documentation for more information on these amazing widgets.
What are some Widget you've been using lately? Let me know in the comments and help me find something new to play around with!