androidsvgmotioneventtouchimageviewsvg-android

Zoomable SVG with clickable areas - Android


I'm making very simple application. It needs to show one SVG containing generalised world map. By clicking on city's name (svg rectangle), I need to show another SVG that corresponds to that city. Also, all SVGs must support zooming and panning.

I managed to make SVGs support zooming and panning and that works perfect. For that purpose, I'm using svg-android library for rendering SVGs and customized TouchImageView for panning, zooming and capturing scale and touch events. But, it seems to be impossible to make clickable regions on SVGs in Android.

I tried brute force, to recalculate position of my interesting areas on every user interaction (on touch or on scale) and on every click on the SVG to check if my areas (List of rectangles) contain that point, and perform corresponding action.

That doesn't work because I can't understand rule for calculating MotionEvent#getX/Y and similar methods. Maybe I could achieve this for fixed SVG but for zoomable, I really can't.

Any hints? Is this even possible in Android?


Solution

  • First of all, really sorry for late answer. Hope it is not too late for everyone :)

    I made a GitHub repo with code sample (not with working app), so please, use it! :)

    Use repo's readme for some details.

    Core solution:

    SVG svg = SVGParser.getSVGFromResource(getResources(), R.raw.world_map);
    
    // Get image view (this is our SVG map that is going to be clickable and zoomable):
    ImageView touchImageView = (ImageView) view.findViewById(R.id.touchImageView);
    
    // Create drawable (will convert svg to drawable so we can set it to image view as a bitmap):
    PictureDrawable image = svg.createPictureDrawable();
    Bitmap b = drawableToBitmap(image); // refer to WorldMapFragment for source code of the converting method 
    touchImageView.setImageBitmap(b);
    
    // Create image with clickable areas from previous image view and set listener to id (listener of type OnClickableAreaClickedListener created in onAttach callback):
    ClickableAreasImage clickableAreasImage = new ClickableAreasImage(new PhotoViewAttacher(touchImageView), listener);
    
    // Define your clickable areas
    // parameter values (pixels): (x coordinate, y coordinate, width, h eight) and assign an object to it
    List<ClickableArea> clickableAreas = new ArrayList<>();
    Map<String, FintemCity> cities = svg.getCities();
    for (String key : cities.keySet()){
      clickableAreas.add(cities.get(key).toClickableArea(getMetrics()));
    }
    
    // Set your clickable areas to the image
    clickableAreasImage.setClickableAreas(clickableAreas);
    

    Votes are appreciated! :)