Behind The SSENSE App Homepage: Building A Dynamic UICollectionView Layout System

Heng Wang
SSENSE-TECH
Published in
6 min readNov 7, 2019

When you open the SSENSE app, the first page to greet you is the gorgeous homepage with its dynamic layouts, full of hyper-personalized products.

The homepage is divided into multiple sections with a horizontal scroll, with each section containing various sizes of product images. Additionally, based on the screen dimensions of the device, the image size will automatically be optimized to provide the best visual quality.

In this article, I will take you through how we created the SSENSE app homepage from three aspects: Design, Implementation, and Customization.

Design

When our Mobile App Dev team received the final version of the SSENSE app design from our UI/UX experts, we needed to abstract the design into wireframes. This would help us extract the similarities within the page, so that we could break the view into different components. Let’s call them Widgets.

Thanks to our amazing Product Design team, who designed all widgets in a manner that each page would just be a combination of multiple widgets, we were able to follow a template wherein the homepage would comprise of a title and a content section, and the content section would conform to one of two types:

  • A dynamic list of top 7 personalized brands displayed in large typography
  • A horizontal scrollable view containing multiple products.

Products inside this view could be displayed in various layouts. For example, one row with three and half visible products including brand names and prices, or a higher density format like three rows with five and half visible products, each with just the image.

Implementation

Building the UI

A well-known saying in iOS UI development is:

There is nothing you cannot solve with one UITableView, if there is, use two.

UITableView provides us the flexibility of displaying different types of data in a scrollable view while maintaining the high performance. Therefore, a UITableView with each section containing one widget would be a good starting point to encapsulate all widgets.

Back to our initial thought of types of content, here is what we could use from UIKit to build the widgets.

  • A list of brands in large typography (Brand widget)

We could use the normal UITableViewCell to display the designer list. We provided the data source of designer names to this section so that it could dynamically display the list.

  • A horizontal scrollable view containing multiple products (Product widget)

For the horizontal scrollable view, we would naturally think of UICollectionView. Apple refers to the UICollectionView as “an object that manages an ordered collection of data items and presents them using customizable layouts”. This gives us the ability to design our own item format, as well as the layout, and whether we want to display it in one or multiple rows.

Here is our initial draft for the UITableView layout with different widgets:

The next big question was how could we make the UICollectionView layout dynamic while maintaining a unified format across all possible iPhone screen sizes?

The Formula

One of our displaying rules is to show a unified format for the product widget regardless of the screen size. This means that if one of the widgets is to show three and half products on the screen, the visual format should be applied to all screen sizes from iPhone SE to iPhone 11 Pro Max.

In order to achieve this, we needed to do some math.

The box of dashed lines represents the visible UICollectionView on the screen, embedded inside a UITableViewCell, and the rectangles inside it represent one UICollectionViewCell. Therefore, we arrived at the following equation, note that N is the only variable here:

From the equation, we could easily deduce value of w and h:

Once we calculate the size of an item in the UICollectionView, we use it to determine the height constraint for the widget based on the number of rows (R) we want to display in each widget.

if R == 1:    return helse:    return (h + SR) * R — SR

The UICollectionView will automatically rearrange the items to the number of rows desired based on the WidgetHeightConstraint.

Putting It All Together

One of our conventions for building the UI is to try to build reusable components whenever possible. Therefore, we have defined components for multiple layouts based on the requirements at the UICollectionViewCell level.

We are using Roman numerals as a suffix to represent the possible layout types.

XL  = 1.5 visible product card on screenL   = 2.5 visible product card on screenM   = 3.5 visible product card on screenS   = 4.5 visible product card on screenXS  = 5.5 visible product card on screenXXS = 6.5 visible product card on screen

HomeWidgetType

At the code level, we defined an enum with various layout types as its associated values.

HomeWidgetProductCell

If the section is a product widget, it calculates the item size of the collection view cell and return the corresponding cell type.

HomeViewController

The UIViewController level decides whether the section should be a list of brands or a collection view of products.

Customization

At this point, our homepage is able to handle various scenarios in terms of widget layouts and is fully controlled by our back-end.

While we are using a REST API to communicate between the back-end and the front-end, the back-end will pass the layout type for each homepage section in its payload.

"homeWidgets": [  {    "title": "NEW FROM",    "layout": "HomeWidgetBrand",    ...  },  {    "title": "RECOMMENDED STYLES",    "layout": "HomeWidgetProductM",    ...  },  {    "title": "TRENDING",    "layout": "HomeWidgetProductX",    ...  },  {    "title": "SSENSE EXCLUSIVE",    "layout": "HomeWidgetProductXXS",    ...  }]

The payload serves as the data source for the UITableView in the homepage. The UITableView determines the layout of each section based on the layout provided by the data source.

Conclusion

To summarize, we first find similarities within the design and break it into multiple reusable components. We then use a combination of UITableView and UICollectionView to lay the foundation of the view structure. Finally, we use Enums to define various layout types, which would be received from the back-end, and then determine the layout to be used on the front-end.

A rule of thumb of iOS UI development at SSENSE is to modularize design into reusable components so that we can standardize the visual design across the app and maximize development productivity. Experience the dynamic UICollectionView layout system for yourself by downloading the SSENSE app here.

Diagrams by Max Kaplun.

Editorial reviews by Deanna Chow, Liela Touré & Prateek Sanyal.

Want to work with us? Click here to see all open positions at SSENSE!

--

--