How We Improved Virtual Gifting Experience in Audio Chatroom

Tech @ ShareChat
ShareChat TechByte
Published in
8 min readDec 2, 2021

Written by Gulzar Ahmed, Chetan Potnuru

We recently shipped out a new Virtual Gifting experience for our ShareChat’s Audio Chatroom- a core feature where the audience can support the creators by sending them virtual gifts. In this blog, we’ll talk about why and how we revamped the existing experience from the ground up. The fundamental idea was to make virtual gifting more fun and intuitive while solving the business goals.

Present Experience — Hits and Misses!

In the existing design, a user needs to tap on a gift icon to reveal different sets of gifts and receivers to choose from. To make this flow clean and smoother, we have used “The Anchoring Principle” wherein we pre-selected the Receiver and a gift to help the user send out their first gift without having to manually select.

It is essential that a user is able to send out their first gift with minimal effort to experience the sense of acknowledgment from creators and others viewing. This sense of social gratification when Receivers would publicly call out and thank them for their contribution is crucial for the users to be interested in recurring participation.

Gifting in ShareChat’s Audio chatroom is not a very uni-directional behaviour. The Gifting frequency often varies when users are involved in time-bound activities and games initiated by the creators. For example, users start sending multiple gifts a.k.a ‘Combo’ when a Chatroom battle is nearing its end meaning the timer is about to hit zero. Hence, users frequently switch between gifts of different values and Receivers to win these battles by a significant difference of total gift value.

Primary Focus Areas:

  • A Gifter would find it cumbersome to go through this process of selection when they do frequent switching between Receivers/Gifts.
  • Since the Gifters would send multiple gifts, the gifting modal/bottom sheet had to remain open unless closed by them. This would restrict the gifter’s view of activity/game status on the main page which was crucial for gifting.
  • The feedback mechanism lacked fun and intuitiveness in conveying the feel of sending someone a gift.

Improved Design

Our main goal was to make gifting easy, contextual and interactive in terms of visual feedback. We as designers and developers started collaborating from the nascent stage, iterating and sharing prototypes amongst each other to ascertain how the interactions would pan out, keeping all the constraints in mind.

Changes Made:

  • We introduced a gift strip (gifts preview) that would accommodate the most used gifts on the main page. As a result, a user would not lose out on the context and gifting, unlike the previous flow
  • Selecting any of the gifts would contextually switch the comment input area to a set of users sequentially placed similar to the top area, to whom users can send gifts. The qualitative assessment showed users identified other users more with their profile pic and their seating order rather than their username. (since the usernames are heavily customized in terms of font styling, etc.)
  • We tested multiple design variants to finalise the most ideal interaction which felt fast, fluid and emulated as if you were gifting someone in person. This new interaction also provided better visual feedback in terms of “combo effect.” The addition of haptic feedback further added to the delight

Under the hood

With the new design, we wanted to make the gifting animation and transition feel instantaneous and natural and handle multiple gift thumbnails on the screen at once while keeping a smooth 60fps.

Unlike other apps, ShareChat’s user smartphone configuration lies between mid to low range, so we also had to keep the memory usage and performance in check. There was no scope of compromise there as it would mar the overall experience.

Here are some of the interesting technical changes we’ve done to make the new design appeal to our user base:

1) Getting the gift animation right — Curve path translation, tweaking scale and alpha animation.2) Instantaneous Feel — Immediate feedback while sending gifts (zero waiting time).3) Rendering at 60fps — Ensuring the app’s activity remains responsive even when multiple gifts are sent at once!4) Natural feel — Physics-based animation

Getting the Gift Animation Right!

Before writing the animation code, we wanted to create the curve path in which the gift would travel. But there are multiple ways to generate a curve. One could use a circular or parabolic curve, but that offers limited control of curvature. Bézier curve, on the other hand, gives more control over the curve through control points and gives a nice, smooth curve that meets the design requirement.

To animate the gift from sender to receiver, we have to go through the following steps:

1) Curve path generation2) Translation — (translating the path generated above)3) Polish — (Scale and alpha animation)

Curve Path Generation:

To describe a shape on screen be it a straight line or a curve we need to use Path class in Android to define it. The path alone cannot draw the desired Bézier curve for us, although it provides an option to pass the control points path.cubicTo(..) as a parameter to define the curve.

The beauty of the Bézier curve is that you don’t need to set control points where it’s forming a curvature, instead, you have to set points that control the curve, which may or may not lie on the curve.

The control points help us in defining the curvature of the curve. But how do we decide where to place control points to get the desired curve?

  • The first quick solution was to do a guesswork, place the control point and get a result that just looked like the design. That didn’t quite work as the curve animation path was dynamic for different positions of gifts and users
  • There’s an ArcMotion class in the Android framework, which has a getPath(..) method which takes the start and end position of the curve and returns a Path object. This internally generates the placement of the two control points, but with this alone we couldn’t obtain the desired result. We had to tweak the angles to get the result. For those interested in knowing the math behind the curve should definitely watch this.

Translation Animation:

Now that we have the curved Path calculated, how do we translate it then? There’s no curvedPath.animate() method. But then getting inspired from the Google I/O animation-related videos, and what Nick Butcher had talked about using ObjectAnimator on performing path animation, we decided to try with ObjectAnimator as a first option.

This worked well, but we didn’t want to use the ObjectAnimator because

  • There was a case when the user profile position(destination) would change mid-way, causing the gift to stop and then change. This kind of change in direction appears unnatural. SpringAnimation solves this and we’ll be discussing in the last part of this blog (Natural Feel)

To perform the animation on our own, we wanted the KeyFrames. At a particular percentage of animation, the KeyFrames would tell us what position (x,y) we have to translate the gift to.

PathMeasure can be used to get the (x,y) position at a particular percentage of animation if we pass the path object. If the path were the same, we would even cache to prevent re-computation.

Polish:

If you notice closely, while the gift animates in the path, it starts small — gradually scaling up in the middle- again scaling down towards the end. Even there’s a change in alpha towards the end.

This is just a subtle detail but was necessary for crafting the experience we had in mind. To achieve this, we just needed an update on the percentage of animation progress and would Linearly interpolate (lerp), scale and alpha multipliers accordingly.

Instantaneous feel!

👈 skipping api response (faster) & not skipping api response (slower) 👉

We wanted to make the whole gifting experience feel very fast but this was not possible if we kept waiting for the API response.

Even a delay of 200ms can be perceived as lag to the human eye.

Since the gifting animation was on the sender side, we had the liberty to skip the API call and interpolate the gift animation, a series of client-side rules were added to redirect the user to the payment page if the balance got over or shows appropriate error if something went awry.

Rendering at 60fps+

We knew while gifting people would keep mashing the send button, this, in turn, was making the garbage collector go crazy by trashing the heap with gift objects, eventually leading to stalls/jank.

To fix this, we implemented object pooling. The pool would create new gifts if the pool didn’t have any gifts or would reuse an existing gift from the pool for animation. Once the gift animation was over, we would release the gift object and put it back in the pool for reuse.

Natural Feel — Physics-based animations!

👈 with spring animation (natural) & object animator (unnatural) 👉

To have continuity in animation, whenever the destination changed mid-way, we usedSpringAnimation. Unlike other animations, it remembers the last velocity when a new animation is created and starts from there.

Impact / The end result: We recorded a steep increase in gifting among users and users love the improved gifting experience!

User feedbacks:

“I really like the new feature because it has increased the speed of gifting”

“I don’t have to use the bottom sheet to select gifts, I can easily choose from the strip”

Cover illustration by Ritesh Waingankar

--

--