1

On the following image I would like to detect what part of the human body the on touch event happened. My idea was to have a GridView and determine the position of the human body where the touch event happened. A GridView seems an overkill though. Would it be a better approach with a different layout ?

 gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
                BodyImage item = (BodyImage) parent.getItemAtPosition(position);
                switch (position) {
                    case 0:

                        // code for head

                        break;
                    case 1:
                        // code for nose 
                    case 2:
                        // code for n-human part

Here is the image to give the audience an idea enter image description here

3 Answers3

4

Foremost thanks to Kris Larson for his answer above. The idea is to superpose two images seen here Images to be superposed in the Fragment and hide the image that has the color. The image on the right was colored used the open source Gimp GIMP

Then on the FrameLayout I added the two images Dynamically:

/**
 * A Fragment that launches Draw
 */
public static class DrawSectionFragment extends Fragment {

    public static final String ARG_SECTION_NUMBER = "section_number";
    boolean touching = false;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        ........

        View rootView = inflater.inflate(R.layout.image_superposed, container, false);
      //  View rootView = inflater.inflate(R.layout.image_superposed, container);
        final ImageView iv1 = (ImageView) rootView.findViewById(R.id.imgSecond);
        iv1.setImageDrawable(getResources().getDrawable(R.drawable.twocolor1));
        final Bitmap bitmap = ((BitmapDrawable)iv1.getDrawable()).getBitmap();

        iv1.setOnTouchListener(new View.OnTouchListener(){
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                CxMediaPlayer mxMediaPlayer;
                mxMediaPlayer = new CxMediaPlayer(getActivity().getBaseContext());
                switch (event.getAction()) {

                    case MotionEvent.ACTION_DOWN:
                        // TODO Auto-generated method stub
                        touching = true;
                        Matrix inverse = new Matrix();
                        iv1.getImageMatrix().invert(inverse);
                        float[] touchPoint = new float[]{event.getX(), event.getY()};
                        inverse.mapPoints(touchPoint);
                        int xCoord = Integer.valueOf((int) touchPoint[0]);
                        int yCoord = Integer.valueOf((int) touchPoint[1]);

                        int pixel = bitmap.getPixel(xCoord, yCoord);

                        int redValue = Color.red(pixel);
                        int blueValue = Color.blue(pixel);
                        int greenValue = Color.green(pixel);

                        if (pixel == Color.CYAN) {
                            //mxMediaPlayer = new CxMediaPlayer(getActivity().getBaseContext());
                            mxMediaPlayer.playShortResource(getActivity().getBaseContext(), 1) ;
                        }
                        if (pixel == Color.YELLOW) {

                            mxMediaPlayer.playShortResource(getActivity().getBaseContext(), 2) ;
                        }
                        if (pixel == Color.rgb(0,0,255)) {
                            CxMediaPlayer mxMediaPlayer1 = new CxMediaPlayer(getActivity().getBaseContext());
                            mxMediaPlayer1.playShortResource(getActivity().getBaseContext(), 2) ;
                        }

                        break;
                    case MotionEvent.ACTION_CANCEL:
                    case MotionEvent.ACTION_UP:
                        touching = false;
                        //invalidate();
                        break;

                }
               // mxMediaPlayer.Release();
                return true;
            }
        });;


        return rootView;
    }
2

Our company did exactly this in our Android app for diagnostic decision support.

We started out with the image of the human form (called a homunculus). Our graphic designer also created transparent overlays of each of the body parts highlighted (to show selection), and also mapped out complex polygons for each area that could be activated by touch. In other words, each touchable area was represented by a set of (x,y) coordinates that roughly outlined the body part.

For the layout, the main container is a FrameLayout containing an ImageView with the homunculus image, overlaid with ImageViews for each highlight image with visibility="gone". An OnTouchListener is used instead of an OnClickListener so that we can get the (x,y) coordinates from the MotionEvent parameter.

In the OnTouchListener, we iterate through all the polygons and hit test to see if a polygon contains the point. If so, then we have our part.

We have a custom Polygon class mainly to do the hit testing. A contains(int x, int y) method was implemented to do the hit testing and used code based on this algorithm: http://alienryderflex.com/polygon/

For drawing the highlight, we have a PolygonDrawable class that creates a Path using the coordinates, creates a PathShape from the path that can be rendered to the UI.

kris larson
  • 30,387
  • 5
  • 62
  • 74
  • I could post some proprietary code, but I prefer to keep my job. Let me know if you offer a bounty for this, I can work up a demo project for you. – kris larson Dec 23 '15 at 18:24
  • HI Kris. first able, Thanks for all your info. The least I would like is you to loose your job!. Your answer led me to exactly what I need it. I went into a the open source GIMP [link](https://www.gimp.org/downloads/) and colored the regions as you suggested. Then I took your suggestion to override the OnCreate event. Amazingly it worked at the first try. Here is the code : – Eric Echeverri Dec 23 '15 at 18:40
  • Could elaborate more in this paragraph : overlaid with ImageViews for each highlight image with visibility="gone". AnOnTouchListener – Eric Echeverri Dec 23 '15 at 19:00
  • Okay, I will go back and update that in a while. I just looked the code and first of all, it isn't what I described, and second, I would do it a little differently with what I know now. – kris larson Dec 23 '15 at 19:05
  • And frankly, I think you should accept @EricEcheverri 's answer; he actually posted some code. An upvote is enough for me. – kris larson Dec 23 '15 at 19:06
  • @EricEcheverri is me Kris! – Eric Echeverri Dec 23 '15 at 19:48
  • Basically the only code I need, is the snipset of code where you instantiate the two ImageViews and the snipset of code where you set on of the imageView to gone – Eric Echeverri Dec 23 '15 at 20:03
0

Create a custom ImageView and override onTouch event, you can detect position of user touch.

@Override
public boolean onTouchEvent(MotionEvent event) {
    event.getX();// X pos of touch 
    event.getY();// Y pos of touch
    return super.onTouchEvent(event);
}
xtr
  • 5,870
  • 1
  • 21
  • 23