Chapters

Hide chapters

Android Debugging by Tutorials

First Edition · Android 12 · Kotlin 1.6 · Android Studio Chipmunk (2021.2.1)

Section I: Debugging Basics

Section 1: 8 chapters
Show chapters Hide chapters

6. Layout Inspector
Written by Zac Lippard

Up until now, you’ve learned many ways to debug your app’s code. But what if you wanted to debug the UI? Enter, the Layout Inspector.

The Layout Inspector is a tool provided by Android Studio that enables you to debug layouts in your app. The inspector takes a snapshot of the UI to provide details about the layout. These details can be what views are in the UI hierarchy, attributes of each view and a 3D rendering to inspect the views at different angles.

Effective use of the Layout Inspector can help you catch potential defects in your layouts, as well as help improve the overall UI performance.

In this chapter, you’ll use the Layout Inspector and learn how to:

  • Inspect the view hierarchy.
  • Generate a 3D rendering of your app’s UI.
  • Read the attributes of a view.
  • Condense layout layers.
  • Validate layouts on different devices and configurations.

Running the Layout Inspector

Begin by opening the Podplay starter project in Android Studio. Before running the app, click Select Run/Debug Configuration from the toolbar and choose Edit Configurations…

In the Run/Debug Configurations dialog, click the Miscellaneous tab and check the Connect to Layout Inspector without restarting activity box.

When you check this option, the Layout Inspector passes a flag to the launching activity. The flag allows the inspector to connect to the app immediately. Otherwise, the inspector has to restart the activity each time it’s loaded, and you’ll have to navigate back to the view you want to inspect.

Click OK to save changes.

Run the app. When the app launches, start the Layout Inspector by clicking Tools ▸ Layout Inspector from the Android Studio menu.

The following sections in the inspector include:

  1. Component Tree: This shows all the views in the hierarchy. You’ll notice this particular layout’s hierarchy is shallow, with only two layers.
  2. Layout Display: This is the rendered display of your layout. This section allows you to zoom in on specific views in the layout and explore the layers of the hierarchy in 3D.
  3. View Attributes: When you select a view from the component tree or the layout display, the attributes for that view appear here.

At the bottom right of the layout display section click the 3D Mode button.

Note: The first time you do this, it may ask you to install some additional components within Android Studio.

The display rendering updates to show a 3D layering of your views:

Notice there’s a toolbar at the top of the layout display section. This toolbar includes several features such as:

  1. Showing and hiding certain aspects of views.
  2. Loading overlays.
  3. Exporting snapshots.
  4. Enabling live updates of the inspector.
  5. Refreshing the inspector.
  6. Adjusting the spacing of the hierarchy layers.

You’ll learn more about each of these later in this chapter.

The 3D rendering in the layout display allows you to observe the layout and its layers, view outlines display and show you how many nested view groups are in your layout. This rendering can help you determine if you have too many layers and if your layouts are complex.

When the UI gets rendered, the system has to do a number of layout passes to draw each view layer in the hierarchy. Too many nested layers can cause drawing issues like overdraw and will slow down the layout process.

Overdraw occurs when the system attempts to draw over the same pixel or group of pixels in layout passes. Overdraw is inefficient and often unnecessary as the GPU has to re-process rendering and draw the same part of the screen multiple times.

Note: To learn more about overdraw and ways to reduce it, read the Overdraw Android developer documentation.

The layout display will show you potential overdraw areas within the 3D rendering. Overlapping layers with background colors set in the same region are candidates for overdraw. You should avoid this as much as possible.

Now that you’ve understood what the Layout Inspector can do, it’s time to improve one layout in the Podplay app!

In the starter project, fragment_episode_player.xml contains a number of nested RelativeLayout and LinearLayout view groups. You’ll improve this layout file and use the Layout Inspector to view the changes.

Refreshing the Layout Inspector

You’ll need to refresh the inspector to load the episode player view. To do so, go to the running Podplay app, tap Search and enter “android”. Tap a podcast from the list and choose an episode so the player screen loads.

Go back to the Layout Inspector and click the Refresh layout icon.

The layout display will refresh and show the hierarchy for the episode player fragment.

As an alternative to manually refreshing the Layout Inspector, you can enable the inspector to update automatically. Whenever you go to a new screen or change the UI, the inspector will update its component tree, display and its view attributes accordingly to reflect the changes from the app.

Click the Live Updates icon in the inspector toolbar to use automatic updates.

Isolating a View

There’s a lot going on in the current layout display with all the views in the hierarchy. What you’ll focus on is the podcastDetailsContainer view. Click that view in the component tree, highlighting the associated view in the display.

