Search code examples
androidandroid-layoutandroid-linearlayoutandroid-relativelayout

Align Android Relative Layout Items w/ Dynamic Size Item in Different Linear Layout


I haven't been able to find anything out there on aligning a widget from a RelativeLayout to a widget within a horizontal LinearLayout. Aligning from one layout to another is almost not even mentioned on the Internet. I thought my question might be easiest explained with a picture. Please pardon the crude drawing:

enter image description here

This really sums up what I'm trying to do. The green is a relative layout and the blue is a horizontal linear layout with each item having a width of 'match_parent' and a weight of '1' for equal distribution across the linear layout - the purpose of this is to take advantage of wider screens and landscape mode by expanding items B-E, the most important information in my application.

I have a statically-sized image (A) to the left of the linear layout. The linear layout is relatively-placed 5dp to the right of A. Items B-D have a rightMargin of 8dp for spacing. F is a pair of TextViews that are aligned to the start of A. G is a pair of TextViews that are aligned to the right of the screen.

What I want to do is:

  • Align the right (end) of F with the right (end) of B.
  • Align the left (start) of G with the left (start) of C.
  • Have this maintain this relationship as the device is rotated into landscape mode.

I have tried aligning the alignEnd, alignToEnd, and alignRight of the relative layout widgets to the widgets in the linear layout, but Android Studio rejects that since they're not siblings in a RelativeLayout. I could do this programmatically and calculate it in a PreDrawListener (add width of A + 5dp + width of B), but I'd rather do it in the layout, if possible.

Here's my layout xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="210dp"
    android:background="#FFFFFF">

    <ImageView
        android:id="@+id/imageView"
        android:layout_width="150dp"
        android:layout_height="150dp"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_marginBottom="1dp"
        android:layout_marginLeft="5dp"
        android:layout_marginRight="5dp"
        android:layout_marginTop="9dp"
        android:cropToPadding="false"
        android:src="@drawable/avatar"/>

    <TextView
        android:id="@+id/Name"
        android:layout_width="wrap_content"
        android:layout_height="31dp"
        android:layout_marginLeft="5dp"
        android:layout_marginTop="155dp"
        android:ellipsize="end"
        android:gravity="center_vertical|left"
        android:paddingTop="3dp"
        android:text="Name"
        android:textColor="#000000"
        android:textSize="22sp"/>

    <TextView
        android:id="@+id/id"
        android:layout_width="150dp"
        android:layout_height="24dp"
        android:layout_marginLeft="5dp"
        android:layout_marginTop="185dp"
        android:ellipsize="end"
        android:gravity="top|left"
        android:paddingTop="-5dp"
        android:text="ID"
        android:textColor="#000000"
        android:textSize="18sp"/>

    <TextView
        android:id="@+id/age"
        android:layout_width="150dp"
        android:layout_height="24dp"
        android:layout_marginLeft="155dp"
        android:layout_marginTop="185dp"
        android:ellipsize="end"
        android:gravity="top|left"
        android:paddingTop="-5dp"
        android:text="Age"
        android:textColor="#000000"
        android:textSize="18sp"/>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="159dp"
        android:layout_marginLeft="160dp"
        android:orientation="horizontal">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_marginRight="8dp"
            android:layout_weight="1"
            android:orientation="vertical">

            <TextView
                android:id="@+id/pTitle"
                android:layout_width="match_parent"
                android:layout_height="30dp"
                android:gravity="center"
                android:text="Title"
                android:textColor="#ffffffff"
                android:textSize="14sp"
                android:textStyle="bold"/>

            <com.github.mikephil.charting.charts.LineChart
                android:id="@+id/chart1"
                android:layout_width="match_parent"
                android:layout_height="match_parent"/>

        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_marginRight="8dp"
            android:layout_weight="1"
            android:orientation="vertical">

            <TextView
                android:id="@+id/rTitle"
                android:layout_width="match_parent"
                android:layout_height="30dp"
                android:gravity="center"
                android:text="Title"
                android:textColor="#ffffffff"
                android:textSize="14sp"
                android:textStyle="bold"/>

            <com.github.mikephil.charting.charts.LineChart
                android:id="@+id/chart2"
                android:layout_width="match_parent"
                android:layout_height="match_parent"/>
        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_marginRight="8dp"
            android:layout_weight="1"
            android:orientation="vertical">

            <TextView
                android:id="@+id/hTitle"
                android:layout_width="match_parent"
                android:layout_height="30dp"
                android:gravity="center"
                android:text="Title"
                android:textColor="#ffffffff"
                android:textSize="14sp"
                android:textStyle="bold"/>

            <com.github.mikephil.charting.charts.LineChart
                android:id="@+id/chart3"
                android:layout_width="match_parent"
                android:layout_height="match_parent"/>
        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:orientation="vertical">

            <TextView
                android:id="@+id/sTitle"
                android:layout_width="match_parent"
                android:layout_height="30dp"
                android:gravity="center"
                android:text="Title"
                android:textColor="#ffffffff"
                android:textSize="14sp"
                android:textStyle="bold"/>

            <com.github.mikephil.charting.charts.LineChart
                android:id="@+id/chart4"
                android:layout_width="match_parent"
                android:layout_height="match_parent"/>

        </LinearLayout>

    </LinearLayout>

</RelativeLayout>

Is this possible? Thanks.


Solution

  • OK, here's how I solved it:

    // Pre-Draw Task
    ViewTreeObserver userImageVTO = userImage.getViewTreeObserver();
    userImageVTO.addOnPreDrawListener( new ViewTreeObserver.OnPreDrawListener() {
        public boolean onPreDraw() {
    
            // Set Alignment Widths
            name.setWidth( imageView.getWidth() + ( ( imageView.getWidth() / 150 ) * 5 ) + chart1.getWidth() );  // Get the Pixel Density (Since Image is 150dp) for 5dp of Padding
            age.setWidth( chart1.getWidth() );
    
            return true;
        }
    });
    

    This is in my custom ListAdapter's getView(). I calculated the width of F with the known-sized imageView (150dp square) and padding (5dp) plus the retrieved width of chart1. Then, in the XML I added this to G:

    android:layout_toRightOf="@id/age"
    android:layout_marginLeft="8dp"
    

    That allows G to expand/contract on rotation since it's set to always be 8dp to the right of F.