0

I'm building an injection tracking app for diabetics and other people who take regular injections, and I'm trying to align 8 checkboxes on top of an image of a body so the user can specify where they got the injection. The problem is that aligning it right now only works for a very specific screen size, and whenever the size is different, the checkboxes move around and end up not on the correct body part. Is there some way I can accomplish this? Hardcoding the margins doesn't seem to be working well. Any help would be appreciated. Thank you.

Here's what i want it to look like ideally, and here is what it actually looks like on a specific screen size which shifts everything around. It gets more extreme than that of course the larger or smaller the screen size.

and here's my code:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.example.android.injectiontracker.MainActivity">

<ImageView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_below="@id/date_and_time_layout"
    android:src="@drawable/blank_body" />

<CheckBox
    android:id="@+id/abdomen_left"
    style="@style/InjectionCheckbox"
    android:layout_alignBaseline="@+id/abdomen_right"
    android:layout_alignBottom="@+id/abdomen_right"
    android:layout_toRightOf="@+id/abdomen_right"
    android:layout_toEndOf="@+id/abdomen_right" />

<CheckBox
    android:id="@+id/thigh_left"
    style="@style/InjectionCheckbox"
    android:layout_alignBaseline="@+id/thigh_right"
    android:layout_alignBottom="@+id/thigh_right"
    android:layout_toRightOf="@+id/thigh_right"
    android:layout_toEndOf="@+id/thigh_right" />



<ImageView
    android:id="@+id/save"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true"
    android:layout_alignParentRight="true"
    android:src="@drawable/ic_save_black_48dp" />


<CheckBox
    android:id="@+id/buttocks_left"
    style="@style/InjectionCheckbox"
    android:layout_below="@+id/abdomen_left"
    android:layout_alignLeft="@+id/arm_left"
    android:layout_alignStart="@+id/arm_left"
    android:layout_marginLeft="24dp"
    android:layout_marginStart="24dp" />

<CheckBox
    android:id="@+id/arm_left"
    style="@style/InjectionCheckbox"
    android:layout_marginRight="74dp"
    android:layout_marginEnd="74dp"
    android:layout_above="@+id/abdomen_left"
    android:layout_toLeftOf="@+id/save"
    android:layout_toStartOf="@+id/save"
    android:layout_marginBottom="16dp" />

<CheckBox
    android:id="@+id/buttocks_right"
    style="@style/InjectionCheckbox"
    android:layout_width="wrap_content"
    android:layout_alignBaseline="@+id/buttocks_left"
    android:layout_alignBottom="@+id/buttocks_left"
    android:layout_toRightOf="@+id/buttocks_left"
    android:layout_toEndOf="@+id/buttocks_left" />

<CheckBox
    android:id="@+id/arm_right"
    style="@style/InjectionCheckbox"
    android:layout_alignBaseline="@+id/arm_left"
    android:layout_alignBottom="@+id/arm_left"
    android:layout_toRightOf="@+id/buttocks_right"
    android:layout_toEndOf="@+id/buttocks_right" />

<CheckBox
    android:id="@+id/abdomen_right"
    style="@style/InjectionCheckbox"
    android:layout_marginLeft="55dp"
    android:layout_marginStart="55dp"
    android:layout_centerVertical="true"
    android:layout_alignParentLeft="true"
    android:layout_alignParentStart="true" />

<CheckBox
    android:id="@+id/thigh_right"
    style="@style/InjectionCheckbox"
    android:layout_marginTop="11dp"
    android:layout_below="@+id/buttocks_left"
    android:layout_alignLeft="@+id/abdomen_right"
    android:layout_alignStart="@+id/abdomen_right" />

