The Android platform offers the ability to completely customise components that are not available in the prebuilt widgets and layouts or modify some existing components to meet our needs. However, making apps more accessible with complex UI requires some additional effort and sometimes nearly impossible. Fortunately, the Android team are continuously working to help us resolve some of these constraints by adding new classes and support libraries to the platform, such as
Disclaimer: This article assumes that you’re familiar with
MotionLayoutand Circular Positioning with
ConstraintsLayout. If not I recommend Introduction to MotionLayout (part I) by Nicolas Roard and ConstraintLayout: Circular Positioning by Andrew Kelly as a starting point.
Recently, I was assigned a task to create an onboarding flow with multiple screens for a client, to showcase a new feature in their Android app. Usually, I’d build such onboarding flow using a ViewPager and animates between these screens using transitions. But this time, I chose to build it with
MotionLayout after some reading and tutorials on
In this article, I’m going to take you through my journey of creating this onboarding flow with
The Onboarding Flow
The onboarding flow(see gif below) comprises of three screens with two control buttons and a progress dot indicator. Each screen incorporates details about that specific screen, encased in a bubble background.
Navigating to the next or previous screen animates to the next or previous screen respectively along with the progress indicator getting updated. The details in the bubble are only visible when the bubble expands and obscure when shrinks.
Why using MotionLayout?
At a glance at the gif, using
MotionLayout may appear irrelevant to you, but allow me to elaborate. First of all, before
MotionLayout, I felt terrible at animations on Android, especially when dealing with custom views. I’d build it by creating a custom view along with the texts and images to a canvas.
Secondly, it is nearly impossible to get this right without callbacks in my animations implementation — probably, some more boilerplate code.
Finally, making these screens accessible isn’t going to be easy based on experience. I’d also need a custom
AccessibilityDelegate for my virtual views.
MotionLayout, I don’t need to worry about all these issues and allows me to focus on the main logic of the onboarding flow.
MotionLayout is a subclass of
ConstraintsLayout and helps with widgets animations. Moreover,
ConstraintsLayout already supports circular positioning and works as the solution used in this article.
The Onboarding Layout
Earlier, I stated that the onboarding comprises of three screens. Which sounds like I’d also need three separate layouts, but with
MotionLayout, it is possible to use a single layout for these screens using constraint set for each screen. Cool, right?
Furthermore, since the bubbles have different details for styling based on design specifications, one way of tackling this is to add all the views in our layout and then position them independently. This approach can result in one large layout file, which is challenging to maintain.
However, I favoured creating a new layout class, i.e.
OnboardingbubbleItemthat subclasses FrameLayout.
OnboardingbubbleItem inflates a view of the bubble, i.e. layout_bubble_item.xml. I strongly recommend this approach as customising is more straightforward with custom attributes and
MotionLayout now treats these views as its direct children.
OnboardingbubbleItem is then circularly constrained from a centre point widget centerPointPlaceholder at a given distance and radius for both expand and obscure details states in the onboarding_motion_layout.xml and the constraint set transitions in onboarding_scene.xml
Animating the screens
MotionScene, a separate file containing the animation specifications needed to transition from the start-position to the end-position of our screen.
But, since the onboarding contains more than two screens and I’d need more than two transitions for the onboarding flow to work. In other words, I’d need to transition from one state to the other. I choose to do this by code since handling these transitions in the
MotionScene file along with the progress indicator, and button state is very tricky in my opinion. However, if you have a better approach, please share in the comment section below.
As mentioned earlier, transitioning between the next and previous screen is accomplished programmatically in the
Fragmentthat hosts the onboarding flow. Notices how the extension function
navigate is implemented. It updates the progress indicator and buttons states and sets the transition between the start and end constraint sets. Then animates to the ending position with
That’s all. Now you know how I built an onboarding flow with
MotionLayout. The full sample is available on Github.
Lastly, I reached out to Nicolas Roard from the
ConstraintsLayout team at Google for help and tipped me on how to make this onboarding work with less code. So stay tuned for part two of this article. See you soon!
Thank you for reading. I’d love to hear your feedback, so please leave me a comment below.
Ernest is an Android professional, with experience in developing and maintaining high quality scalable Android applications. Ernest is currently working as a Senior Android consultant at DNB(MinBank) via Shortcut, previously EVRY (Digital banking services) and Zedge Inc. Ernest enjoys taking photos and playing soccer with his kids when he is not co-organising meetups for his local developer community.
This post was originally posted on Ernests blog on Medium.