Tag: kotlin

Over ❤️ Kotlin – How we’ve used Kotlin to build our design app

Over ❤️ Kotlin – How we’ve used Kotlin to build our design app

I recently presented this talk at Kotlin Everywhere South Africa as the keynote for the event. I really enjoyed preparing this talk as it spoke about how we use Kotlin, mistakes we’ve made along the way and our opinion on how we decide to use certain features. 

Talk Description:

Over the past year and a half, I’ve worked primarily on a Kotlin codebase. We at Over, were lucky enough to get a chance to start a project from scratch and we chose Kotlin for many reasons. Our app has been featured multiple times on the Google Play Store and we have found ourselves facing some unique challenges with the product.

In this talk, I’ll cover what my experience has been like working on a Kotlin codebase. I will cover some of the features in Kotlin we use the most, some features we eagerly over used and some of the mistakes we’ve made along the way.

The video recording can be found here: 

The slides for the talk can be found here:

Android: Using Physics-based Animations in Custom Views (SpringAnimation)

Android: Using Physics-based Animations in Custom Views (SpringAnimation)

Learn how to use physics-based animations in a Custom View implementation for natural looking animations in your app.

You’ve used all the standard Android animation techniques, but you find that they sometimes just don’t give you that extra sparkle you are looking for. You’ve wondered how to get more natural looking animations and had no luck thinking about how to do it yourself. So here you are, reading this article in the hope that you will learn how to create beautiful, natural, physics-based animations in your app. 🌈

The Problem 🕵🏽‍♀️

The physics-based animation library is not new, but it was largely unexplored territory for me. Having always used the “standard” animation options (i.e. view.animate()), I had never found a need to use the physics-based animations, until I started with this particular custom view animation. This animation required that we animate a view between two points, decided by the user. Using the standard ValueAnimator, the result was not good enough for the polish that our app requires.

Here is how I previously animated the custom ColourDropperView using the ValueAnimator and PropertyValuesHolder class:

private fun animateToPoint(point: Point) {
    val propertyX = PropertyValuesHolder.ofFloat(ColorDropperView.PROPERTY_X, dropperPoint.x, point.x)
    val propertyY = PropertyValuesHolder.ofFloat(ColorDropperView.PROPERTY_Y, dropperPoint.y, point.y)

    val animator = ValueAnimator()
    animator.setValues(propertyX, propertyY)
    animator.interpolator = OvershootInterpolator()
    animator.duration = 100
    animator.addUpdateListener { animation ->
        val animatedX = animation.getAnimatedValue(ColorDropperView.PROPERTY_X) as Float
        val animatedY = animation.getAnimatedValue(ColorDropperView.PROPERTY_Y) as Float
        setPoint(Point(animatedX, animatedY))
    }
    animator.start()
}

The PropertyValuesHolder is useful when creating custom animations on our own properties. When using it, the animated property values can be fetched from the animation in the AnimationUpdateListener callback. At this point, the values are interpolated between the start and end values we initially provide. We can then go ahead and perform the draw operation (by calling invalidate() on our custom view) using these new animated values and the view will animate 🤩. In our case, the setPoint() method calls invalidate()and the draw() function uses the new point values to draw itself.

ValueAnimator Example

Don’t get me wrong — the above animation is okay in most contexts but we would like it to look more fluid. We need to animate it elegantly between these two positions.

One of the problems with the above animation is that we needed to specify a duration that the animation should take. We specified 100ms which moved the view at a high speed. But you may also notice that the ColorDropperViewmoves a lot faster when the distance between the start and end point is larger. We could play around with the duration property until it looked more acceptable. Ideally, we want the velocity to remain the same and the animation to look consistent, no matter the distance between the two points.

The Solution: SpringAnimation ✨

In order to make the animation more fluid, we need to switch to using the SpringAnimation class (documentation can be found here). The SpringAnimation class allows us to set the property which we will be animating, the velocity and the end value that the property should use.

To use the SpringAnimation class, we need to include the dependency in our build.gradle file:

implementation "androidx.dynamicanimation:dynamicanimation:1.0.0"

There are a bunch of built-in properties that we can use to achieve some standard effects, such as SCALE_XROTATION and ALPHA properties (check the documentation for the full list here). In our case, we needed to animate a custom property — the colour dropper’s X and Y point (the underlying data structure that the view depends on for drawing). So we need to do things a bit differently.

We need to take a look at the SpringAnimation constructor that takes in the FloatPropertyCompat object as an argument. This property will link up our custom view implementation to the animation. The SpringAnimation class uses this object to call into our custom view class on every change of the float value. Here is the implementation of the two custom FloatPropertyCompatobjects for the X position and the Y position on screen:

