Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MATCH_PARENT if sibling view is larger, WRAP_CONTENT if sibling view is smaller

I have two views in a layout. I'll call them View A and View B respectively.

┌──────┐
│┌─┐┌─┐│
││A││B││
│└─┘└─┘│
└──────┘

The height of parent layout (which includes View A and View B) is WRAP_CONTENT.

Here, the height of View B is WRAP_CONTENT. That is, its height can be changed with respect to its content.

What I want to do is

  1. Set View A's height to View B's height if View A's content is shorter than View B's content.
  2. Set View A's height to its own content's height if View A's content is taller than View B's content.

So,

① If content of View B is taller, then View A's height is set to View B's height.

       ┌──────┐      ┌──────┐
       │┌─┐┌─┐│      │┌─┐┌─┐│
       ││ ││ ││      ││A││ ││
I want ││A││B││, not │└─┘│B││.
       ││ ││ ││      │   │ ││
       │└─┘└─┘│      │   └─┘│
       └──────┘      └──────┘

② If content of View B is shorter, then View A's height is View A's own conent's height.

       ┌──────┐      ┌──────┐
       │┌─┐┌─┐│      │┌─┐┌─┐│
       ││ ││B││      ││A││B││
I want ││A│└─┘│, not │└─┘└─┘│.
       ││ │   │      └──────┘
       │└─┘   │
       └──────┘

If the parent is LinearLayout (Horizontal), setting View A's height to WRAP_CONTENT violates case 1, and setting View A's height to MATCH_PARENT violates case 2.

If the parent is RelativeLayout, setting View A to align both its parent's top and bottom violates RelativeLayout's condition: Note that you cannot have a circular dependency between the size of the RelativeLayout and the position of its children. For example, you cannot have a RelativeLayout whose height is set to WRAP_CONTENT and a child set to ALIGN_PARENT_BOTTOM.

How can I solve this problem?

like image 801
Naetmul Avatar asked Jun 15 '13 00:06

Naetmul


People also ask

What is the difference between Match_parent and Wrap_content?

fill_parent and match_parent are the same, used when we want the height or width of a view to be as big as its parent view, fill_parent being deprecated. wrap_content is used when we want the view to occupy only as much space as required by it.

What does the Match_parent constant do?

match_parent is used for referring to the parent size either through layout_width or layout_height attributes. If we set layout_height as match_parent then the view's height will be as same as the parent's height.

What does Match_parent mean?

match_parent and fill_parent are same property, used to define width or height of a view in full screen horizontally or vertically. These properties are used in android xml files like this. android:layout_width="match_parent" android:layout_height="fill_parent"

What is wrap content in Android?

Wrap Content: Wrap content takes the length of the text and wraps its content. Example: “This is a Wrap Text”. The wrap content starts wrapping from “This” and ends at “text”.


3 Answers

There's different ways to go about this, for example by creating your own custom ViewGroup, probably based on a horizontal LinearLayout. However, I recon that the most straightforward solution would be to dynamically set the requirements at runtime.

Consider the following layout with just two TextViews in a horizontal LinearLayout:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/container"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:background="#f00"
    android:padding="10dp" >

    <TextView
        android:id="@+id/first"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="#0f0"
        android:padding="5dp"
        android:text="One line" />

    <TextView
        android:id="@+id/second"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="#00f"
        android:padding="5dp"
        android:text="Two\nlines"
        android:textColor="#fff" />

</LinearLayout>

Both wrap their height, which basically matches up to your first requirement.

Now requirement 2: for demonstration purposes, I've broken the second TextView's text up into two lines, in order to make it taller than the first one. To make the first TextView match it's height, all you have to do is this:

LinearLayout container = (LinearLayout) findViewById(R.id.container);
final TextView first = (TextView) findViewById(R.id.first);
final TextView second = (TextView) findViewById(R.id.second);

container.post(new Runnable() {
    @Override public void run() {
        int h1 = first.getMeasuredHeight();
        int h2 = second.getMeasuredHeight();
        if (h1 < h2) first.getLayoutParams().height = h2;

    }
});

The 'trick' is to post to the view's queue, ensuring the logic will not get executed until the children have been measured and have a valid height. For requirement 2, the height of the first view will only have to be changed if the second view is taller, which is exactly what the part in the run() method does.

like image 132
MH. Avatar answered Oct 07 '22 21:10

MH.


You need to set the dimensions of the views programmatically using layout params. Assuming that you are using a LinearLayout to hold the views this is what you would do:

//the views are called a and b
LinearLayout.LayoutParams aParams = a.getLayoutParams();
LinearLayout.LayoutParams bParams = b.getLayoutParams();
int aWidth = aParams.width;
int aHeight = aParams.height;
int bWidth = bParams.width;
int bHeight = bParams.height;
if (aHeight >= bHeight) {
    // do nothing
}
else {
    a.setLayoutParams(new LinearLayout.LayoutParams(aWidth, bHeight));
}

When you set their heights originally keep them as wrap_content in the xml, prior to this modification.

like image 44
Jackson Kulik Avatar answered Oct 07 '22 22:10

Jackson Kulik


This can be solved very easily, from just the axml.

Keep the parent layout's height as wrap_content and set every child view's height to be match_parent. This will cause the parent layout's height to wrap to the highest child, and every child view's height to stretch to the parents.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:orientation="horizontal"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content">
    <TextView
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:text="text" />
    <TextView
      android:layout_width="wrap_content"
      android:layout_height="match_parent"
      android:text="More\ntext" />
</LinearLayout>
like image 37
Moffen Avatar answered Oct 07 '22 22:10

Moffen