Animations in Loklak Wok Android

Imagine an Activity popping out of nowhere suddenly in front of the user. And even more irritating, the user doesn’t even know whether a button was clicked. Though these are very small animation implementations but these animations enhance the user experience to a new level. This blog deals with the animations in Loklak Wok Android, a peer message harvester of Loklak Server.

Activity transition animation

Activity transition is applied when we move from a current activity to a new activity or just go back to an old activity by pressing back button.

In Loklak Wok Android, when user navigates for search suggestions from TweetHarvestingActivity to SuggestActivity, the new activity i.e. SuggestActivity comes from right side of the screen and the old one i.e. TweetHarvestingActivity leaves the screen through the left side. This is an example of left-right activity transition. For implementing this, two xml files which define the animations are created, enter.xml and exit.xml are created.

<set
   xmlns:android="http://schemas.android.com/apk/res/android"
   android:shareInterpolator="false">

   <translate
       android:duration="500"
       android:fromXDelta="100%"
       android:toXDelta="0%"/>
</set>

 

NOTE: The entering activity comes from right side, that’s why android:fromXDelta parameter is set to 100% and as the activity finally stays at extreme left, android:toXDelta parameter is set to 0%.

As the current activity, in this case TweetHarvestingActivity, leaves the screen from left to the negative of left. So, in exit.xml the android:fromXDelta parameter is set to 0% and android:toXDelta parameter is set to -100%.

Now, that we are done with defining the animations in xml, it’s time we apply the animations, which is really easy. The animations are applied by invoking Activity.overridePendingTransition(enterAnim, exitAnim) just after the startActivity method. For example, in openSuggestActivity

private void openSuggestActivity() {
   Intent intent = new Intent(getActivity(), SuggestActivity.class);
   startActivity(intent);
   getActivity().overridePendingTransition(R.anim.enter, R.anim.exit);
}

 

Touch Selectors

Using touch selectors background color of a button or any clickable can be changed, this way a user can see that the clickable responded to the click. The background is usually light accent color or a lighter shade of the icon present in button.

There are three states involved while a clickable is touched, pressed, activated and selected. And a default state, i.e. the clickable is not clicked. The background color of each state is defined in a xml file like media_button_selector, which is present in drawable directory.

<selector xmlns:android="http://schemas.android.com/apk/res/android">

   <item android:drawable="@color/media_button_touch_selector_backgroud" android:state_pressed="true"/>
   <item android:drawable="@color/media_button_touch_selector_backgroud" android:state_activated="true"/>
   <item android:drawable="@color/media_button_touch_selector_backgroud" android:state_selected="true"/>

   <item android:drawable="@android:color/transparent"/>
</selector>

 

The selector is applied by setting it as the background of a clickable, for example, touch selector applied on Location image button present in fragment_tweet_posting.xml .

<ImageButton
   android:layout_width="40dp"
   android:layout_height="40dp"
   
   android:background="@drawable/media_button_selector" />

 

Notice the change in the background color of the buttons when clicked.

Resources:

Some youtube videos for getting started:

Creating Animations in GTK+ with Pycairo in SUSI Linux App

SUSI Linux has an assistant user interface to answer your queries. You may ask queries and SUSI answers interactively using a host of skills which range from entertainment, knowledge, media to science, technology and sports. While SUSI is finding the answer to the query, it makes sense to add some animations depicting the process. The UI for SUSI Linux app is wholly made using GTK+ 3 using PyGObject (PyGTK). Thus, I needed to find a way create animations in GTK+.

Animations in most frameworks are generally created using repetitive drawing after an interval which leads to the effect of an object’s movement. Thus, basic need was to find a way to draw a custom object in GTK+. Reading the documentation of the GTK+, I realized that this could be done with a GTKDrawingArea.

GTKDrawingArea defines an area on which application developers can do the drawing on their own. GTK itself does not provide Canvas and related object to draw the shapes. For that, we need to use Cairo graphics library. Cairo is an open source graphics library with support for multiple window systems. It can run on a variety of backends, though here, we are not concerned about them.

Cairo can be accessed in Python using Pycairo. Pycairo is a set of Python 2 & 3 bindings for the cairo graphics library. Resources for usage of Pycairo for animations with GTK+ 3 are very less thus I will try to explain it in this blog in detail. We will start by creating an Animator class extending the GTK DrawingArea class.

