Our experience using MotionLayout in NFC payments

At Mercado Libre we are in continuous beta. This cultural principle is reflected in our NFC payments, where we explore a new Android component to create a unique experience.

Rodrigo Dominguez
Mercado Libre Tech
Published in
9 min readNov 26, 2021

--

Read the story in Spanish.

Let’s take it from the starting point of the Android Devs of the team in charge of the NFC (Near Field Communication) payment experience at Mercado Pago.

The experience we have created together with the UX team.

This video shows the complete proposal of the NFC payment flow brought to us by the UX team.

Full flow of the NFC payment experience for Brazil.

As Android Devs, when we saw this animation, several questions popped up in our minds:

How do we do this? 😅
— I don’t know, Rick!

Has anybody here at Mercado Libre done something like this? 🤔
— No

UXers, could it be made simpler? 🥺
— Hmm.. no.

After the first questions, some others came up, more technical ones…

What component can we use?
— MotionLayout by Rodrigo Domínguez. You may know me from my contributions in ConstraintLayout and some talks about MotionLayout 1, talk 2 and talk 3.

Is there anything native to help us create this experience?
— MotionLayout, MotionLayout (IT Team)

Could we create this experience with ObjectAnimator, ValueAnimator, etc.?
— No, MotionLayout, MotionLayout, MotionLayout (IT Team)

Can animations with ConstraintLayout help us?
— Maybe, but MotionLayout, MotionLayout, MotionLayout (IT Team)

At Mercado Libre we already use Lottie which gives us a common Developer Experience for both platforms. What would happen if we used it?
— With Lottie we would not be able to have dynamic label information, we would not be able to manage the states of our transitions and user interactions with the animation.

OK, Rodri. But what is MotionLayout?
—It’s a new Android component for animating widgets between different states. Just what we need. 😁

Estado A _____________________________________________ Estado B

Transición

In our experience, we use the states as shown below...

Estado A _____________________________________________ Estado B

Transición

More challenges in the experience

Our payment experience requires a first tap with the POS Terminal to initiate communication via NFC; then a second tap to confirm the transaction.

In addition, it allows for a single-tap payment. Once the payment process is completed, information about the successful transaction must be displayed. In other words, in this flow, the transitions of the second tap are not shown. That would require our animation to travel from state A to state D, without going through states B and C.

In the following example, we can see how with a single tap we approved a transaction (state B), but since we did not have internet, we showed state D at the end of the animation.

Likewise, being able to open our flow from anywhere in the application with the first tap implied different entry points and different animation states.

Another challenge was providing support to offline payments, and through the animation, communicating the success of the payment but with different transitions.
Because of all these different entry points, offline payments and one or two taps to pay successfully, we understood that Lottie would not be able to support different states and communicate back to the user the beginning and end of a transition.

MotionLayout provided us with “listeners” to know the status of our transitions, to start a new transition, to restart it and to set the progress.
Having all the cards laid out on the table, we concluded that MotionLayout was the best option for the whole NFC payment experience. Now..

What changes would be necessary to make this component available for all Mercado Libre devices??

We will now explore how we update our third-party libraries within Mercado Libre. To this purpose, MotionLayout is a component included in the latest version of the ConstraintLayout library.

ConstraintLayout Update

Updating our libraries is not simply modifying a version of Gradle dependencies, building, and compiling. At Mercado Libre, dozens of teams and hundreds of developers work with the Android platform. All third-party libraries, together with their respective versions, are centralized and on an allowlist.Therefore, we avoid version chaos, unnecessary libraries, and all the problems that could come up when having different versions in different modules.

At the time we started creating the NFC experience, we were using ConstraintLayout version 1.1.3. In order to use MotionLayout, we needed to upgrade the former to version 2.0.

This is how we upgrade our dependencies within Mercado Libre and how we communicate to all our teams about the different updates in our App libraries. It is the responsibility of each team to test and update their project to upload onto the appropriate release train 🚃.

Building our animation for NFC payment

After updating our ConstraintLayout version to 2.0, we have to build our complete experience step by step. Here’s how.

Before starting, let’s make this clear: in MotionLayout, each state is called ConstraintSet and groups the different constraints and attributes of our views. From here on, we will call each ConstraintSet “state” (stateA, stateB, etc.) and we will represent the transition from one constraintSet to another one as stateA -> stateB..

Transition 1: Preparing our animation before the first tap