This is a bit better, but you can also isolate this container view and remove all the others in the hierarchy that you don’t care about.

To do this, right-click the podcastDetailsContainer and select the Show Only Subtree option.

Now, the display section updates to only show the view hierarchy related to the container:

Views in the component tree that aren’t a part of the selected subtree will grey out with strikethrough text.

Click and drag the layers in the display section to rotate the 3D model. You can also expand or contract the spacing by adjusting the Layout spacing slider. Increase the spacing to provide more clarity in the subtree display:

Take note of the nested layers in the highlighted section in the layer display above. You’ll work on condensing this layout to remove some extra layers.

Before you start, take a picture of the app in this state. You’ll use this picture later to confirm that your changes align with how the app currently looks.

To take a screen capture, click the Logcat tab in Android Studio and click the Screen capture icon.

In the dialog window, save the screen capture to your workstation.

Now it’s time to improve the layout!

Condensing Layouts With ConstraintLayout

Open fragment_episode_player.xml in Android Studio. Look for the RelativeLayout with id set to @+id/headerView:

<RelativeLayout
  android:id="@+id/headerView"
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:background="#eeeeee"
  app:layout_constraintEnd_toEndOf="parent"
  app:layout_constraintStart_toStartOf="parent"
  app:layout_constraintTop_toTopOf="parent">

  <ImageView
    android:id="@+id/episodeImageView"
    android:layout_width="60dp"
    android:layout_height="60dp"
    android:layout_marginStart="8dp"
    android:layout_marginTop="8dp"
    android:contentDescription="@string/episode_thumbnail"
    android:src="@android:drawable/ic_menu_report_image" />

  <TextView
    android:id="@+id/episodeTitleTextView"
    android:layout_width="match_parent"
    android:layout_height="0dp"
    android:layout_alignBottom="@+id/episodeImageView"
    android:layout_alignTop="@+id/episodeImageView"
    android:layout_marginEnd="8dp"
    android:layout_marginStart="8dp"
    android:layout_toEndOf="@+id/episodeImageView"
    android:text="" />
</RelativeLayout>

This view is currently a RelativeLayout with child views episodeImageView and episodeTitleView. These child views can move up one level since the root of this layout is already a ConstraintLayout. Replace the code above with the following:

<ImageView
  android:id="@+id/episodeImageView"
  android:layout_width="68dp"
  android:layout_height="68dp"
  android:paddingStart="8dp"
  android:paddingTop="8dp"
  android:contentDescription="@string/episode_thumbnail"
  android:src="@android:drawable/ic_menu_report_image"
  android:background="#eeeeee"
  app:layout_constraintTop_toTopOf="parent"
  app:layout_constraintStart_toStartOf="parent" />

<TextView
  android:id="@+id/episodeTitleTextView"
  android:layout_width="0dp"
  android:layout_height="0dp"
  android:paddingEnd="8dp"
  android:paddingStart="8dp"
  android:text=""
  android:gravity="center_vertical"
  android:background="#eeeeee"
  app:layout_constraintTop_toTopOf="@id/episodeImageView"
  app:layout_constraintStart_toEndOf="@id/episodeImageView"
  app:layout_constraintEnd_toEndOf="parent"
  app:layout_constraintBottom_toBottomOf="@id/episodeImageView" />

The most notable changes here are:

  • Removing of the RelativeLayout component.
  • Adding background-color #eeeeee to each child view.
  • Replacing margins with padding to properly apply the background color.
  • episodeTitleTextView is now centered vertically in the parent view using the android:gravity property.
  • Applying constr aints to each child view.

If you try to compile the app it’ll fail because we’ve removed the headerView element which EpisodePlayerFragment references. Rather than changing the code to change the visibility of each child view, you can use a Group. Add the following below episodeTitleTextView:

<androidx.constraintlayout.widget.Group
  android:id="@+id/headerView"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  app:constraint_referenced_ids="episodeImageView,episodeTitleTextView" />

This view logically groups episodeImageView and episodeTitleTextView together under the headerView ID. This allows EpisodePlayerFragment to reference the same ID without the overhead of an extra view layer in the hierarchy.

The next view group you’ll condense is the playerControls view. This is a fairly complex LinearLayout which contains the controls for the player, such as rewind, play/pause and fast-forward. This is within a nested RelativeLayout. There’s also another nested LinearLayout which holds the time controls, like the start and end times, as well as the seek bar.

Start by replacing the playerControls LinearLayout with a ConstraintLayout:

