I've implemented this by placing the image in a RelativeLayout (FrameLayout would work too), and then adding each outlined view programatically. If you know the x and y origin (perhaps as a ratio to the image) and the size for each area, you can easily inflate each view/area (with a black border, transparent center), make it clickable and set a listener, and then set it's origin by adjusting it's margins. You may want to perform all of this after the image has finished laying out:
I put this in onActivityCreated
of my Fragment
, but other lifecycle methods would work too...
ViewTreeObserver vto = image.getViewTreeObserver();
vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
if (image.getMeasuredHeight() > 0) {
addHotSpots();
ViewTreeObserver obs = image.getViewTreeObserver();
obs.removeGlobalOnLayoutListener(this);
}
}
});
And this is how I actually place all the hotspots/areas:
protected void addHotSpots() {
HotSpot[] hotSpots = res.hotspots;
for (HotSpot hs : hotSpots) {
addHotSpotToImage(hs);
}
private void addHotSpotToImage(HotSpot hs) {
int height = image.getMeasuredHeight();
int width = image.getMeasuredWidth();
//this piece will probably be different for you
//depending on what you know about the area's intended size/position
double hsHeightRatio = hs.lr.y - hs.ul.y;
double hsWidthRatio = hs.lr.x - hs.ul.x;
double leftMargin = hs.ul.x * width;
double topMargin = hs.ul.y * height;
double hsHeight = height * hsHeightRatio;
double hsWidth = width * hsWidthRatio;
LayoutInflater vi = (LayoutInflater) image.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View newSpot = vi.inflate(R.layout.question_hotspot, null);
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams((int) hsWidth, (int) hsHeight);
newSpot.setTag(hs.key);
newSpot.setFocusable(true);
newSpot.setClickable(true);
newSpot.setFocusableInTouchMode(true);
newSpot.setOnTouchListener(this);
params.topMargin = (int) topMargin;
params.leftMargin = (int) leftMargin;
image.addView(newSpot, params);
}