Flutter: Create BodyMap Widget with selectable body parts

Viewed 843

I hope you're doing fine in tough times like these.

I wanted to ask this question before I lose myself in a forest full of widget trees. Currently, I am developing an app in flutter for my master thesis and one functionality is going to be the following:

user should be able to select a body part from a body map, and the selected part should be highlighted. I will attach a screenshot for better understanding.

I know it's more of a "how would you do this?" question rather than a problem but still, maybe someone has a better idea than me.

Body Map with one selected part

So my approach to this would be:

  • use a blank image of a human body as the background in a Stack

  • with Positioned Widgets, place circular buttoms on top of the selectable body parts

Would this seem like an ok-ish solution or is there a better approach to this?

All the best!

1 Answers

My concern would be the buttons not lining up with the image on different-sized screens. Here is some pseudocode to show how I would do it. Hopefully, you find this helpful.

/// These are all of the selectable body parts.
enum BodyParts {
  leftArm, head, torso, leftLeg, rightLeg, rightArm
}

/// This is the height of the entire body diagram.
final double bodyHeight = 650.0;

/// This is the height of the head.
final double headHeight = 50.0;

/// This will be the selected body part.
BodyParts selected;

// Display the entire body.
Column(
  children[
    // The left side of the body.
    Column(
      children[
        // To account for the height of the head.
        SizedBox(height: headHeight),
        
        // Left arm
        MaterialButton(
          height: 300.0,
          child: Image.asset(
            selected == BodyParts.leftArm
                ? "assets/images/left_arm_selected.png"
                : "assets/images/left_arm.png"
          ),
          onPressed(() => setState(() => selected = BodyParts.leftArm)),
        ),
      ],
    ),

    // The middle of the body.
    Column(
      children[
        // Head
        MaterialButton(
          height: headHeight,
          child: Image.asset(
            selected == BodyParts.head
                ? "assets/images/head_selected.png"
                : "assets/images/head.png"
          ),
          onPressed(() => setState(() => selected = BodyParts.head)),
        ),

        // Torso
        MaterialButton(
          height: 250.0,
          child: Image.asset(
            selected == BodyParts.torso
                ? "assets/images/torso_selected.png"
                : "assets/images/torso.png"
          ),
          onPressed(() => setState(() => selected = BodyParts.torso)),
        ),

        // Legs
        Row(
          children[
            // Left leg
            MaterialButton(
              height: 300.0,
              child: Image.asset(
                selected == BodyParts.leftLeg
                    ? "assets/images/left_leg_selected.png"
                    : "assets/images/left_leg.png"
              ),
              onPressed(() => setState(() => selected = BodyParts.leftLeg)),
            ),

            // Right leg
            MaterialButton(
              height: 300.0,
              child: Image.asset(
                selected == BodyParts.rightLeg
                    ? "assets/images/right_leg_selected.png"
                    : "assets/images/right_leg.png"
              ),
              onPressed(() => setState(() => selected = BodyParts.rightLeg)),
            ),
          ],
        )
      ],
    ),

    // The right side of the body.
    Column(
      children[
        // To account for the height of the head.
        SizedBox(height: headHeight),
        
        // Right arm
        MaterialButton(
          height: 300.0,
          child: Image.asset(
            selected == BodyParts.rightArm
                ? "assets/images/right_arm_selected.png"
                : "assets/images/right_arm.png"
          ),
          onPressed(() => setState(() => selected = BodyParts.rightArm)),
        ),
      ],
    ),
  ],
)

Please keep in mind, this is not functioning code; it is pseudocode to help explain a possible way to solve this problem.

The above code would take a broken-up version of the body image and map each of the pieces to its own button. Once a button is selected, a different version of the body part will be shown to indicate it is selected.

Related