Mastering Dart & Flutter DevTools — Part 2: Flutter Inspector

Flutter Gems
14 min readDec 28, 2022

by Ashita Prasad (LinkedIn, Twitter), fluttergems.dev

This is the second article in the “Mastering Dart & Flutter DevTools” series of in-depth articles. In this article, you will learn about DevTools’ Flutter Inspector via an example app case study. In case you want to check out any other article in this series, just click on the link provided below:

Installation and setup of DevTools is a pre-requisite for this part. In case you missed it, the installation and setup details are provided in detail here.

As mobile apps are growing at a rapid pace (~6k apps released per day on Apple and Google Play Store combined), there is a fierce competition to grab user’s attention and retention. The user interface (UI) of an app plays a crucial role in the overall user experience that is important for retaining users. A well-designed UI can make an app more intuitive and easy to use, while a poorly designed UI can make even the most powerful app difficult and frustrating to use. A good UI can also help differentiate your app from others on the market and make it more appealing to users. Thus, a well-designed UI is essential for the success of any app.

In Flutter, you can design and build beautiful User Interface (UI) through the use of widgets. To create a layout in Flutter, you can use a combination of these widgets to create the structure and appearance of your app’s user interface. But, what happens when your app’s layout has issues and the UI does not match the intended design?

This is where Flutter Inspector comes to our rescue. It can be used to understand existing layouts as well as diagnose any layout issues that may exist in an app. And the best part is that the visual debugging of the Layout can be performed on-the-fly.

The objective of this article is to walk you through the Flutter Inspector tool that can be used to debug any layout issues and understand it better using a real-life example app.

Flutter Inspector

Flutter Inspector is a tool that can be used for inspecting the widget tree of a Flutter app. Using this tool, you can easily visualize and inspect the layout, size, and visual properties of the widgets that compose the app’s UI. This tool can also be used to identify performance issues, perform visual debugging of the app and provide detailed information about the widgets.

To better understand how you can leverage the Flutter Inspector tool, let us go through a case-study exercise. In this exercise, we will begin with the UI layout in the left, as shown in the image below. Our objective is to identify the issues in the UI and debug them visually using the Flutter Inspector. After resolving all the UI issues visually, we will make the necessary code changes and transform the layout into the desired UI (right screen).

Example App — Provided UI (left) & Desired UI (right)

Now, let us get started with the case study.

Step 1: Getting the Source Code

Create a local copy of the below repository 👇

Open the repo in GitHub as shown below.

Click on the green button <> Code, then visit the Local tab and click Download ZIP to download the source code for this exercise.

Extract the file using any unzip tool.

We now have a local copy of the source in the folder flutter_inspector_demo-master.

Step 2: Opening the Project in VS Code

Launch VS Code, open the project folder in VS Code and go to pubspec.yaml file.

Click on Get Packages to fetch all the packages required for the project.

Click Get Packages

Step 3: Launching Flutter Inspector in VS Code

Before we launch the Flutter Inspector, we must run the app.

Click on No Device in the status bar and select a target device. If a default device is already selected, you can click on it and change the target device.

Select Target Device

We will go ahead and select an android emulator as the target device.

android emulator selected as target device

Now, click Run to run the app (main function) as shown in the image below.

Run the app

Flutter Inspector can be launched using the following instructions:

Click Dart DevTools in status bar > 
Click Open DevTools in Web Browser > Click Flutter Inspector tab
Launch App and Flutter Inspector

Anatomy of the Flutter Inspector

The Flutter Inspector window has three major parts:

  1. Toolbar
  2. Widget Tree Pane
  3. Layout Explorer / Widget Details Tree Pane

Let us quickly walk through these parts:

1. Flutter Inspector’s Toolbar

Flutter Inspector’s Toolbar

Flutter Inspector’s toolbar provides features that help in debugging layout issues visually. To activate any feature you just need to press the corresponding button in the toolbar. The available features are:

  • Select Widget Mode — Widgets can be selected in the interactive Widget Tree Panel to inspect their properties. But, this can be cumbersome in case the widget tree is deep. Enabling this mode allows the user to select a widget directly on the app’s UI, so that it can be further inspected.
  • Slow animations — When slow animations is enabled, all animations runs 5 times slower allowing for easy visual inspection. It is useful for observing and tweaking any animation that might not look fully right.
  • Show guidelines — When this feature is enabled, guidelines are drawn in the app displaying render boxes, alignments, paddings, scroll views, clipping and spacers. This tool can be used to better understand and modify the layout such as better aligning the widgets or removing any unwanted padding.
  • Show baselines — This tool is useful for visually inspecting the alignment of texts using baselines that are horizontal lines used for positioning texts. Selecting this option will make all the baselines visible, allowing you to precisely check the vertical alignment of the text.
  • Highlight repaints — This tool is useful for highlighting the widgets that are repainting frequently, that can hamper the performance of the app. Every time a box repaints, a border is drawn around it in a rotating rainbow colour.
  • Highlight oversized images — As the name suggests, this tool highlights high resolution images that are using too much memory by inverting colours and flipping them. Fixing these images is important as they can cause poor performance, especially on lower end devices and in case you have many images on the screen like in a GridView or a ListView.

