prscrew.com

Creating Expandable Lists in SwiftUI: A Comprehensive Guide

Written on

Chapter 1: Introduction to Expandable Lists

Utilizing an expandable list view in your application provides users with greater control over what they see on their screens. This clever approach significantly enhances user experience, especially when managing large amounts of data.

In this tutorial, we'll explore various methods for creating an expandable list view in SwiftUI, starting with the standard use of the List modifier, followed by built-in expandable components: OutlineGroup and DisclosureGroup.

Important: Ensure your simulator or device is running iOS 14 or later to utilize these features.

Chapter 2: Building the Data Model

Before we can implement the expandable list, we need to establish a data model. Start by defining the model with the following code:

struct SFMenu: Identifiable {

var id = UUID()

var name: String

var sfSymbol: String

var subMenuItems: [SFMenu]?

// List Items

static let iPhone = SFMenu(name: "iPhone", sfSymbol: "iphone")

static let keyboard = SFMenu(name: "Keyboard", sfSymbol: "keyboard")

static let mouse = SFMenu(name: "Magicmouse", sfSymbol: "magicmouse")

static let person = SFMenu(name: "Person", sfSymbol: "person")

static let faceSmiling = SFMenu(name: "Smiling", sfSymbol: "face.smiling")

static let cross = SFMenu(name: "Cross", sfSymbol: "cross")

static let faceMask = SFMenu(name: "Face Mask", sfSymbol: "facemask.fill")

// Grouping Items

static let devices = SFMenu(name: "Devices", sfSymbol: "display", subMenuItems: [

.iPhone, .keyboard, .mouse

])

static let human = SFMenu(name: "Human", sfSymbol: "person.crop.circle", subMenuItems: [

.person, .faceSmiling

])

static let health = SFMenu(name: "Health", sfSymbol: "heart", subMenuItems: [

.cross, .faceMask

])

}

Code structure for SFMenu in SwiftUI

To ensure that each item is uniquely identifiable, the model must include a property of type UUID. This will simplify later integration into a List view. The static constants within the model represent the collections that will populate the expandable list, with comments indicating their intended positions.

Chapter 3: Creating the Expanding List

Now that we have our model set up, we can proceed to create the expandable list. Add the following property inside ContentView:

let items: [SFMenu] = [.devices, .human, .health]

This property holds an array of data that will serve as the expanding list. In the body, implement the List view as follows:

List(items, children: .subMenuItems) { row in

Image(systemName: row.sfSymbol)

Text(row.name)

}

This tutorial assumes you are already acquainted with how Lists function, so we will focus on the children parameter. This parameter enables the creation of a tree-structured data model, utilizing the subMenuItems from our previously defined model.

Run the application to see your expandable menu in action!

Screenshot of the expandable list in SwiftUI

The menu should expand and collapse when tapped.

Chapter 4: Implementing OutlineGroup

As an alternative, you can use the OutlineGroup modifier. Using the same model, include the following code in ContentView:

struct ContentView: View {

let items: [SFMenu] = [.devices, .human, .health]

var body: some View {

List {

OutlineGroup(items, children: .subMenuItems) { row in

Image(systemName: row.sfSymbol)

Text(row.name)

}

}

}

}

The syntax remains largely the same, producing a similar outcome. The decision between OutlineGroup and List comes down to personal preference or the complexity of your code.

Chapter 5: Exploring DisclosureGroup

The DisclosureGroup is inherently included in the OutlineGroup. Utilizing it independently grants you control over the disclosure state, allowing you to programmatically manage the expansion and collapse of the view. Below is an example of how DisclosureGroup functions:

struct ContentView: View {

var body: some View {

ZStack {

DisclosureGroup("This is the title") {

Text("Content 1")

Text("Content 2")

}

.padding()

}

}

}

When you run this code, you'll see the corresponding layout, which can be expanded by clicking the view.

Screenshot demonstrating DisclosureGroup functionality

To set it to expand by default, create a boolean state variable initialized to true and bind it to the isExpanded parameter:

struct ContentView: View {

@State var isExpanded: Bool = true

var body: some View {

ZStack {

DisclosureGroup("This is the title", isExpanded: $isExpanded) {

Text("Content 1")

Text("Content 2")

}

.padding()

}

}

}

After running the application again, notice that it expands by default.

Chapter 6: Customizing the Appearance

Let's enhance the appearance of the DisclosureGroup. By the end of this chapter, you will have a customized expandable view.

To modify the appearance of the DisclosureGroup, follow this syntax:

DisclosureGroup(

content: {

// Customize your items here.

},

label: {

// Customize the title's appearance here.

}

)

Using the same data model from earlier, add a property inside ContentView:

let items: [SFMenu] = [.devices, .human, .health]

In the body, implement ForEach to avoid redundancy in your code, embedding the DisclosureGroup within it:

var body: some View {

VStack {

ForEach(items, id: .id) { name in

DisclosureGroup(

content: {

// Add content here

},

label: {

// Add label customization here

}

)

.padding()

.border(.black, width: 1)

.accentColor(.black)

}

}

.padding()

}

To clarify the label section, modify it as follows:

label: {

HStack {

Text(name.name)

.foregroundColor(.black)

Spacer()

}

}

While the views will not expand upon tapping since they currently lack content, we can employ ForEach under the content parameter to add details:

content: {

ForEach(name.subMenuItems!, id: .id) { row in

HStack {

Image(systemName: row.sfSymbol)

Spacer()

Text(row.name)

Spacer()

}

.padding()

}

},

By doing this, you break down the name.subMenuItems, extracting both the name and sfSymbol.

Now, your ContentView code is complete, and you can run the application to interact with the views.

Source code screenshot for customizable DisclosureGroup

Congratulations on reaching this point! You can find the source code for this tutorial on GitHub.

May the code be with you,

  • Arc

This video, "How to create expanding lists – SwiftUI," provides a visual demonstration of the concepts discussed in this tutorial.

The second video, "Expandable List in SwiftUI," offers further insights into creating expandable lists using SwiftUI.

Share the page:

Twitter Facebook Reddit LinkIn

-----------------------

Recent Post:

Affordable Business Ventures for Future Entrepreneurs

Explore ten budget-friendly business ideas that aspiring entrepreneurs can start with minimal investment.

Essential Python Packages for Dataset Acquisition in Data Science

Discover key Python packages for obtaining datasets to enhance your data science projects and portfolio.

Unlocking Earnings on Medium Without Constant Writing

Discover how to earn on Medium without writing constantly. Explore membership referrals and email subscriptions for passive income.

Elevate Your Dad Bod: Style Tips for a Better T-Shirt Look

Discover how to enhance your look in t-shirts with practical tips on diet, exercise, and style.

The Hidden Truth About Writing for a Living: A Cautionary Tale

A realistic perspective on writing as a career and the financial challenges that come with it.

The Complexity of Disposition Discourse in Modern Society

An exploration of how we discuss mental dispositions and the implications of these conversations in contemporary society.

Mastering Public Speaking: Strategies for Engaging Presentations

Discover innovative techniques for effective public speaking, including insights from Oren Klaff's

Embracing Imperfection: The Truth About Mental Health

Discover the truth about mental health and the importance of self-acceptance rather than striving for perfection.