Native Experiences in Cross-Platform Apps
Our Friend Mix music profile builder is a good example of how a cross-platform approach to app building can still play to an individual platform’s strengths.
As well as building apps for clients, we’ve published our own apps to showcase some Audiogum features. Alongside Gumbot - our voice playlist maker, we recently released Friend Mix on Android and iOS. Friend Mix creates playlists based on multiple people’s music tastes to make sure you get the right blend of tracks for a party or social event.
The music profile builder
One of the key parts of the Friend Mix experience is the music profile builder where each user can indicate what kind of music they like. It's a good example of how a feature can differ between platforms even in a cross-platform app. Although the app is built using Xamarin to allow us to share code, it doesn’t stop us from playing to a platform’s strengths and creating a different experience on different target devices.
After choosing their favourite music genres, users are presented with a range of artists in those genres. Each time they select an artist, recommendations of similar artists appear alongside. Having completed their choices, we have a music profile for each user that we can use to create a combined playlist.
On Android, we use a RecyclerView with horizontal layout, presenting the artists in rows. As artists are selected, new artist recommendations come in as a new column:
On iOS, we decided to try something different and made use of SpriteKit to create a SpriteKit Scene of profile bubbles. We set boundaries on the scene and define the SKPhysicsBody for each element. The recommendations pop in depending on how much space is available around the selected item and SpriteKit takes care of the interactions between bubbles as they jostle for position on the screen.
So with two different solutions for the same feature, in what way is this cross-platform? Previously, I’ve talked about how we use MVVM in our Xamarin apps and bind native views directly to shared ViewModels.
This case is no different. From the ViewModel’s point of view, most of the behaviour is identical. The ViewModel presents a collection of artists from the chosen genres, keeps track of which ones have been selected, and on each new selection it updates the artist list with new recommendations.
The view binds to the artist collection in whichever form it chooses, highlights selected items, triggers the relevant ViewModel command when artists are selected and reacts to recommendations being added to the list. ViewModel tests exercise the ViewModel in the same way.
The only difference between the two implementations in terms of ViewModel behaviour is around how the recommendations are added to the list. Android requires the entire next column to be populated with new recommended artists. On iOS, the number of new artists added depends on how close the selected artist is to the edge of the screen.
ViewModels are view agnostic in MVVM. The ViewModel doesn't know or care which front end it serves, be that Android, iOS, an automated test case or some other platform in future. As part of its interface, this ViewModel offers up a delegate, which views can implement to dictate how many new artists should be inserted and where:
Great experiences in their own right
A key challenge of cross-platform development is to achieve the productivity gains of shared code without losing the flexibility to make a great native app on each platform. By making the best of what the native APIs offer, each version of your app can be a great experience in its own right.
Which version of the profile builder do you prefer? Try Friend Mix and let us know what you think.