2. Widget Tree Pane

Widget Tree Pane

In Flutter, any piece of UI that is rendered on the screen is a widget. The layout of a Flutter app’s user interface is composed of a hierarchy of widgets that is better known as the widget tree. The tree consists of individual widgets, each of which has its own properties and child widgets. This hierarchical structure is the primary reason why Flutter is able to efficiently compose and render the user interface. The Widget Tree pane is useful for viewing this widget tree and it can be used to select any widget in the tree to further inspect its layout and properties.

3. Layout Explorer / Widget Details Tree Pane

Layout Explorer

Whenever a flex widget (Row, Column, Flex) or any child of a flex widget is selected in the Widget Tree Pane, its layout can be visualized in the Layout Explorer (shown above). This view also provides various tools using which we can visually change the existing layout. To get a more detailed view of all the properties and values of the selected widget, you can click on the Widget Details Tree Tab as shown below.

Widget Details Tree

After getting familiar with the interface (anatomy) of the Flutter Inspector Page, let us now proceed to the case study.

Case Study

Our objective is to use the Flutter Inspector to visually debug layout issues in the example app so that we can get our desired UI.

Example App — Provided UI (left) & Desired UI (right)

Looking at the two UIs, we can identify 4 major problems in the layout:

  • Layout Problem #1 — Over-flowing text in the first row.
  • Layout Problem #2 — Emojis are not well-spaced and are not at the center of the remaining available vertical space in the page.
  • Layout Problem #3 — The horizontal divider is missing.
  • Layout Problem #4 — Submit button is not center aligned.

Let us go ahead and use the Flutter Inspector to fix these layout problems one at a time.

Layout Problem #1

The first issue that we need to resolve in our UI is the overflowing text.

Layout Problem #1

On launching the Flutter Inspector, we can see Error 1/1 in the Widget Tree Panel.

Click on the Down Button as shown in the image below to navigate to the error causing widget. The error encountered is ‘A RenderFlex overflowed by...’ error, which is one of the most commonly occurring error. You can see yellow & black stripes indicating the area of overflow both in the app UI and the Layout Explorer.

As shown in the image below, the reason for this error is due to the fact that the child widget Text is not constrained in its size and is trying to be wider (by 237 pixels) than the width permitted by its parent (Row).

Overflow Error

As shown in the image below, we can debug this issue directly from the Layout Explorer by setting the flex of the Text widget as 1. This way we are telling the Text widget that it can expand only till it fills the available space along the main axis of the Row widget.

Fixing Issue via Layout Explorer

Voila! The issue is now fixed.

But, hold on a second. If you go ahead and restart the app, the issue comes back again to haunt us.

This is because visually fixing any issue using the Layout Explore is not permanent as no code changes are being made. It is a visual debugging tool using which you can play around and identify the correct solution. After arriving at the solution, you now have to perform the necessary code changes to persist the solution.

Let us go ahead and modify the existing Problem #1 code given below

// Problem #1
Row(
children: const [
Text(
'Please provide your valuable feedback by sharing your experience with us!',
style: TextStyle(
fontSize: 18.0,
),
),
],
),

by wrapping the Text widget inside the Expanded widget so that widget fills the entire available space horizontally. The default value of flex of the Expanded widget is 1 which is same as the value of flex we had set using the Layout Explorer.

The modified code is given below:

// Problem #1
Row(
children: const [
Expanded(
child: Text(
'Please provide your valuable feedback by sharing your experience with us!',
style: TextStyle(
fontSize: 18.0,
),
),
),
],
),

After modifying the code, the new changes should automatically Hot Reload. In case it doesn’t, then press Restart to propagate the changes we made.

Press Restart

After fixing the first layout problem our app UI looks as follows.

After Fixing Layout Problem #1

Layout Problem #2

The next problem we need to fix is the layout of the emojis.

Layout Problem #2

As shown in the image above, the emojis should be at the center of the remaining available vertical space. Also, the emojis should be evenly spaced.

Before we proceed further, let us go ahead and enable the Show Guidelines mode from the toolbar as shown in the image below. These guidelines will help us better debug the layout visually.

Enable Show Guidelines

Let us start with creating some even spacing between the emojis.

Create Even Spacing

As shown in the image above, click on the Row widget in the widget tree that contains the Emoji widgets. In the Layout Explorer, the widgets inside the Row are currently aligned as start along the main axis. Click on the dropdown and select the alignment as spaceEvenly. Now you can observe that the Emoji widgets are evenly spaced just as we wanted them to be.

Next, we want to expand this Row containing emojis to occupy the entire remaining vertical space.

Expand Row to occupy the entire remaining vertical space

