define('DISALLOW_FILE_EDIT', true);{"id":4342,"date":"2014-02-19T18:39:58","date_gmt":"2014-02-19T23:39:58","guid":{"rendered":"http:\/\/www.unfocus.com\/?p=4342"},"modified":"2014-05-14T23:47:02","modified_gmt":"2014-05-15T03:47:02","slug":"svgview-for-xamarin-android","status":"publish","type":"post","link":"http:\/\/www.unfocus.com\/2014\/02\/19\/svgview-for-xamarin-android\/","title":{"rendered":"SVGView for Xamarin.Android"},"content":{"rendered":"

Instead of making dozens of PNG files<\/a> for all the various screen sizes<\/a> for icon assets, I wanted to use vector graphics<\/a> (such as SVG<\/a>) in an\u00a0Android<\/a> app I’m building<\/a> with Xamarin.Android<\/a>. There is a tool for generating images<\/a>, and that’s better than nothing, but SVG is even easier, and I’m all about easier. I thought this would be relatively easy to do, but it turns out Android has no built in support for vector image formats.<\/p>\n

Xamarin<\/a> has a nice binding project and sample<\/a> for using an SVG library (I think it wraps SVG-Android on GitHub<\/a>) in Android apps, but it wasn’t clear how to use that, and there was an annoying gotcha I hit along the way, that I thought I’d document here.<\/p>\n

There are two projects in the sample solution. One is the library project, and the other is a sample project, with sample art that you can build to see it working. What we want to do is build the library, and then copy the necessary components into our own Android app project. Here’s how to do that using Xamarin Studio<\/a>.<\/p>\n

    \n
  1. Download and unzip the project files from Xamarin<\/a> (or fork it on GitHub<\/a>). Open the Solution in Xamarin Studio. You should see something like this:\"\"<\/li>\n
  2. Put the build mode into “Release” and then right click (or control click) on SvgAndroid (Highlighted in the screenshot above), and then click Build SvgAndroid (or highlight the project and press cmd+K). This will make a release .dll file (a .NET assembly) in the bin folder:
    \n\"\"<\/li>\n
  3. You’ll need to copy two files into your own project. SvgAndroid.dll from bin\/Release, and svg-android-1.1.jar from the Jars folder. I put SvgAndroid.dll file in the project\/Assemblies folder in in my project hierarchy so that the dll could be managed in git with the rest of my project (the git rule of thumb – include what you need to build, and I need this dll to build the app). The jar file – svg-android-1.1.jar – went into the project\/Jars folder.<\/li>\n
  4. Add the assembly to the project: Right click on references in the Solution panel, and choose “Edit References.” In there, add the .dll under the “.Net Assemblies” tab.<\/li>\n
  5. Add the jar file: Add the jar file to your project using add file or add folder (to add the entire Jars folder). Then right click the jar file, and choose “Build Action” -> “AndroidJavaLibrary” to make sure it gets packaged with your application.<\/li>\n<\/ol>\n

    That’s it! Those two files are all you need. Now you can create an SVGView class, and use that in your axml layouts. Here’s a quick and dirty example of the class:<\/p>\n

    [csharp]using System;
    \nusing System.Collections.Generic;
    \nusing System.Linq;
    \nusing System.Text;
    \nusing Android.App;
    \nusing Android.Content;
    \nusing Android.OS;
    \nusing Android.Runtime;
    \nusing Android.Util;
    \nusing Android.Views;
    \nusing Android.Widget;
    \nusing Com.Larvalabs.Svgandroid;<\/p>\n

    namespace unFocus
    \n{
    \n\tpublic class SVGView : ImageView
    \n\t{
    \n\t\tprotected string svgSrc;
    \n\t\tpublic string SVGSrc {
    \n\t\t\tget {
    \n\t\t\t\treturn svgSrc;
    \n\t\t\t}
    \n\t\t\tset {
    \n\t\t\t\tsvgSrc = value;
    \n\t\t\t\tsetupSVG ();
    \n\t\t\t}
    \n\t\t}<\/p>\n

    \t\tpublic SVGView (Context context) :
    \n\t\t\tbase (context)
    \n\t\t{
    \n\t\t\tInitialize ();
    \n\t\t}<\/p>\n

    \t\tpublic SVGView (Context context, IAttributeSet attrs) :
    \n\t\t\tbase (context, attrs)
    \n\t\t{
    \n\t\t\tInitialize (attrs);
    \n\t\t}<\/p>\n

    \t\tpublic SVGView (Context context, IAttributeSet attrs, int defStyle) :
    \n\t\t\tbase (context, attrs, defStyle)
    \n\t\t{
    \n\t\t\tInitialize (attrs);
    \n\t\t}<\/p>\n

    \t\tvoid Initialize ()
    \n\t\t{
    \n\t\t}<\/p>\n

    \t\tvoid Initialize (IAttributeSet attrs)
    \n\t\t{
    \n\t\t\tvar a = Context.ObtainStyledAttributes(attrs, Resource.Styleable.SVGView);
    \n\t\t\tSVGSrc = a.GetString(Resource.Styleable.SVGView_svgSrc);
    \n\t\t\ta.Recycle ();
    \n\t\t}<\/p>\n

    \t\tvoid setupSVG ()
    \n\t\t{
    \n\t\t\t\/\/ svg-android doesn’t work in hardware mode, so set software
    \n\t\t\tSetLayerType (LayerType.Software, null);<\/p>\n

    \t\t\tif (null == SVGSrc)
    \n\t\t\t\treturn;
    \n\t\t\tSVG svg = SVGParser.GetSVGFromAsset (Context.Assets, SVGSrc);
    \n\t\t\tSetImageDrawable (svg.CreatePictureDrawable ());
    \n\t\t\tInvalidate ();
    \n\t\t}
    \n\t}
    \n}[\/csharp]<\/p>\n

    And in values\/attrs.xml:<\/p>\n

    [xml]<?xml\u00a0version="1.0"\u00a0encoding="UTF-8"\u00a0?>
    \n <resources>
    \n \u00a0\u00a0\u00a0\u00a0<declare-styleable\u00a0name="SVGView">
    \n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<attr name="svgSrc"\u00a0format="string"><\/attr>
    \n \u00a0\u00a0\u00a0\u00a0<\/declare>
    \n <\/resources>[\/xml]<\/p>\n

    Now you can create SVGViews in axml using:<\/p>\n

    [xml]<unFocus.SVGView
    \n \u00a0\u00a0 android:svgSrc="svg\/somesvgfile.svg"
    \n \u00a0\u00a0 android:layout_width="58.0dp"
    \n \u00a0\u00a0 android:layout_height="58.0dp"
    \n \u00a0\u00a0 android:id="@+id\/icon" \/>[\/xml]<\/p>\n

    SVG files go in the Assets folder, in whatever tree you want. In this example, they are in Assets\/svg\/. Build action for svg files is “AndroidAsset,” which should be the default.<\/p>\n

    There is an irritating gotcha, that’ll have you tearing your hair out if you don’t know about it.<\/p>\n

    SVG files MUST have width and height attributes on the root element to work with this library. If you don’t have them, and Adobe Illustrator CC doesn’t add them by default, the lib will fail with cryptic error messages. The fix is easy enough, just open the SVG in Xamarin and add width and height attributes. There will already be a viewBox attribute with the correct attributes (viewBox=”0 0 70 70″ <– the second two, width and height). You’ll need to add these: width=”70px” height=”70px”.<\/p>\n

    Update:<\/strong> One other thing I forgot to mention – this didn’t work on the Xamarin Alpha for some reason. The SVGAndroid binding was failing if I remember correctly (at least that’s where the runtime\u00a0 errors seemed to originate). So if you are having trouble getting this to work, it might be something in the Alpha channel.<\/p>\n

    Update 2:<\/strong> What I’ve showed you here will work, but some folks on the Xamarin forums suggest there may be advantages to including third party code in alternative ways (like including an entire project, etc.). Have a read.<\/a><\/p>\n

    Update 3:<\/strong> SVG-Android won’t work<\/a> under hardware acceleration<\/a>, which is enabled by default in apps targetting Android 3.0 and newer. You just get a blank space. The easiest way around this is to set the Application, Activity, or the specific view you are working on to use software acceleration.<\/p>\n

    I modified the SVGView example above to do this automatically, but you can also do it yourself (using the code above) or by setting the android:layerType=”software” on the specific view (or somethings its parent).<\/p>\n

    This is worth knowing about because other types of drawables (such as animations) seem to display other types of incompatibilities with hardware acceleration (such as fuzzy low resolution renderings), and setting software mode can fix it.<\/p>\n

    Enjoy!<\/p>\n","protected":false},"excerpt":{"rendered":"

    Instead of making dozens of PNG files for all the various screen sizes for icon assets, I wanted to use vector graphics (such as SVG) in an\u00a0Android app I’m building with Xamarin.Android. There is a tool for generating images, and that’s better than nothing, but SVG is even easier, and I’m all about easier. I … Continue reading “SVGView for Xamarin.Android”<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[63,180],"tags":[225,182,30,226],"_links":{"self":[{"href":"http:\/\/www.unfocus.com\/wp-json\/wp\/v2\/posts\/4342"}],"collection":[{"href":"http:\/\/www.unfocus.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.unfocus.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.unfocus.com\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"http:\/\/www.unfocus.com\/wp-json\/wp\/v2\/comments?post=4342"}],"version-history":[{"count":3,"href":"http:\/\/www.unfocus.com\/wp-json\/wp\/v2\/posts\/4342\/revisions"}],"predecessor-version":[{"id":4388,"href":"http:\/\/www.unfocus.com\/wp-json\/wp\/v2\/posts\/4342\/revisions\/4388"}],"wp:attachment":[{"href":"http:\/\/www.unfocus.com\/wp-json\/wp\/v2\/media?parent=4342"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.unfocus.com\/wp-json\/wp\/v2\/categories?post=4342"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.unfocus.com\/wp-json\/wp\/v2\/tags?post=4342"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}