October 7th, 2021

Erase pen handling code with the Ink SDK

Kristen Halper
SW/FW Engineer

Hello Android developers!

We’ve just updated one of our existing samples – TwoNote – to include the Ink SDK preview introduced in March and updated in July. TwoNote now also uses the Jetpack Window Manager library to provide foldable support.

If you want to check out the updated sample for yourself, this is the perfect time to download the new Microsoft Surface Duo 2 emulator and start building or enhancing apps for Surface Duo 2!

Pen and ink SDK

The SDK is based on the pen input classes available in Android, as demonstrated in our sample, and it provides two main classes to help you implement pen support.

First, the InkView class is a control that you can place in your views, and it acts as a canvas. This class also defines an interface called DynamicPaintHandler that can be implemented to define different paint styles, including erasing.

The second class, InputManager, keeps track of all pen data (tilt, pressure, pointer type, etc.) and stores pen strokes.

For instructions on how to use the Ink SDK in your projects, refer to this blog post.

TwoNote update

The initial release of TwoNote featured a custom solution for inking, in which we created the PenDrawView and Stroke classes to display and track drawings. This required a lot of tedious x/y coordinate calculations, and we also had to store and maintain large data structures filled with stroke data.

Now that the updated version of TwoNote uses the Ink SDK to handle pen support, we’ve been able to remove those classes entirely, which translates to about ~600 lines of code “erased”! The new version of the app instead uses the InkView and InputManager classes provided by the SDK. This change reduced the amount of background calculations required and really improved the overall inking experience.

The main improvements we’ve seen in the app are shown below.

Smoother strokes

Two example notes in TwoNote (unspanned) with a zig zag pen stroke. The stroke has a few sharp edges on the left, but is smoother on the right Figure 1: Inking in TwoNote from before (left) and after (right) incorporating the Ink SDK into the app. You can see how much smoother the strokes are, especially when pen pressure is changing.

Hover functionality for previewing stroke color and size

Example note in TwoNote app (spanned) with a written grocery list for the farmer's market (apples, tomatoes, peaches, or nectarines) Next to some of the inked list is a white circle, which is the eraser hover indicator Figure 2: The eraser hover indicator appears when a stylus eraser is held near the screen. TwoNote also shows different hover indicators that show the current paint color and stroke size.

Highly customizable pen styles

As mentioned above, the Ink SDK defines the DynamicPaintHandler interface, which can be implemented in unique ways to create different pen styles. We even used it to implement erasing in TwoNote, so now eraser strokes can be undone just like pen strokes.

The code snippet below is an example of the settings we used to make the generic pen style for TwoNote. You can see how both the alpha and width of each stroke are set based on pen pressure, and also how we chose custom style, strokeJoin, and strokeCap values to control the stroke shape.

/**
 * Renders the ink with transparency linked to the pressure on the pen.
 */
inner class FancyPaintHandler : InkView.DynamicPaintHandler {
    override fun generatePaintFromPenInfo(penInfo: InputManager.PenInfo): Paint {
        val paint = Paint()
        val alpha = penInfo.pressure * 255

        paint.color = Color.argb(
            alpha.toInt(),
            drawView.color.red,
            drawView.color.green,
            drawView.color.blue
        )
        paint.isAntiAlias = true
        // Set stroke width based on display density.
        paint.strokeWidth = when (penInfo.pointerType) {
            InputManager.PointerType.FINGER -> drawView.strokeWidthMax
            else -> TypedValue.applyDimension(
                TypedValue.COMPLEX_UNIT_DIP,
                penInfo.pressure * (drawView.strokeWidthMax - drawView.strokeWidth) + drawView.strokeWidth,
                resources.displayMetrics
            )
        }
        paint.style = Paint.Style.STROKE
        paint.strokeJoin = Paint.Join.ROUND
        paint.strokeCap = Paint.Cap.ROUND

        return paint
    }

    override fun selectInkingMode(): InputManager.InkingType {
        return InputManager.InkingType.INKING
    }
}

Since the Ink SDK is open source, we were also able to add our own customizations to the InkView and InputManager classes to suit the needs of the TwoNote app. So, if you’re looking to add inking support to your app and need a good starting place, the Ink SDK is the perfect resource for you!

Emulator support

Recent updates to the Android emulator mean you can now fully test your pen and inking features on touch-screen host computers. This includes pressure sensitivity, pen orientation, and the eraser tip.

Download the latest Surface Duo 2 emulator to start building and testing dual-screen pen-enabled apps!

Resources and feedback

For more coding tips, visit the Surface Duo developer documentation , our samples, and Google’s Android large screen development guidance.

If you have any questions, or would like to tell us about your dual-screen pen-enabled apps, use the feedback forum or message us on Twitter @surfaceduodev.

Finally, please join us for our dual screen developer livestream at 11am (Pacific time) each Friday – mark it in your calendar and check out the archives on YouTube.

Author

Kristen Halper
SW/FW Engineer

Works in the Surface Duo Developer Experience team to help with all aspects of dual-screen SDK development and customer engagement.

0 comments

Discussion are closed.