As visible in Widget Tree Pane in the image above, the Row containing Emoji widgets is the second child of the Column. Go ahead and click on the parent Column widget and scroll down to locate this Row in the layout explorer. Now, set the flex of this Row as 1. As the parent of this Row is a Column, its main axis is along the vertical direction. So setting the flex as 1 tells this Row that it can expand vertically as long as the Column permits.

Although we were able to expand the emoji row vertically, still the emojis are not in the center as desired. This is because each Emoji widget is a Column containing an emoji Text and a label Text as its children. When the row expands vertically, the columns do too, as it can be seen via guidelines. But, these children are aligned towards the start of the main axis of the Column widget, so their position does not change. As shown in the image below, we can change their alignment via the Layout Explorer. Click on the Column widget inside each Emoji widget and change the main axis alignment to center.

Children of Emoji Widgets are center aligned

As this is the required solution, let us go ahead and make the necessary code changes.

class Emoji extends StatelessWidget {
....

@override
Widget build(BuildContext context) {
return Column(

// Add this line to align Emoji & Text to center
mainAxisAlignment: MainAxisAlignment.center,

children: [
...
],
);
}
}

class MainApp extends StatelessWidget {
const MainApp({super.key});

@override
Widget build(BuildContext context) {

...
//Problem #2

// Wrap the Row widget inside an expanded widget to
// expand vertically
Expanded(
child: Row(

// Add spaceEvenly main axis alignment inside Row
mainAxisAlignment: MainAxisAlignment.spaceEvenly,

children: const [
Emoji('😀', 'Good'),
Emoji('😐', 'Average'),
Emoji('🙁', 'Bad'),
],
),
),
...
}
}

The 3 code changes to be made are:

  • The Row of Emoji widgets is wrapped inside the Expanded widget so that it can occupy the entire remaining vertical space.
  • mainAxisAlignment: MainAxisAlignment.spaceEvenly added to the above row to space the Emoji widgets evenly in the horizontal direction.
  • mainAxisAlignment: MainAxisAlignment.center added to the Column widget of the Emoji to center align its children vertically.

After resolving the Layout Problem #2, the UI is now heading towards our desired UI.

After Fixing Layout Problem #2

Layout Problem #3

The next task is to figure out the curious case of the missing horizontal divider.

Layout Problem #3

On inspecting the widget tree as shown below, we can see that although the Divider widget is present, still it is not visible in the UI. If we click on the widget and look at the Layout Explorer, its width is computed as 0.0 as no width constraint is provided.

Explore the Layout of the Divider widget

Go ahead and set the value of flex as 1 so that the width constraint is supplied and it expands to occupy the entire available width of the Row.

Adding a flex value

Let us make the necessary code changes by wrapping the Divider inside an Expanded widget as shown below:

// Problem #3
Row(
children: const [
// Wrap the Divider inside the Expanded widget
// to provide width constrain
Expanded(
child: Divider(
color: Colors.black,
),
),
],
),

After solving Layout Problem #3 we obtain the following UI.

After Fixing Layout Problem #3

Layout Problem #4

The final task remaining at hand is to center align the Submit button.

Layout Problem #4

This issue can be quickly fixed by changing the main axis alignment of the children inside the last Row widget. Click on the widget and select center from the main axis alignment dropdown as shown below.

Center align the button

Let us go ahead and perform the corresponding code changes.

// Problem #4
Row(
// Add mainAxisAlignment as center
mainAxisAlignment: MainAxisAlignment.center,

children: [
ElevatedButton(
onPressed: () {
debugPrint('Submit button pressed.');
},
child: const Text(
'Submit',
),
),
],
),

The final UI after solving the Problem Layout #4 is shown below.

After Fixing Layout Problem #4

Yay! We have successfully obtained the desired UI Layout with the help of Flutter Inspector tool that helped us in debugging the issues visually.

In this article we took the help of DevTools’ Flutter Inspector tool to visually debug a UI Layout containing various problems. We started with a given Layout and identified various layout issues like overflowing text, uneven spacing between emojis, missing horizontal divider and submit button not being center aligned. Using the tools provided inside Flutter Inspector, we resolved those issues, made the necessary code changes and finally obtained the desired UI.

We would love to hear your experience with the Flutter Inspector. In case you faced any issues while going through this exercise or while running the tool for your project, please feel free to mention it in the comments and we can definitely take a look into it. Also, in case you have any other suggestion, do add it in the comments.

In the remaining articles of this series, we have discussed other tools available in the DevTools suite that can help you build high-performance Flutter apps. Don’t forget to check out the links below to navigate to the tool you want to learn next:

Source Code(s) used in this article:

Special thanks to Kamal Shree (GDE — Dart & Flutter) for reviewing this article.

--

--

Flutter Gems

Maintained by Ashita Prasad, Flutter Gems is a curated package guide for Flutter ecosystem. Visit https://fluttergems.dev