class Animator(Gtk.DrawingArea):
   def __init__(self, **properties):
       super().__init__(**properties)
       self.set_size_request(200, 80)
       self.connect("draw", self.do_drawing)
       GLib.timeout_add(50, self.tick)

   def tick(self):
       self.queue_draw()
       return True

   def do_drawing(self, widget, ctx):
       self.draw(ctx, self.get_allocated_width(), self.get_allocated_height())

   def draw(self, ctx, width, height):
       pass

In the above code stub, we created the Animator class extending the GTK.DrawingArea. Animator class is meant to be an abstract class for the other animators. We defined the size request of the area we want and connected the “draw” signal to the do_drawing method. On notable thing to note here is that, we have “draw” signal on GTK+ 3 while on GTK+2 we have “on_expose” signal. On the creation of the widget, draw signal is fired. In the handler do_drawing method, we receive widget and ctx. Here ctx is the Cairo context. We can perform our drawing with the help of the of Cairo context. We further call the draw method passing the context, width and height of the widget. On notable thing here is that, even though we requested for a size for the widget, allocated size might be different depending upon a number of factors. Thus, drawing must be done according to allocated area instead of the absolute area.

The draw is an abstract method. All the animators must override this method to implement custom drawing on the widget area. Lastly, we add a timeout based call to tick method. This is what drives the animation. This is done with the help of GLib.timeout_add(). Here the first argument is the time in milliseconds after which callback should be fired and second argument is the callback that should be fired. We are calling tick method in the class. It is required for the method to return True if successful for proper functioning. We call queue_draw method from within the tick method. queue_draw leads to invalidation of current area and again generates the draw signal.

Now that we know how the core of the animation will work, let us define some cool animations for the Listening phase of the application. We define the Listening Animator for the same.

class ListeningAnimator(Animator):
   def __init__(self, window, **properties):
       super().__init__(**properties)
       self.window = window
       self.tc = 0

   def draw(self, ctx, width, height):

       self.tc += 0.2
       self.tc %= 2 * math.pi

       for i in range(-4, 5):
           ctx.set_source_rgb(0.2, 0.5, 1)
           ctx.set_line_width(6)
           ctx.set_line_cap(cairo.LINE_CAP_ROUND)
           if i % 2 == 0:
               ctx.move_to(width / 2 + i * 10, height / 2 + 3 - 
                           8 * math.sin(self.tc + i))
               ctx.line_to(width / 2 + i * 10, height / 2 - 3 + 
                           8 * math.sin(self.tc + i))
           else:
               ctx.set_source_rgb(0.2, 0.7, 1)
               ctx.move_to(width / 2 + i * 10, height / 2 + 3 - 
                           8 * math.cos(self.tc - i))
               ctx.line_to(width / 2 + i * 10, height / 2 - 3 + 
                           8 * math.cos(self.tc - i))
               ctx.stroke()

In this we are drawing some lines with round cap to create an effect like below.

Since, the lines must move we are using trigonometric functions to create sinusoidal movement with some phase difference between adjacent lines. To set color of the brush, we use set_source_rgb method. We may then move the pointer to desired position, draw lines or other shapes. Then, we can either fill the shape or draw strokes using the relevant methods. The full list of methods can be accessed here in the official documentation.
After creating the widget, it can be easily added to the UI depending on the type of the container, generally by add method. You may access the full code of SUSI Linux repository to learn more about the usage in SUSI Linux App. The final result can be seen in the following video.

Resources:

Addition Of Settings Page Animations in Open Event Android App

In order to bring in some uniform user flow in the  Open Event Android  there was a need to implement slide animation for various screens. It turned out that the settings page didn’t adhere to such a rule. In this blog post I’ll be highlighting how this was implemented in the app.

Android Animations

Animations for views/layouts in android were built in order to have elements of the app rely on real life motion and physics. These are mainly used to choreograph motion among various elements within a page or multiple pages. Here we would be implementing a simple slide_in and a slide_out animation for the settings page. Below I highlight how to write a simple animator.

slide_in_right.xml

<?xml version="1.0" encoding="utf-8"?>
<set

   xmlns:android="http://schemas.android.com/apk/res/android">
   <translate
       android:duration="@android:integer/config_shortAnimTime"
       android:fromXDelta="100%"
       android:toXDelta="0%" />

</set>

This xml file maily is what does the animation for us in the app. We just need to provide the translate element with the position fromXDelta from where the view would move to another location that would be toXDelta.

@android:integer/config_shortAnimTime is a default int variable for animation durations.

Here toXDelta=”0%” signifies that initial position of the page i.e the settings page that is the screen itself. And the 100% in fromXDelta signifies the virtual screen space to the right of the actual screen(OUTSIDE THE SCREEN OF THE PHONE).

