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
View A
's height to View B
's height if View A
's content is shorter than View B
's content.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?
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.
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.
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"
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”.
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 TextView
s 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.
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.
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>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With