In part one of this 3-part series, you’ll learn how to prototype different elements of the user interface for Stream’s iOS Chat SDK using SwiftUI.
•about 1 month ago
This tutorial will focus on designing the elements that make up the ChannelListView and ChatsView components. In parts two and three, you’ll build on these components by adding interactions and animations, creating a more seamless chat experience.
You can download the Xcode project containing the SwiftUI source code from GitHub to follow along.
The project contains a ZIP file with several Swift files and folders for the layouts, interactions, and animations for this project. Additionally, you will use SF Symbols 3 as icons for the project. You can find all other assets, such as images and custom icons, in the Xcode assets folder.
Before getting started, download the latest version of Xcode (this tutorial uses v13.0). If you haven’t installed Xcode, download it at Xcode 13 (recommended) or download it from the App Store:
- Launch the Mac App Store.
- Search for Xcode. If you haven’t installed it, you will see a DOWNLOAD button instead of an UPDATE button.
- After downloading Xcode, move it to the Applications folder and follow the instructions to install.
Once you've installed Xcode, you're ready to create a project!
Want to integrate SwiftUI into your project? Check out our new SwiftUI SDK to get started.
Create a New Xcode (SwiftUI) Project
To create a project, launch Xcode:
- From the welcome screen, select Create a new Xcode project.
- In the Application window, select App and then Next.
- Enter the Project Name, then select Next.
- Select a location on your computer where you want to store the project files, then click Create.
After creating the Xcode project and adding your new folders and files, the folder and files structure should look similar to the image below.
In Xcode, you can use new files and folders to organize sections of your designs or compositions in the same way you use groups and layers in design tools.
To add a new file or folder to your project:
- Press Control on the keyboard and click the project folder.
- Then, select New File or New Group.
In the image below, you can see several folders and files have been added to the project to organize various sections of the app screens.
Creating the Navigation Bars and Compose Area
The following sections will show you how to design the header at the top of the screen (HeaderView), a compose area where users can input messages before sending (ComposeAreaView), and the tab bar at the bottom of the screen (TabBarView).
Create the Header View
SwiftUI is a declarative language, which means you describe what and how the interface should be. Then, the SwiftUI system presents the visual representation of what you’ve described.
To create your HeaderView, create a new Swift file HeaderView by right-clicking the folder ChannelList and selecting New File....
Then, enter the code below:
In this snippet, you’re telling SwiftUI to present a horizontal parent container (HStack) consisting of an Image on the left, Text in the middle, a space between the content (Spacer), and another Image on the right.
By resuming the Xcode preview, you will see the following header image:
Note: You can find the hamburger and start conversation icons in the assets folder. You may also upload your own icons to the Xcode assets folder and use them.
Create the Compose Area
The compose area is made up of a TextField, which allows users to input a message. It also has attachment and send buttons.
To create the compose area, create a file called ComposeAreaView and add the following code:
In this snippet, you:
- Define the color constant composeAreaBackgroud and, as the variable implies, use it for the background of the compose area.
- Define the constant darkDisabled for the background of the send button when the text field is empty.
- Define the state variable composeText and use it as a value for the text parameter of the textField, which will display a placeholder text in the text field.
- Create the paper clip, lightning, and send (arrow) icons as buttons using San Francisco Symbols (SF), and use a horizontal container to arrange them.
Create the Tab Bar
The tab bar appears at the bottom of the screen and allows users to switch between pages within the application.
To create the tab bar, add a new Swift file called TabBarView and enter the following code:
In this snippet, you create the tab bar by embedding two tab items (
”Mentions”) in a
TabView. Because the tab bar allows you to switch between pages, you need to define the page where each tab item should point to.
From the code, you can see the tab items point to the same page,
MentionsView. This is intentional, but in your application, you could point the
Chats button to a chats page and the
@) button to the
To attach a tab item to a page, use the
.tabItem modifier. In each tab item, add a
Label consisting of the text (for example, “Chats”) and an image (SF Symbol).
The tab bar also displays two badges on the top right of each tab item with a notification count. To create the badges, add the
.badge modifier and indicate the badge value.
Note: The badge modifier is only available in iOS 15. After adding the badge modifier to the code, you’ll get an error. To resolve the error, click the error button when it appears. This will add the 'if #available' version check to the code as shown below.
Creating the Channel List
The channel list view has four main sections:
The ChannelListView shows a list of messages containing the user’s avatar, name, message summary, status, timestamp, message count, and delivery receipt.
To create the ChannelListView, you need data. You can find the data for this project in the file ChannelListData.swift (located in this interaction prototyping GitHub.
Create Your Data Source
To get the user data, create a new file and copy the content of ChannelListData.swift to it. Or, you can define the structure of the data and the fields you want to display in the file as seen in the code below:
In the code above, there is only one user under
ChannelData . You can find the complete list of users in the file ChannelListData after downloading the project file.
Add a Scrollable List (ChannelListView)
To build your scrollable list, create a new Swift file called ChannelListView.swift and populate it with the data source you created in the file ChannelListData.swift.
Then, add the code in the snippet below:
Here’s what’s going on this snippet:
- In ChannelListView.swift, you define the color styles you want to use for UI elements (like
- Since the messages will be pulled from a data source, you create a variable called
messagesand set it as an empty array.. Then, create an empty
- Inside the
List, you use an
HStackto arrange the list items horizontally.
- Then, you retrieve the
userStatusdefined in the ChannelListData.swift file and place them in a depth stack (
ZStack) so that the status shows on the top-right of the avatar.
- Next, you add a vertical container (
VStack) in the list and place the
- You add another
HStackto arrange the
- Then, you embed this horizontal container in a vertical container and place the
unreadMessageCounton the content.
- For the content in the top-level
HStack, you use a
Spacer()to push it to the left and right edges of the screen.
To learn more about how to retrieve data from another Swift file to populate a list in SwiftUI, watch Apple’s Introduction to SwiftUI.
Combining Header, Search Bar, Channel List, and Tab Bar
To put it all together, embed the scrollable list created in ChannelListView.swift in a vertical container VStack. This will serve as the main layout container for the four sections of the screen: your header, search bar, list, and tab bar.
In the main vertical container, add the header HeaderView() and search bar CustomSearchBarView(), which are contained in another Swift file above the list.
Finally, add the TabBarView(), which is also contained in another Swift file, so that it appears at the bottom of the screen.
Designing Inbound and Outbound Messages
This section shows you how to build the composition of incoming and outgoing messages with the user's avatar, message bubbles, text, timestamp, emojis, and delivery status.
Creating an Inbound Message
Create a new file called InboundSingleLineView.swift and add the following code:
In this snippet, you pull the user’s avatar from the assets folder, adding the user’s name, text on the message bubble, and the timestamp:
- Begin by defining the chat bubble color as
inboundBubbleColorusing color literal and stating the red, green, and blue color values.
- Next, draw a rectangle for the chat bubble and place a text on the rectangle using the
- Embed the chat bubble with the text in a
VStacklayout container and add the text
Space Cadet 9.01 AMbelow the bubble.
- Align the
Space Cadet 9.01 AMand the bubble to the left using the alignment parameter of the VStack and set its value to
- Finally, put the
VStackinside an HStack` and add the user avatar to the left.
- In the horizontal layout container, set the alignment parameter to
.bottomso that the avatar appears at the bottom left of the message bubble and the text below it.
Creating an Outbound Message
Next, you will create an outbound message by embedding text, a message bubble, and emojis using stack views, vertical stack (VStack), horizontal stack (HStack), and depth stack (ZStack) in a new Swift file called OutboundSingleLineView.swift.
To create an outbound message, add the following code:
When you preview your code, Xcode will present the composition as seen in the image below:
You can see the rectangle has three rounded corners and the bottom right corner is straight.
To give your outbound messages this visual effect:
- Place the rounded rectangle (bubble) in a
- Then, draw another small rectangle with a width of 20 and a height of 21 above the bubble.
- Set the alignment parameter of the
.bottomTrailingso that the small rectangle appears at the bottom right of the bubble to form a straight edge.
- Next, add the emojis using text and place them in front of the bubble with the
.overlaymodifier. You can use the
ZStackin SwiftUI to put an element in front of another.
- Create a horizontal container
HStackand place the
readReceptimage and the timestamp as text inside the
- Finally, put all the content in a
VStackso that it becomes the root container for all the message views and use the alignment parameter to align the content to the right by setting the value as
Building the Message List in ChatsView
The ChatsView screen has three main sections: MessageListHeader(), ScrollView(), and ComposeAreaView(). It is laid out by composing inbound and outbound messages created in the previous sections as well as other message components found in the folders below.
To get started, download the project file and create a new Swift file called
ChatsView file created, add the following code:
In this snippet, you bring the inbound and outbound messages together onto one screen.
Here’s a walkthrough of the steps:
- Begin by creating the root
VStack, which you will use to arrange the
ScrollView, and the
- In the root
VStack, add the
- Between the header and the compose area, add a
ScrollView, which enables scroll functionality.
- Inside the
ScrollView, add a
VStackas a root layout container.
- Add horizontal containers
HStackin the root vertical container to arrange the inbound and outbound messages.
- In the top
InboundMessageView()and place a spacer below it so that it pushes the content to the left of the screen.
- Next, add another
OutboundSingleLineView()in it. By adding a spacer below
OutboundSingleLineView(), the content will be pushed to the right edge of the screen.
Repeat the above steps to bring as many inbound and outbound messages to the scrollable section as possible.
Well done. This tutorial covered how to design the main screens and chats view of the Stream iOS Chat SDK using SwiftUI.
You also learned how to create child or sub-views (like inbound and outbound messages) as components by creating them in new files in Xcode.
You can download the SwiftUI source code for this project as a zip file from GitHub. In part two of this tutorial, you will use the designs you created in part one to design interactions and micro-interactions for the iOS Chat SDK.