<androidx.constraintlayout.widget.ConstraintLayout
  android:id="@+id/playerControls"
  android:layout_width="0dp"
  android:layout_height="wrap_content"
  android:background="@android:color/background_dark"
  app:layout_constraintBottom_toBottomOf="parent"
  app:layout_constraintEnd_toEndOf="parent"
  app:layout_constraintStart_toStartOf="parent">

Remember to change the end tag to match.

Next, you’ll need to add the nested child views as a single, flattened layer. Replace nested RelativeLayout and LinearLayout views with the following code:

<Button
  android:id="@+id/playToggleButton"
  android:layout_width="34dp"
  android:layout_height="34dp"
  android:layout_marginTop="8dp"
  android:background="@drawable/ic_play_pause_toggle"
  android:scaleType="fitCenter"
  app:layout_constraintTop_toTopOf="parent"
  app:layout_constraintStart_toStartOf="parent"
  app:layout_constraintEnd_toEndOf="parent"
  app:layout_constraintBottom_toTopOf="@id/seekBar" />

<ImageButton
  android:id="@+id/forwardButton"
  android:layout_width="34dp"
  android:layout_height="34dp"
  android:layout_marginStart="24dp"
  android:layout_marginTop="8dp"
  android:background="@android:color/transparent"
  android:contentDescription="@string/skip_forward"
  android:scaleType="fitCenter"
  android:src="@drawable/ic_forward_30_white"
  app:layout_constraintTop_toTopOf="parent"
  app:layout_constraintStart_toEndOf="@id/playToggleButton"
  app:layout_constraintBottom_toTopOf="@id/seekBar" />

<ImageButton
  android:id="@+id/replayButton"
  android:layout_width="34dp"
  android:layout_height="34dp"
  android:layout_marginEnd="24dp"
  android:layout_marginTop="8dp"
  android:background="@android:color/transparent"
  android:contentDescription="@string/replay_button"
  android:scaleType="fitCenter"
  android:src="@drawable/ic_replay_10_white"
  app:layout_constraintTop_toTopOf="parent"
  app:layout_constraintEnd_toStartOf="@id/playToggleButton"
  app:layout_constraintBottom_toTopOf="@id/seekBar" />

<Button
  android:id="@+id/speedButton"
  android:layout_width="wrap_content"
  android:layout_height="0dp"
  android:layout_marginEnd="8dp"
  android:layout_marginTop="5dp"
  android:background="@android:color/transparent"
  android:text="@string/_1x"
  android:textAllCaps="false"
  android:textColor="@android:color/white"
  android:textSize="14sp"
  app:layout_constraintTop_toTopOf="parent"
  app:layout_constraintEnd_toEndOf="parent"
  app:layout_constraintBottom_toTopOf="@id/seekBar" />

<TextView
  android:id="@+id/currentTimeTextView"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:layout_marginBottom="8dp"
  android:layout_marginStart="8dp"
  android:text="@string/_0_00"
  android:textColor="@android:color/white"
  android:textSize="12sp"
  app:layout_constraintStart_toStartOf="parent"
  app:layout_constraintBottom_toBottomOf="parent" />

<SeekBar
  android:id="@+id/seekBar"
  android:layout_width="0dp"
  android:layout_height="wrap_content"
  android:layout_marginBottom="8dp"
  android:layout_marginEnd="8dp"
  android:layout_marginStart="8dp"
  android:progressBackgroundTint="@android:color/white"
  app:layout_constraintStart_toEndOf="@id/currentTimeTextView"
  app:layout_constraintEnd_toStartOf="@id/endTimeTextView"
  app:layout_constraintBottom_toBottomOf="parent" />

<TextView
  android:id="@+id/endTimeTextView"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:layout_marginBottom="8dp"
  android:layout_marginEnd="8dp"
  android:text="@string/_0_00"
  android:textColor="@android:color/white"
  android:textSize="12sp"
  app:layout_constraintEnd_toEndOf="parent"
  app:layout_constraintBottom_toBottomOf="parent" />

All the views constrain to either the parent view or each other. No more nested RelativeLayout or LinearLayout required!

Build and run the app, search “android” again and select the same podcast and episode. You’ll notice that the episode player layout looks the same but with fewer layers. You can also confirm that the layers have been condensed down by using the 3D mode in the layout display:

Don’t believe your eyes that view layers are the same? Well, next, you’ll confirm that they actually do match! :]

Confirming Changes With the Layout Overlay

Start by refreshing the Layout Inspector. Next, click the Load Overlay icon:

Select the Logcat screen capture that you saved from earlier. The inspector’s display section updates and includes the overlaid image on top of the rendered layout.

  1. Use the Overlay Alpha slider to change the overlay’s opacity. As you adjust the slider, the image fades in and out. There won’t be any changes between the overlay image and the rendering from the Layout Inspector. With this tool, you can officially confirm that the views remained the same while condensing the hierarchy.
  2. Finally, click the Clear Overlay button in the toolbar.