private val floatPropertyAnimX = object : FloatPropertyCompat<ColorDropperView>(PROPERTY_X) {
    override fun setValue(dropper: ColorDropperView?, value: Float) {
        dropper?.setDropperX(value)
    }

    override fun getValue(dropper: ColorDropperView?): Float {
        return dropper?.getDropperX() ?: 0f
    }
}

private val floatPropertyAnimY = object : FloatPropertyCompat<ColorDropperView>(PROPERTY_Y) {
    override fun setValue(dropper: ColorDropperView?, value: Float) {
        dropper?.setDropperY(value)
    }

    override fun getValue(dropper: ColorDropperView?): Float {
        return dropper?.getDropperY() ?: 0f
    }
}

These two objects access two custom methods on the ColorDropperView class and the setValue methods will be called whilst the animation is running, which will set the new interpolated values. In this case, setDropperX() and setDropperY() are custom methods in our ColorDropperView class. When these methods are invoked, they change the underlying value and call invalidate() which will trigger another redraw of the view.

Once we have our properties defined, we can then go on to implement the SpringAnimation effect with these properties.

Now we can see, our animateToPoint() function uses the SpringAnimationclass, passes in the reference to the ColorDropperView (this) and we can set a few properties on the animation (such asstiffness and dampingRatio). We then call start() and the animation will run.

private fun animateToPoint(point: Point) {

    SpringAnimation(this, floatPropertyAnimX, point.x).apply {
        spring.stiffness = SpringForce.STIFFNESS_MEDIUM       
        spring.dampingRatio = SpringForce.DAMPING_RATIO_MEDIUM_BOUNCY
        start()
    }

    SpringAnimation(this, floatPropertyAnimY, point.y).apply {
        spring.stiffness = SpringForce.STIFFNESS_MEDIUM
        spring.dampingRatio = SpringForce.DAMPING_RATIO_MEDIUM_BOUNCY
        start()
    }
}

It is worth noting, that we don’t need to (and we can’t) specify the duration of this animation, which makes total sense! In the real world, when something is falling or moving, we can only calculate how long it’ll take based on its mass, stiffness, velocity and other factors. We cannot tell the object how long it should take.

Here is a recording of how the animation works now using the SpringAnimation class. Much smoother and more natural looking, don’t you think?

SpringAnimation in action

Damping Ratio (bouncy-ness) 🎾

The dampingRatio that we can set on a SpringAnimation determines how much bounce the animation will have. There are some built-in options for the dampingRatio that’ll produce different results:

  • DAMPING_RATIO_NO_BOUNCY
  • DAMPING_RATIO_LOW_BOUNCY
  • DAMPING_RATIO_MEDIUM_BOUNCY (default)
  • DAMPING_RATIO_HIGH_BOUNCY

We are also able to set a value between 0 and 1 for this ratio if preferred. Here are three examples of the effect the dampingRatio has on our custom view:

dampingRatio example

Stiffness

Another property that we can set on a SpringAnimation is the stiffnessof the spring force. Like the dampingRatio, we can choose from a few predefined options:

  • STIFFNESS_LOW
  • STIFFNESS_VERY_LOW
  • STIFFNESS_MEDIUM (default)
  • STIFFNESS_HIGH

The stiffness affects how long the animation will take: if the spring is very stiff (STIFFNESS_HIGH) the animation will perform quicker than if the stiffness is low.

Below is an example of some of the different stiffness values in action:

Stiffness examples

Velocity 🚗

SpringAnimations can also have their startVelocity set using setStartVelocity(). This value is specified in pixels per second. If you would like to specify it, you should convert from a dp value into pixels to ensure the animation looks consistent across different devices. The default startVelocity is 0.

Here is an example of how to set the startVelocity to 5000dp per second:

SpringAnimation(this, floatPropertyAnimY, point.y).apply {
    setStartVelocity(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 5000f, resources.displayMetrics))
    start()
}

This is what different start velocities look like on the custom view:

startVelocity options

Cancel SpringAnimation ✋🏾

Another great part about physics-based animations is that they can be cancelled midway through the animation if required. Calling SpringAnimation#cancel() will terminate the animation. There is also the option toSpringAnimation#skipToEnd() which will immediately show the end state of the animation (this can cause a visual jump — as if the animation wasn’t implied).

Dynamic Animation — KTX Functions

There are currently some extension functions provided by the following KTX dependency (check for the latest version here):

