{"id":1920,"date":"2021-10-07T12:53:06","date_gmt":"2021-10-07T19:53:06","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/surface-duo\/?p=1920"},"modified":"2022-06-10T12:35:26","modified_gmt":"2022-06-10T19:35:26","slug":"pen-ink-sdk-sample","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/surface-duo\/pen-ink-sdk-sample\/","title":{"rendered":"Erase pen handling code with the Ink SDK"},"content":{"rendered":"<p>Hello Android developers!<\/p>\n<p>We\u2019ve just updated one of our existing samples \u2013 TwoNote \u2013 to include the Ink SDK preview introduced in <a href=\"https:\/\/devblogs.microsoft.com\/surface-duo\/android-pen-ink-control-preview\">March<\/a> and updated in <a href=\"https:\/\/devblogs.microsoft.com\/surface-duo\/pen-ink-sdk-hover\/\">July<\/a>. TwoNote now also uses the <a href=\"https:\/\/docs.microsoft.com\/dual-screen\/android\/jetpack\/window-manager\/\">Jetpack Window Manager<\/a> library to provide foldable support.<\/p>\n<p>If you want to check out the <a href=\"https:\/\/github.com\/microsoft\/surface-duo-window-manager-samples\/tree\/main\/TwoNote\">updated sample<\/a> for yourself, this is the perfect time to download the new Microsoft <a href=\"https:\/\/docs.microsoft.com\/dual-screen\/android\/emulator\/\">Surface Duo 2 emulator<\/a> and start building or enhancing apps for <a href=\"https:\/\/www.microsoft.com\/d\/surface-duo-2\/9408kgxp4xjl\">Surface Duo 2<\/a>!<\/p>\n<h2>Pen and ink SDK<\/h2>\n<p>The SDK is based on the pen input classes available in Android, as demonstrated in our <a href=\"https:\/\/devblogs.microsoft.com\/surface-duo\/pen-events-on-the-surface-duo\">sample<\/a>, and it provides two main classes to help you implement pen support.<\/p>\n<p>First, the <strong>InkView<\/strong> class is a control that you can place in your views, and it acts as a canvas. This class also defines an interface called <strong>DynamicPaintHandler<\/strong> that can be implemented to define different paint styles, including erasing.<\/p>\n<p>The second class, <strong>InputManager<\/strong>, keeps track of all pen data (tilt, pressure, pointer type, etc.) and stores pen strokes.<\/p>\n<p>For instructions on how to use the Ink SDK in your projects, refer to this <a href=\"https:\/\/devblogs.microsoft.com\/surface-duo\/pen-ink-sdk-hover\/#try-it-out\">blog post<\/a>.<\/p>\n<h2>TwoNote update<\/h2>\n<p>The <a href=\"https:\/\/devblogs.microsoft.com\/surface-duo\/noteworthy-new-app-sample-twonote\/\">initial release of TwoNote<\/a> featured a custom solution for inking, in which we created the <strong>PenDrawView<\/strong> and <strong>Stroke<\/strong> 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.<\/p>\n<p>Now that the updated version of TwoNote uses the Ink SDK to handle pen support, we\u2019ve been able to remove those classes entirely, which translates to about ~600 lines of code \u201cerased\u201d! The new version of the app instead uses the <strong>InkView<\/strong> and <strong>InputManager<\/strong> classes provided by the SDK. This change reduced the amount of background calculations required and really improved the overall inking experience.<\/p>\n<p>The main improvements we\u2019ve seen in the app are shown below.<\/p>\n<h3>Smoother strokes<\/h3>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2021\/10\/example-note-in-twonote-unspanned-both.png\"><img decoding=\"async\" class=\"alignnone size-full wp-image-1926\" src=\"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2021\/10\/example-note-in-twonote-unspanned-both.png\" alt=\"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\" width=\"1099\" height=\"797\" srcset=\"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2021\/10\/example-note-in-twonote-unspanned-both.png 1099w, https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2021\/10\/example-note-in-twonote-unspanned-both-300x218.png 300w, https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2021\/10\/example-note-in-twonote-unspanned-both-1024x743.png 1024w, https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2021\/10\/example-note-in-twonote-unspanned-both-768x557.png 768w\" sizes=\"(max-width: 1099px) 100vw, 1099px\" \/><\/a>\n<em>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.<\/em><\/p>\n<h3>Hover functionality for previewing stroke color and size<\/h3>\n<p><img decoding=\"async\" width=\"1063\" height=\"823\" class=\"wp-image-1923\" src=\"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2021\/10\/example-note-in-twonote-app-spanned-with-a-writt.png\" alt=\"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\" srcset=\"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2021\/10\/example-note-in-twonote-app-spanned-with-a-writt.png 1063w, https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2021\/10\/example-note-in-twonote-app-spanned-with-a-writt-300x232.png 300w, https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2021\/10\/example-note-in-twonote-app-spanned-with-a-writt-1024x793.png 1024w, https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2021\/10\/example-note-in-twonote-app-spanned-with-a-writt-768x595.png 768w\" sizes=\"(max-width: 1063px) 100vw, 1063px\" \/>\n<em>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.<\/em><\/p>\n<h3>Highly customizable pen styles<\/h3>\n<p>As mentioned above, the Ink SDK defines the <strong>DynamicPaintHandler<\/strong> 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.<\/p>\n<p>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.<\/p>\n<pre>\/**\r\n * Renders the ink with transparency linked to the pressure on the pen.\r\n *\/\r\ninner class FancyPaintHandler : InkView.DynamicPaintHandler {\r\n    override fun generatePaintFromPenInfo(penInfo: InputManager.PenInfo): Paint {\r\n        val paint = Paint()\r\n        val alpha = penInfo.pressure * 255\r\n\r\n        paint.color = Color.argb(\r\n            alpha.toInt(),\r\n            drawView.color.red,\r\n            drawView.color.green,\r\n            drawView.color.blue\r\n        )\r\n        paint.isAntiAlias = true\r\n        \/\/ Set stroke width based on display density.\r\n        paint.strokeWidth = when (penInfo.pointerType) {\r\n            InputManager.PointerType.FINGER -&gt; drawView.strokeWidthMax\r\n            else -&gt; TypedValue.applyDimension(\r\n                TypedValue.COMPLEX_UNIT_DIP,\r\n                penInfo.pressure * (drawView.strokeWidthMax - drawView.strokeWidth) + drawView.strokeWidth,\r\n                resources.displayMetrics\r\n            )\r\n        }\r\n        paint.style = Paint.Style.STROKE\r\n        paint.strokeJoin = Paint.Join.ROUND\r\n        paint.strokeCap = Paint.Cap.ROUND\r\n\r\n        return paint\r\n    }\r\n\r\n    override fun selectInkingMode(): InputManager.InkingType {\r\n        return InputManager.InkingType.INKING\r\n    }\r\n}<\/pre>\n<p>Since the Ink SDK is <a href=\"https:\/\/github.com\/microsoft\/surface-duo-sdk\/tree\/main\/inksdk\">open source<\/a>, 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\u2019re looking to add inking support to your app and need a good starting place, the Ink SDK is the perfect resource for you!<\/p>\n<h2>Emulator support<\/h2>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/surface-duo\/android-emulator-pen-support\/\">Recent updates<\/a> 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.<\/p>\n<p>Download the latest <a href=\"https:\/\/docs.microsoft.com\/dual-screen\/android\/emulator\/\">Surface Duo 2 emulator<\/a> to start building and testing dual-screen pen-enabled apps!<\/p>\n<h2>Resources and feedback<\/h2>\n<p>For more coding tips, visit the <a href=\"https:\/\/docs.microsoft.com\/dual-screen\/\">Surface Duo developer documentation<\/a> , <a href=\"https:\/\/docs.microsoft.com\/dual-screen\/android\/jetpack\/window-manager\/samples\">our samples<\/a>, and Google\u2019s <a href=\"https:\/\/developer.android.com\/large-screens\">Android large screen development guidance<\/a>.<\/p>\n<p>If you have any questions, or would like to tell us about your dual-screen pen-enabled apps, use the\u00a0<a href=\"http:\/\/aka.ms\/SurfaceDuoSDK-Feedback\">feedback forum<\/a>\u00a0or message us on Twitter\u00a0<a href=\"https:\/\/twitter.com\/surfaceduodev\">@surfaceduodev<\/a>.<\/p>\n<p>Finally, please join us for our <a href=\"https:\/\/twitch.tv\/surfaceduodev\">dual screen developer livestream<\/a> at 11am (Pacific time) each Friday \u2013 mark it in your calendar and check out the <a href=\"https:\/\/www.youtube.com\/channel\/UClGu9QLtPNz8OdddBfhZXPA\">archives on YouTube<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Hello Android developers! We\u2019ve just updated one of our existing samples \u2013 TwoNote \u2013 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 [&hellip;]<\/p>\n","protected":false},"author":72597,"featured_media":1923,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[],"class_list":["post-1920","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-surface-duo-sdk"],"acf":[],"blog_post_summary":"<p>Hello Android developers! We\u2019ve just updated one of our existing samples \u2013 TwoNote \u2013 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 [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/posts\/1920","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/users\/72597"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/comments?post=1920"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/posts\/1920\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/media\/1923"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/media?parent=1920"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/categories?post=1920"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/tags?post=1920"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}