In our stateA, we see that the POS image (left image) and the cell phone image (right image) are at the sides of our screen. In stateB, both images are moved to the center of our screen indicating the end of transition 1 (stateA -> stateB). At this point, we will ask the user to bring the mobile phone close to the POS for the first communication.

Transition 2: Ready for the first tap

After finishing transition 1, our payments flow must tell the user to bring his cell phone close to the POS terminal. This is the point when we use one of the advantages that MotionLayout gives us: that of being able to execute the transitions whenever we want to. Then, at the end of our transition 1, we automatically execute transition 2 (stateB -> stateC).

Transition 3: Waiting for communication with the POS

At the end of transition 2, we must wait for the user to bring the mobile phone close to the POS and achieve a successful communication so that payment can be executed (here we move from stateC -> stateD).

While waiting, we must show a circular effect on our main card as follows:

This is when another question comes up:

Could we use Lottie for some parts of the experience?

Yes, we had no problem mixing Lottie with MotionLayout for static animations such as the blue circles when waiting for the communication with the POS in our Transition 3.

Another moment of the experience in which we took advantage of the synergy of these 2 tools (Lottie + MotionLayout) was when making a successful payment:

And for an offline payment from which we cannot get any transaction information, we also make use of Lottie animation visibility and play:

Let’s continue with our full animation…

Transition 4: Communicating a successful POS connection message

In this animation, we must let the user know that we have successfully connected the mobile phone to the POS. To do so, we move from our current stateD to our stateE by simply changing the visibility of some texts and hiding the circles, i.e., Lottie animation. In our Android Studio viewer, Lottie animations cannot be played.

Transition 5: Communicating that the payment was successful

In this animation, we must tell the user that the payment was successful. After the second tap with the POS (we move from stateE -> stateF), we change the visibility of some texts and show our green Lottie circles, as mentioned above. We also give visibility to a Lottie animation.

Transition 6: Showing payment information

Once the operation is successful, we must wait for the payment information from our backend. In case we do not have internet, we switch to stateH to communicate the end of the transaction. If we do have internet and get the transaction information, we must switch to stateG.

Transition 7: Showing successful payment information

This is the last transition of our experience. Here we show the information of our successful transaction (we have moved from StateI). We now change the position of our main card and show the view block that contains all the information of the transaction.

To generate motion effect in our main card and to let the listeners know when a transition ends, we have used the full potential of MotionLayout from its multiple KeyFrames states. In this way, we managed to replicate the animation proposed by our UX team quite accurately.

Lessons learned

  1. MotionLayout gives us the potential to create animations that are very difficult to achieve with other tools.
  2. Having more than 5 states, we must take into account the following considerations:
  • Handling of the ongoing transition state.
  • XML size (motionScene).

Having multiple XML transitions makes the reading more complex. As a result, it is also more complex to maintain and more prone to errors.

  • Clear names for the different ConstraintSets.

3. Use MotionLayout when the user interacts with the animation..

4. Do not mix the handling of your own animations (e.g., visibility, rotation, scale, etc.) with those of MotionLayout..

When trying to change the same attributes from the code, and also from the MotionLayout states, we noticed unexpected behaviors. For example, if we wanted to change the visibility of some views by code and also handle it from MotionLayout, when switching from one state to another one, the visibility was not executed as we had expected.

5. Use linear navigation between transitions

stateA -> stateB, stateB -> stateC ✅
stateA -> stateC ❌

The transition from stateA -> StateC without passing through StateB has shown unexpected behaviors. When our views travel from stateA -> stateB, both states know the initial and final attributes of all the views we have declared in both states. But when performing a stateA -> stateC, some views in one of our states may not have been declared and the transitions generated may differ from the expected ones.

6. It is possible to use MotionLayout and Lottie together without any problems.

Production experience 🚀

After an intensive internal testing, iterations, and many mocked payments, the feature was released in Brazil during 2021 Q1.

We are proud to see how NFC payments can be successfully made on the subway in Rio de Janeiro, Brazil.

NFC payment in the subway of Rio de Janeiro, Brazil

In a video, we show a real test of NFC payment at POS

NFC payment at POS in Brazil.

… How about you? What was your experience using MotionLayout? Would you like to share it in the comments?

--

--

Rodrigo Dominguez
Mercado Libre Tech

Android Tech Lead @ Uala | Previously MercadoLibre, Despegar, Kavak.com