implementation "androidx.dynamicanimation:dynamicanimation-ktx:1.0.0-alpha01"

The alpha version was released on the 9th February 2019, but there are some new changes that haven’t been released yet, which will clean up this code quite a bit. Take a look here at the new extension functions that will be provided soon. The clean up of creating the FloatPropertyCompat objects is particularly interesting and will help clean up this code in the future.

Finally 🧚🏼‍♀️

The physics-based animations in Android are great alternatives when you have animations that need to look more natural. They are also great for when you are moving things around on the screen and you aren’t sure how long the animation should take. Rather don’t try to guess those duration values, use physics animations instead. 👩🏻‍🔬

For our animation, we ended up going with the DAMPING_RATIO_MEDIUM_BOUNCY ,STIFFNESS_MEDIUM and the startVelocity set at 0. This was the final animation that we stuck with:

Final animation

Where else have you found physics-based animations to be useful? Let me know your thoughts on Twitter! 🌈

Thanks to Josh LeibsteinGarima JainNick Rout and Dan Galasko for reviewing this post. 💚

Android Canvas APIs with Kotlin and KTX

Android Canvas APIs with Kotlin and KTX

Learn how to use the Android KTX extension functions to clean up Canvas drawing code

Have you ever wanted to write a Custom View on Android but you were too afraid to deal with X, Y translations on a Canvas object? 

Well, working with them got a whole lot easier when using Kotlin and the Android KTX Extension functions provided by the Android Team at Google. 

Drawing on Canvas without KTX 🙀🙅🏽‍♀️

If you want to translate (move) an object you are drawing on a Canvas, how would you go about doing that? You would likely need to do something like the following:

canvas.save()
canvas.translate(200f, 300f)
canvas.drawCircle(...) // drawn on the translated canvas
canvas.restore()

Canvas#save() and Canvas#restore() can be used to save() the current matrix (transformations like translate, rotate etc) and restore() the state of the Canvas back to its original transformations. 

The drawCircle() method that we are calling will be drawn at a translated point on the Canvas. Once restore is called, the Canvas is no longer translated and any further operations on that Canvas after that point will not be translated.

Example of a circle being drawn to a Canvas, the first doesn’t contain a translation, whereas the second has a translation applied

If we wanted to then do something more complex, for instance, draw a path that is scaled up after we have translated, the code would look as follows:

val translateCheckpoint = canvas.save()
canvas.translate(200f, 300f)
canvas.drawCircle(...) // drawn on the translated canvas
val rotateCheckpoint = canvas.save()
canvas.rotate(45f)
canvas.drawRect(...) // drawn on the translated and rotated canvas
canvas.restoreToCount(rotateCheckpoint)
canvas.restoreToCount(translateCheckpoint)
Example of drawing a Rect — Image 1: No transformations — without doing save/restore. Image 2: Translated with same checkpoint as circle. Image 3: Translated and rotated.

To do multiple translations on a Canvas, we would then want to use restoreToCount with the specific checkpoint. This will notify the canvas of the certain checkpoint of the transformations that should be restored. 

We can see that this can easily get out of control and it becomes really difficult to follow what transformations will be applied to a certain draw... call.  

Improving Canvas API calls with Android KTX 😻

To use these extension functions, you need to make sure you are importing the core-ktx dependency in your app level build.gradle file (look here for the latest version):

implementation 'androidx.core:core-ktx:1.0.1'

If we are using KTX, we can simplify the previous draw examples to be the following:

canvas.withTranslate(200f, 300f) {
drawCircle(...)
}

This wraps up this logic in a block, that makes it easier to understand and our code is cleanly separated. We also don’t need to specify the canvas on which to draw on at this point, since the block now has the Canvas in this scope. If we wished to draw certain parts of the Canvas at different points, say we wanted to translate and scale, we can nest the withRotate function inside the first withTranslate block. 

canvas.withTranslate(200f, 300f) {
drawCircle(...) // drawn on the translated canvas
withRotate(45f) {
drawRect(...) // drawn on the translated and rotated canvas
}
}

Now our function calls are clearly separated with parentheses and we can easily see which canvas transformations will be applied to the drawRect function by using these extension functions. 

Diving into the Android KTX implementation 📝

This is one of the extension functions for Canvas defined in the KTX library (original source code can be found here):

/**
* Wrap the specified [block] in calls to [Canvas.save]/[Canvas.translate]
* and [Canvas.restoreToCount].
*/
inline fun Canvas.withTranslation(
x: Float = 0.0f,
y: Float = 0.0f,
block: Canvas.() -> Unit
) {
val checkpoint = save()
translate(x, y)
try {
block()
} finally {
restoreToCount(checkpoint)
}
}

