MATCH_PARENT, если вид на сестры больше, WRAP_CONTENT, если вид сестры меньше

У меня есть два вида в макете. Я назову их View A и View B соответственно.

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

Высота родительского макета (включая View A и View B) равна WRAP_CONTENT.

Здесь высота View B равна WRAP_CONTENT. То есть его высота может быть изменена по отношению к ее содержимому.

Что я хочу сделать, это

  • Установите высоту View A height до View B height, если содержимое View A меньше View B.
  • Установите высоту View A в свою собственную высоту контента, если содержимое View A выше, чем View B.

Итак,

① Если содержимое View B выше, то высота View A установлена ​​на View B height.

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

② Если содержимое View B короче, то View A высота View A имеет собственную высоту коннектора.

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

Если родительский элемент LinearLayout (Horizontal), установка View A height на WRAP_CONTENT нарушает регистр 1, а установка View A height на MATCH_PARENT нарушает регистр 2.

Если родительский элемент RelativeLayout, установка View A для выравнивания верхней и нижней части родителя нарушает условие RelativeLayout: 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.

Как я могу решить эту проблему?

Ответ 1

Существуют разные способы сделать это, например, создав собственный пользовательский ViewGroup, возможно, на основе горизонтального LinearLayout. Тем не менее, я считаю, что наиболее простым решением было бы динамическое определение требований во время выполнения.

Рассмотрим следующий макет с двумя TextView в горизонтальном 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>

Оба обертывают их высоту, что в основном соответствует вашему первому требованию.

Теперь требование 2: для демонстрационных целей я разбил второй текст TextView на две строки, чтобы сделать его выше первого. Чтобы первый TextView соответствовал высоте, все, что вам нужно сделать, это следующее:

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;

    }
});

"Трюк" заключается в отправке в очередь просмотра, гарантируя, что логика не будет выполняться до тех пор, пока дети не будут измерены и не будут иметь действительную высоту. Для требования 2 высота первого представления должна быть изменена только в том случае, если второе представление более высокое, что и является частью метода run().

Ответ 2

Вам необходимо установить размеры представлений программным образом с помощью параметров макета. Предполагая, что вы используете LinearLayout для хранения представлений, это то, что вы сделали бы:

//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));
}

Когда вы устанавливаете свои высоты, сначала сохраняйте их как wrap_content в xml до этой модификации.

Ответ 3

Это можно решить очень легко, только из axml.

Держите родительскую высоту макета как wrap_content и установите для каждой высоты представления ребенка значение match_parent. Это приведет к тому, что высота родительского макета будет привязана к самому высокому ребенку, а каждая высота представления ребенка растянется до родителей.

<?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>