Dina
  • 23
  • 6
  • 1
    try constraint layout – Mrinmoy Jan 10 '17 at 09:49
  • try this library [link] (https://github.com/Lukle/ClickableAreasImages) In which you can check and uncheck checkboxes on a portion clicked by user. Hope it will retain on bigger screen sizes as well .Not checked . Hope it will helpful. – Rv Lalwani Jan 10 '17 at 09:52
  • Use Framelayout to solve this issue – samsad Jan 10 '17 at 09:53
  • you can try this answer [link](http://stackoverflow.com/questions/3294590/set-the-absolute-position-of-a-view/27824866#27824866) – Rv Lalwani Jan 10 '17 at 09:58
  • Thank you all so much for the suggestions. Right now PercentFrameLayout as suggested below works well enough for Portrait orientation, so i'm planning to try the library Rv Lalwani linked to see if i can get it to work for landscape as well. I'll let you know how that goes :-) If that doesn't work i'll look more into constraint layout. I tried it before but since i'm very new to android i couldn't quite figure out how to get it to work. – Dina Jan 12 '17 at 23:35

1 Answers1

0

I think what will help you the most here is PercentFrameLayout.

This is a support library so you have to add

    compile 'com.android.support:percent:24.2.1'

to your build.gradle file (the version will vary depending on what you've updated).

Your current layout uses wrap_content for the width and height of the ImageView. If your screen width is smaller that the width of the image, then the ImageView is going to have a different aspect ratio than the image itself, and this is going to make getting an accurate layout difficult.

A good approach is to have at least two layouts

  • one layout for smaller devices like phones where the screen width may be smaller than your image
  • another layout for larger devices like tablets where the screen width is larger than your image

See How to support multiple screens if you aren't familiar with alternate layouts.

First you need to ensure that the aspect ratio of the ImageView matches the image. Do this by specifying android:adjustViewBounds="true" along with a width of match_parent and a height of wrap_content.

Then wrap the ImageView in a PercentFrameLayout that also has a width of match_parent and a height of wrap_content.

Now you have a view that is somewhat predictable for using percentages. I downloaded the image that you linked to and used it to come up with this:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                xmlns:app="http://schemas.android.com/apk/res-auto"
                xmlns:tools="http://schemas.android.com/tools"
                android:id="@+id/activity_main"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:orientation="vertical">

    <android.support.percent.PercentFrameLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true">

        <ImageView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:adjustViewBounds="true"
            android:src="@drawable/blank_body" />

        <CheckBox
            android:id="@+id/abdomen_left"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:layout_marginLeftPercent="15.5%"
            app:layout_marginTopPercent="32%"/>

        <CheckBox
            android:id="@+id/abdomen_right"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:layout_marginLeftPercent="25%"
            app:layout_marginTopPercent="32%"/>

        <CheckBox
            android:id="@+id/thigh_left"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:layout_marginLeftPercent="15.5%"
            app:layout_marginTopPercent="47%"/>

        <CheckBox
            android:id="@+id/thigh_right"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:layout_marginLeftPercent="25%"
            app:layout_marginTopPercent="47%"/>

        <CheckBox
            android:id="@+id/arm_left"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:layout_marginLeftPercent="57%"
            app:layout_marginTopPercent="22%"/>

        <CheckBox
            android:id="@+id/arm_right"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:layout_marginLeftPercent="82.5%"
            app:layout_marginTopPercent="22%"/>

        <CheckBox
            android:id="@+id/buttocks_left"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:layout_marginLeftPercent="64%"
            app:layout_marginTopPercent="38.5%"/>

        <CheckBox
            android:id="@+id/buttocks_right"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:layout_marginLeftPercent="73.5%"
            app:layout_marginTopPercent="38.5%"/>

    </android.support.percent.PercentFrameLayout>

</RelativeLayout>

(Sorry, I remove your styles and such since I didn't have access to those.)

For the larger devices, your alternate layout should specify a fixed width for the PercentFrameLayout:

    <android.support.percent.PercentFrameLayout
        android:layout_width="600dp"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true">

then you would position this within your larger RelativeLayout as you require (I show center/top as an example).

This should get you a pretty acceptable result.

You will still see some slight distortion depending screen width since you are measuring to the left and top of the checkbox. For a pixel-perfect layout, you would need to make a custom layout component that can position the centers of the checkboxes right at the points of interest.

kris larson
  • 30,387
  • 5
  • 62
  • 74
  • Thank you so much. This is very close to what I want. I've disabled landscape mode because everything just gets wonky when i use it, but if you have ideas on how to make it work for landscape as well, that would be great. I tried putting everything inside a scroll view, then setting the relative layout and the percent frame layout to wrap content instead of match parent, but that didn't work. Right now what happens is that 6 of the chechboxes move to the top of the screen and two disappear behind other checkboxes. – Dina Jan 12 '17 at 23:10
  • My suggestion for having an alternate layout with a fixed width should help with that. You should be able to get that to work in a scrolling view. If you can't get that to work, add the landscape XML to your question and I'll have a look. – kris larson Jan 13 '17 at 15:02