Taking a deeper look into how this extension function works, we can see that the functions wrap up the logic of saving and restoring the canvas. The last parameter is a function and that function (block()) is a function literal with receiver. This sounds complicated but this just means that the Canvas instance then becomes the this scope for that function definition. 

This allows us in the block() function, to call the Canvas methods without having to specify the canvas object directly. For example, we don’t have to call canvas.drawCircle() anymore, we can now just call drawCircle() and the correct Canvas object will be used for that method call. 

The block param is the last parameter of the function (and it is a function itself) so we are able to extract the block function outside of the parentheses. For example, both of the following usages are acceptable:

canvas.withTranslate(200f, 300f, {
drawCircle(...)
})

Outside of parenthesis:

canvas.withTranslate(200f, 300f) {
drawCircle(...)
}

It is worth noting that in Android Studio, the first example here will produce a lint warning to tell you to rather use the second option. 

What a nifty mechanism for cleaning up our Canvas API interactions!

Finally… ✨

We can see how the AndroidX Canvas Extension functions can help improve the readability of our canvas transformation code. There are a few other extension functions for Canvas, some of the others include:

  • Canvas#withScale() 
  • Canvas#withSkew() 
  • Canvas#withMatrix()

Have you found any other useful extension functions in the KTX library? Let me know on Twitter @riggaroo 

Thanks to Nick Rout and Josh Leibstein for reviewing this post. 

[HOW TO] Set up Kotlin Source Code & Tests in your Android Apps

[HOW TO] Set up Kotlin Source Code & Tests in your Android Apps

After reading a lot of different posts raving about Kotlin, I couldn’t help myself. I had some serious FOMO. In this blog post, I will be looking at getting Kotlin set up in existing Android Apps.

What is Kotlin?

Kotlin is a statically typed programming language that can be used to write Android Apps. It is made by JetBrains, the same guys who make IntelliJ, Resharper and other awesome tools.

What does Kotlin code look like?

Below is how you would declare a function in Kotlin:

fun sum(a: Int, b: Int): Int {
  return a + b
}

As you can see there are a few notable differences from Java:

  1. The lack of semicolons (Yay right?).
  2. The declaration of the return type is at the end of the function definition.
  3. The type of the parameters are defined after the parameter name.

For more basic syntax differences, you can read more here.

Why is it better than Java?

A quick summary of Kotlin’s Advantages over Java:

This video by Jake Wharton highlights the differences between Java and Kotlin quite well. There are more links at the end of this blog post.

So now that we know what Kotlin is and why we might want to use it for our Android Apps. Lets take a look at getting set up in our existing Android Project.

Setting up your existing Android Project to use Kotlin

  1. Install the Kotlin plugin for Android Studio :
    • Go to “Preferences”→ “Plugins”→ “Install JetBrains Plugin”→ Type “Kotlin” in the search box→ Select “Kotlin” and install it. You will probably need to restart Android Studio for the settings to take effect.Kotlin Plugin in Settings Menu - Android Studio
  2. Go to your project level build.gradle file and add the following line into the classpath section
    buildscript {
        repositories {
            jcenter()
        }
        dependencies {
            classpath "com.android.tools.build:gradle:2.0.0-alpha3"
            classpath 'com.github.dcendents:android-maven-gradle-plugin:1.3'
            classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.0.0-beta-4584"
        }
    }
  3. In your app level build.gradle  add the following:
    buildscript {
        repositories {
            maven { url 'https://maven.fabric.io/public' }
        }
    
        dependencies {
            classpath 'io.fabric.tools:gradle:1.+'
        }
    }
    apply plugin: 'com.android.application'
    apply plugin: 'kotlin-android'
    
    android {
        ...
        sourceSets {
            main.java.srcDirs += 'src/main/kotlin'
        }
    }
    
    dependencies {
        ...
        compile 'org.jetbrains.kotlin:kotlin-stdlib:1.0.0-beta-4584'
      
    }
    
  4. Create a folder in your app/src/main/  folder called kotlin . You can then create a folder with your package name, so for my example it would be org.bookdash.android.(You can also add kotlin files into the same directory as the Java files, I just prefer to separate them out by language.)
    Folder Structure when using kotlin programming language in android studio
  5. To add a new Kotlin class, right click on the package name and click “New -> Kotlin File or class”. Give it a name, select the type and you can start writing Kotlin code!How to Add new Kotlin class file in Android Studio

