Open Sourcing our Day View UI Library for Making Meetings Easier
March 21, 2019
Our members leverage LinkedIn Messenger for a number of use cases, and oftentimes a scheduling component is an important piece of the interaction. A few examples include:
A student who wants to schedule time to chat with a graduate from his or her school for career advice.
A freelancer who needs to schedule a call with a potential customer.
A job seeker who wants to set up a meeting with an employee at a company to talk about a job opportunity.
Unfortunately, there’s often a ton of friction involved in selecting dates and times. You might have to open a separate calendar application on your device to check your availability, and there’s a fair amount of copy and pasting involved when composing the subsequent message. To simplify this process, we implemented a way for you to easily share your availability with your 1st degree connections in LinkedIn Messenger. Now, in the LinkedIn Android app (iOS coming soon), you can view your calendar and select available time slots you’d like to share in a message. Please see more details on this feature in our member blog post here. For more on how this works, please see the short video below:
To implement this, we needed a calendar day view that supported event rendering. Nothing like this exists in the iOS and Android SDKs, so we turned to the open source world.
Open source libraries
At first, we thought there'd probably be an open source library we could drop into our codebase. It turns out, however, that none of the calendar-related open source libraries for iOS or Android met our needs. The libraries fell into one of two categories:
- Full-featured calendar apps
- Simple calendar views
The libraries in the first category proved to be too complex for what we wanted. For example, it was clear we couldn’t feasibly extract the day view rendering logic from the rest of the code base. Some of the libraries in the latter category came close to what we were looking for, but there was a big problem: none of the libraries included an algorithm for handling conflicting events. Instead, they either stacked conflicting events on top of each other or displayed the events in a singular list.
To illustrate this problem, consider the following example: You have three events that occur between 1 and 3 a.m. We want them to occupy equal-width columns side-by-side, so each event can be seen clearly.
The libraries in the first category could of course handle this as they were full calendar apps, but we knew that only the libraries of the simple calendar view category would be feasible in integrating with our app. So, we concluded the optimal member experience could only be achieved by writing our own library.
But if we were going to write our own library, the next question was, how do we get the most use out of it? At that point, we realized we could help other developers avoid the exact issues we had faced by open sourcing our library!
We had a few core design goals in mind when developing the custom display logic. First was the rendering performance. Since our day view was going to have to display N events per day, we realized early on that support for view recycling would be critical. We kept the recycling logic simple by only recycling event views between days, so each individual day still requires N views to be created or reclaimed from other days. But our aim was to ensure that the swiping between days was smooth, and this sort of view recycling helped.
After implementing view recycling, we noticed the scrolling performance still wasn’t good enough. Luckily, we found an easy fix by adjusting the hour and half-hour dividers. Originally, each divider was its own view, but dividers are really just simple lines that can be rendered directly to the canvas. Switching over to direct rendering brought our scrolling performance up to the standard of smoothness we expected.
Another core design goal was internationalization. To support multiple languages, we made sure that all of the text we displayed used a generic formatter that didn’t assume the language was English. A hard issue to tackle here was how to lay out the views for RTL (right-to-left) languages. To prevent RTL mode from drastically increasing the complexity of our layout logic, we implemented a simple translation layer that processes all layout geometry in the day view. When RTL mode is detected, the horizontal coordinates of the child views are flipped and shifted by this translation layer.
Our implementations in the day view are different between iOS and Android. Even though the design goals were consistent, each platform posed a different set of questions we needed to answer.
On iOS, we had to choose between Swift and Objective-C for our programming language. We picked Objective-C for our programming language for the following reasons:
Reduction of binary size
Better interoperability with our existing Objective-C projects
Faster autocomplete in XCode
Another question on iOS was how we would format dates and times. Internally, we used the NSDate object to manipulate timestamps. To format the timestamps into localized text, we created a custom pipeline using NSLocale and NSCalendar objects. This allowed us to support over twenty different languages and locales.
Switching over to Android, the main question was around which SDK versions we would support. One positive aspect of creating a custom view is how isolated the logic can be from the rest of the app. Although we originally developed the day view internally within the LinkedIn Android app, we realized it could support a lower SDK version than the LinkedIn app does. Our app supports Android SDK version 21 and higher, but our library supports everything back to version 14.
Our day view library is now live on GitHub for Android and is coming soon for iOS. We’d obviously welcome any contributions or feature requests for either platform, but one engineering principal we’re following is “Keep your project scope well defined!” As mentioned previously, there are already some great open source projects that provide a full featured calendar experience. Our library’s purpose is to provide a reliable and robust calendar day view.
Having said that, if there are any use cases within the project’s scope that we haven’t thought of yet, we’d love to hear them. To contribute to the project or to request a feature/bug fix, please visit our GitHub page.