This is the 3 part of a series of posts where we are trying to improve the ui and interaction with forms in Android. Part 2 introduced the FloatingHints library and showed how this simple pattern can make a big impact in your forms.
The source code for Part 2 is already available on Github.
On today’s post, we will introduce an easy way of dealing with transitions between forms and how to respond to orientation changes
The Form flow does not need to suck
It’s very common to see a welcome message when opening a form which is telling us a bit about the application or simply because someone decided that we are all still living in the early days of the internet. Don’t worry, we got you covered for that.
One of the most annoying things that may happen when navigation through a Login form is when pressing the Register button. I’ve seen things, and I’m sure you also have! A common example is to jump to a whole new Activity, the user is going to see that ugly change of context, the famous white background in the screen while the screens change or even worse… it may as well send the user to the Browser just because the application can’t handle registrations.
Wouldn’t it be nice if you could just have a nicer way of showing all the content?
There are several ways of animating views,
ViewSwitcher being the most used examples.
Before start using a
ViewPager and write adapters, fragments, etc… let’s understand what we are talking about here. This is more a personal
point of view than anything else but, I’m just not a big fun of building a castle when I only need a hut. Our form currently has two main goals,
Sign in and Register users, that’s 2 actions and bunch of
EditTextso let’s keep it simple.
We are going to create three different views, one for Register, one for the Welcome message and the last one for Signining in. We will
then use an animator to make the transitions from one view to another. As discussed earlier,
ViewPagercould be a solution
but I don’t see the need of using adapters and fragments for this purpose.
ViewSwitcheronly allows use to switch between two views so
the ideal candidate for this task is a
One thing though, we are not going to show one view after the other. Instead, we are going to switch between views with different animations by sliding the form left and right depending on the action that the user wants to take. Right, how do we do that?
As you can see, after showing the welcome message if the user wants to Register we’ll slide the form from the left and if the user wants
to Log in we will slide the form from the right. To do that, the
MultipleViewSwitcherneeds to add
some new functionality to what the
The first addition is that we need to be able to change the initial page of the view.
There are several ways of doing this but since we are extending
ViewAnimatorand I really like to use the
set this initial page as an attribute.
1 2 3
Our new view is now able to use this attribute and change the displayed page once it’s inflated. Note that this page change can’t be done
before the view is inflated since it has not computed yet all all it’s children nor added them to the
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
As you all know, the first view in the
ViewAnimatorhas the id 0 so we are going to set our initialPage as 1:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
Cool, now all the form is in place and our first page is the Welcome Message. Earlier we said that we wanted to animate the
transitions between forms, and that’s exactly what the
MultipleViewSwitcheris made for. Basically, there are two methods and attributes
that we are going to use in order to achieve this
As you’ve seen, the forms are not always sliding into the same direction but changing based on the current page. In order to achieve that we are also going to add some changes to the transition logic so this can be easily handled.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
The view allows us to set two Animations which we will use to animate the views accordingly. Looking into
the ViewAnimator implementation one can
see that it’s holding refference to both the In and the Out Animations, so there is no need for our new View to add more overhead to it.
It is our responsability though to keep an eye on how many Animations we are loading and how we do it. Same as the
can receive a new Animation by parameter or the resourceId of it which we will then load with
At this point we hace achieved all the goals of the wanted but there is a small annoying issue, when rotating the device we are not saving the
current displayed child
ViewAnimatordoes not do it either, so it would be the Activity/Fragment responsibility. I’d much rather have this solved
in the View so we are going to save the state of the View when rotation.
Saving the state of the view
Since our form is now composed by more than one view, it would be nice to save the displayed child on orientation changes. No one wants to move the device from portrait to landscape and realise that the form is now showing the initial page. This view is not just usable in forms, one can easily use it to handle the on boarding wizard of an application. Can you imagine how frustrated the user would be if after swiping through four screens, the device is rotated and the wizards needs to be completed from the beginning?
Parcelableto save the instance state). I’ve seen plenty of implementations
creating their own Parcelable, etc… but the easiest way in my opinion is using a Bundle (which implements Parcelable)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
When the device’s orientation changes, the view itself will save it’s instance state and restore the displayed child. It’s very important that the View has it’s own id defined
in the XML layout, if it doesn’t the
onRestoreInstanceState()won’t be called and state won’t be restored.
Show me the code
If this caught your attention, please check the source code for Part 3 already available on Github.
The next part will be last one and will add some love to the overall look and feel in addition to some interesting ideas about buttons and input keyboard handling.