Convert existing Java files to Kotlin

In Android Studio if you want to convert a Java class to Kotlin, do the following:

  1. Open the file you wish to convert
  2. Run the following command. (Navigate to Action):
    • MacOs: CMD + Shift + A
    • Linux & Windows: CNTRL + Shift + A
  3. Then type “kotlin”, you should see the option to convert existing Java file into Kotlin.  Convert existing Java code to Kotlin
  4. This will take the Java file that you are in and convert it into a Kotlin class. I would make sure that the code that is generated is okay. I am always a bit worried about generated code not working. 😁
  5. I converted the AboutActivity  from my Book Dash App to use Kotlin, this is the result:
    class AboutActivity : BaseAppCompatActivity(), AboutContract.View {
    
        private var aboutPresenter: AboutPresenter? = null
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_about)
            aboutPresenter = AboutPresenter(this)
    
            val toolbar = findViewById(R.id.toolbar) as Toolbar
            setSupportActionBar(toolbar)
            val actionBar = supportActionBar
    
            if (actionBar != null) {
                actionBar.setDisplayHomeAsUpEnabled(true)
                actionBar.setTitle(R.string.about_heading)
            }
    
            val textViewWhyBookDash = findViewById(R.id.text_why_bookdash) as TextView
            textViewWhyBookDash.text = Html.fromHtml(getString(R.string.why_bookdash))
            Linkify.addLinks(textViewWhyBookDash, Linkify.ALL)
            ...
        }
    
        override fun showLearnMorePage(url: String) {
            val intent = Intent(Intent.ACTION_VIEW)
            intent.setData(Uri.parse(url))
            startActivity(intent)
        }
    }

    If you want to see an example of an app using Kotlin and Java, you can check out my github project, the Feature-Kotlin-AboutActivity branch.

Writing Tests in Kotlin

After getting some code written in Kotlin, I thought it would be great to see if I could set up some Android tests in Kotlin. Here is how to do it:

  1. In your androidTest folder create a kotlin folder
  2. Create your package name that matches the package you are testing.Getting Android Tests set up in Kotlin
  3. In your app build.gradle file, add the following:
    android {
        ...
        sourceSets {
            main.java.srcDirs += 'src/main/kotlin'
            androidTest.java.srcDirs += 'src/androidTest/kotlin'
        }
    
    }

    Adding that line tells Gradle that it should also look in the kotlin folder for source code and it should include it when building.

  4. Then you can start adding code to that folder. Below is an example of my AboutActivityTest  which does some basic espresso testing in Kotlin.
    @RunWith(AndroidJUnit4::class)
    @SmallTest
    class AboutActivityTest {
    
        @Rule
        fun getRule() = ActivityTestRule(AboutActivity::class.java)
    
    
        @Before
        fun setUp() {
            Intents.init()
        }
    
        @After
        fun tearDown() {
            Intents.release()
        }
    
        @Test
        @Throws(Throwable::class)
        fun loadAboutBookDash_SeeInformation() {
            val about = Html.fromHtml(InstrumentationRegistry.getTargetContext().getString(R.string.why_bookdash))
            val headingAbout = InstrumentationRegistry.getTargetContext().getString(R.string.heading_about)
    
            onView(withText(headingAbout)).check(matches(isDisplayed()))
    
            onView(withText(about.toString())).perform(scrollTo()).check(matches(isDisplayed()))
    
        }
    
        @Test
        @Throws(Throwable::class)
        fun clickLearnMore_OpenBrowser() {
    
            onView(withText(R.string.learn_more)).perform(scrollTo(), click())
    
            intended(allOf(hasAction(Intent.ACTION_VIEW),
                    hasData(Uri.parse("http://bookdash.org"))))
        }
    
    }
    

    Why I like Kotlin

  • The code looks neater and concise (no more semi-colons)
  • It is not just for Android apps.  It runs on the JVM you can use it pretty much anywhere.
  • You can write in both Java and Kotlin in the same project, they work together.
  • Of course the Null Safety Lambdas , Extension functions are great too 😁

What next?

I suggest reading through the docs about the advantages of Kotlin and try out some Kotlin code on the website or in a sample app. Then go forth and #MakeKotlinApps!

I would love to know what your are experiences with it so far? Do you have any other tips or tricks to getting started with Kotlin?

Links:

Book Dash Android App Github

Why Kotlin is my next Programming Language

Kotlin – The swift of Android

Using Project Kotlin for Android

RedChain –  Github Project for Android App – Daily goal tracker written in Kotlin