Exporting a Layout Inspector Snapshot

The Layout Inspector provides an export tool where you can save all the inspector details to an .li file. This snapshot file is useful for sharing with your team and viewing in Android Studio.

To export an inspector snapshot, click the Export Snapshot icon in the toolbar:

When you’re ready to view the snapshot, you can open it directly in Android Studio via File ▸ Open and select the .li file.

The view for this file is the same as the Layout Inspector window, and you can perform all the same tasks on this screen as you can in the inspector window.

Validating Layouts

Before running your application, you can visually inspect your changes in the XML layout files with the Layout Validation tool. This tool helps you confirm that the layouts you write look correct across a wide range of device references, color settings and font sizes.

Open fragment_episode_player.xml, and you’ll see that the Layout Validation tab on the right vertical toolbar appears.

Select this tab to open the validation window:

This window shows you what the layout will look like under different device configurations.

Two notable options in the window toolbar are:

  1. Configuration Set: Changes the device configuration itself. This is where you can choose different device types and do colorblind tests or font size validation.
  2. View Options: Provides options to change the layout. The main option is Show System UI, which you can enable now. This particular option will display the status and action bars at the top and the hardware buttons at the bottom.

Devices Types

As shown above, the default configuration setting is the Reference Devices. Using this configuration, the Layout Validation shows the layout on a range of device types, including phones, foldables, tablets and even desktop configurations. This saves you time from having to load multiple emulators for each device type or gather actual devices and run the app on each one.

You can also show Wear OS configurations if you’re working on a wearable app. While the episode player view isn’t intended for this use, you can still check out how the layout will appear on the different Wear OS configurations.

Change the configuration set to Wear OS Devices:

Custom Configurations

You can create a custom configuration based on the criteria that you want to validate. To do this, change the configuration set to Custom. Notice that the validation toolbar updates to include the Add configuration icon.

Click the icon and a dialog appears:

Here, you can set your configuration settings. For this example, give it the name “Landscape” and choose LANDSCAPE for the orientation.

Click Add, and the validation window will update to include the layout using your custom configuration:

Colorblind Tests

It’s important to ensure your layouts are accessible to as many people as possible. In the Layout Validation tab, you can perform a layout test to confirm that your app is still accessible to users who are color blind.

Change the configuration set to Color Blind:

Multiple layouts appear showing the different types of common color blindness:

  • Protanopes and Protanomaly represent how people with severe and mild red-green color blindness will see the layouts. Defects in the red cone eye pigments of the eye cause this type of color blindness.
  • Deuteranopes and Deuteranomaly show how the layouts appear to those with severe and mild red-green color blindness caused by defects in the green cone pigments.
  • Tritanopes represents the layouts in the way users with blue-yellow color blindness see them.

These different views help you determine if there are color clashes that you’ll need to address before releasing your app to the public.

Font Sizes

Along with the topic of accessibility, font sizing is another essential aspect to test. A common way of testing your app is by adjusting the font size via the Settings app and then opening your app and verifying that the changed font size looks good.

With the Font Sizes configuration, you can easily view at once how your layout will appear with different font sizes.

Change the configuration set to Font Sizes:

The default font size at 100% is displayed, along with small — 85%, large — 115% and largest — 130%. This allows you to see font size differences side-by-side. You can also determine if there’ll be any issues with your layout if a user needs to use an increased font on their device.

Challenge

Congratulations on condensing down those views in the episode player! But, there’s still more you can do. You converted the playersControl view to a ConstraintLayout in fragment_episode_player.xml. Improve that layout again and remove the playerControls layer altogether. After removing the layer, move its children into the root ConstraintLayout. Afterward, verify that the layer is gone by using the Layout Inspector and its 3D rendering mode.

Key Points

  • The Layout Inspector displays the views as layers in the UI hierarchy.
  • The inspector’s 3D render tool allows you to view the layers.
  • Add overlays in the inspector to confirm changes are accurate.
  • Export snapshots of the inspector for later use.
  • Validate layouts against device types, color blindness tests, and font sizes.

Where to Go From Here?

To learn even more about the Layout Inspector, read the associated Android developer user guide.

If you’re interested in learning more about accessibility, check out Android Accessibility by Tutorials.

The journey isn’t over yet! In the next chapter, you’ll learn how to live query databases with the Database Inspector.

Have a technical question? Want to report a bug? You can ask questions and report bugs to the book authors in our official book forum here.
© 2026 Kodeco Inc.