Using this animation it appears that the screen is sliding into the view of the user from the right.

We will be using overridePendingTransition to override the default enter and exit animations for the activities which is fade_in and fade_out as of Android Lollipop.

The two integers you provide for overridePendingTransition(int enterAnim, int exitAnim) correspond to the two animations – removing the old Activity and adding the new one.

We have already defined the enterAnim here that is slide_in_left. For the exit animation we would define another animation that would be stay_in_place.xml that would have both fromXDelta and toXDelta as 0% as their values. This was done to just avoid any exit animation.

We need to add this line after the onCreate call within the SettingActivity.

@Override
 protected void onCreate(Bundle savedInstanceState) {

       //Some Code
       super.onCreate(savedInstanceState);
       overridePendingTransition(R.anim.slide_in_right,    R.anim.stay_in_place);
     //Some Code

Now we are done.

We can see below that the settings page animates with the prescribed animations below.

Resources

 

Motion in android

So earlier this year I attended a talk where the speaker wanted to introduce us to meaningful motion in android apps and he convinced us to use this in our apps as well. Motion came in with Material design, actually not really came but became popular with Material design and since google has added the same kind of motions to their apps as well, developers have started using it.

I love motion, not only does it boost engagement but it’s instantly noticeable. Think of the apps you use that feature motion design and how pleasing, satisfying, fluent and natural they feel to experience. Eg. Zomato, Play music etc.

Now think of some apps that don’t use any kind of motions and you’ll realise they look a bit boring and you as users will always prefer apps with some kind of motion.

Touch

So firstly let’s discover the feedback on touch. It helps to communicate to the user in a visual form that some interaction has been made. But also keep in mind that this animation should be enough for them to gain clarity and encourage further explorations and not distract them.

For adding backgrounds you can use the following :

  • ?android:attr/selectableItemBackground — Show a ripple effect within the bounds of the view.
  • ?android:attr/selectableItemBackgroundBorderless — Show a ripple effect extending the bounds of the view.

View Property Animator

Introduced in API 12, this allows us to perform animated operations (in parallel) on a number of view properties using a single Animator instance

Some of the parameters that can be added to a view are as follows :

  • alpha() -Set the alpha value to be animated to
  • scaleX() & scaleY()— Scales the view on it’s X and / or Y axis
  • translationZ() — Translates the view on its Z axis
  • setDuration()— Sets the duration of the animation
  • setStartDelay() — Sets the delay on the animation
  • setInterpolator() — Sets the animation interpolator
  • setListener() — Set a listener for when the animation starts, ends, repeats or is cancelled.

Now let’s write some code on how to do this on a button for example:

mButton.animate().alpha(1f)
.scaleX(1f)        
.scaleY(1f)        
.translationZ(10f)        
.setInterpolator(new FastOutSlowInInterpolator())        .setStartDelay(200)        
.setListener(new Animator.AnimatorListener() {            
@Override            
public void onAnimationStart(Animator animation) { }             
@Override            
public void onAnimationEnd(Animator animation) { }             
@Override            
public void onAnimationCancel(Animator animation) { }             
@Override            
public void onAnimationRepeat(Animator animation) { }        
})        
.start();

Note : Use ViewCompat class to implement the ViewPropertyAnimator from Android API version 4 and up

Object Animator

Similar to the ViewPropertyAnimator, the ObjectAnimator allows us to perform animations on various properties of the target view (both in code and XML resource files). However, there a couple of differences:

  • The ObjectAnimator only allows animations on a single property per instance e.g.Scale X followed by Scale Y.
  • However, it allows animations on a custom Property e.g. A view’s foreground colour.

Her we need to set the evaluator, set the delay and call start().

private void animateForegroundColor(@ColorInt final int targetColor) {   
    ObjectAnimator animator = ObjectAnimator.ofInt(YOUR_VIEW, FOREGROUND_COLOR, Color.TRANSPARENT, targetColor);                    animator.setEvaluator(new ArgbEvaluator()); animator.setStartDelay(DELAY_COLOR_CHANGE); animator.start();}

Interpolators

An Interpolator can be used to define the rate of change for an animation, meaning the speed, acceleration and behaviour during animating can be altered. Some of them are :

These are some of the basics. there are a lot of other things like

  • Window transitions(Explode, fade, slide etc.)
  • Shared element Transitions
  • Other custom transitions
  • Animated Vector drawables

you can play around with these for a better understanding but be sure to actually try everything on a device/emulator since you’ll get to actually see the changes in the UI and in turn understand better.