У меня есть два представления в LinearLayout
, оба из которых должны wrap_content
, чтобы они были минимально достаточно большими для отображения своего контента. Группа представлений LinearLayout
должна wrap_content
двух дочерних групп, чтобы она была достаточно большой, чтобы отображать содержимое обоих дочерних представлений.
Но после этого, если одно из двух дочерних представлений больше, другое дочернее представление должно расширяться, чтобы соответствовать родительскому представлению, чтобы заполнить оставшееся пространство, доступное для него. Содержимое двух дочерних представлений является динамическим и неизвестным, которое будет больше во время выполнения.
Два дочерних представления - это TextView
и Spinner
. Spinner
должен заполнить все оставшееся пространство в ширине LinearLayout
. Но если я изменю Spinner
layout_width
на match_parent
и TextView
не будет достаточно большим, Spinner
будет обрезать его содержимое.
В основном мне нужен способ выбрать максимальную ширину между wrap_content
и match_parent
.
Это макет:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/parentView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="-2dp"
android:layout_marginBottom="-2dp"
android:paddingStart="4dp"
android:paddingEnd="4dp"
android:textSize="12sp"
android:textColor="?android:textColorHint"
tools:text="Label" />
<Spinner
android:id="@+id/spinner"
style="@style/Widget.AppCompat.Spinner.Underlined"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<!-- or android:layout_width="match_parent"? need max of both... -->
</LinearLayout>
Есть хитрость, которую вы можете использовать для выполнения этого с LinearLayout
и без дополнительных представлений: используйте wrap_content
для родительского LinearLayout и match_parent
для обоих match_parent
элементов. Пока у LinearLayout нет дочерних элементов с фиксированными размерами, эта комбинация сделает общий родительский элемент таким же широким, как и его самый широкий дочерний элемент.
<LinearLayout
android:layout_width="wrap_content"
...>
<TextView
android:layout_width="match_parent"
.../>
<Spinner
android:layout_width="match_parent"
.../>
</LinearLayout>
(Я добавил цвет фона в LinearLayout, чтобы было легче увидеть, как он сам себя масштабирует.)
Обновление: ответ Ben P выполняет это, все еще используя LinearLayout
.
После дальнейшего тестирования различных решений выясняется, что лучшим решением будет не использовать LinearLayout
в качестве родительской группы представлений. По любой причине FrameLayout
обеспечивает желаемое поведение переноса содержимого дочернего представления, даже когда дочернее представление установлено в match_parent
, так что используется максимум двух размеров. LinearLayout
не обеспечивает такое же поведение.
Но тогда проблема в том, как заставить два дочерних представления располагаться вертикально. Это может быть достигнуто в FrameLayout
с помощью комбинации layout_gravity
и представления Space
. По какой-то странной причине, по крайней мере, в моем случае использования этого макета в качестве элемента в родительском FlexboxLayout
, установка высоты FrameLayout
явно не подойдет для определения ее высоты. Использование wrap_content
с представлением Space
установленным на требуемую высоту, работает.
Это макет, который работает, не требуя дополнительного кода:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/parentView"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<!-- setting FrameLayout layout_height doesn't work for some reason -->
<Space
android:layout_width="0dp"
android:layout_height="56dp" />
<TextView
android:id="@+id/label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="top|start"
android:layout_marginTop="-2dp"
android:layout_marginBottom="-2dp"
android:paddingStart="4dp"
android:paddingEnd="4dp"
android:textSize="12sp"
android:textColor="?android:textColorHint"
tools:text="Label" />
<Spinner
android:id="@+id/spinner"
style="@style/Widget.AppCompat.Spinner.Underlined"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom" />
</FrameLayout>
Space
, хотя я не могу точно сказать, что он будет работать в вашем случае использования FlexboxLayout. Проверьте мой ответ ниже и дайте мне знать.
Обновление: см. Мой другой ответ для лучшего решения.
Хотелось бы, чтобы было более элегантное решение, но способ, которым я достиг этого, заключается в добавлении дополнительного скрытого дублирующего представления Spinner
используемого только для определения размера родительского LinearLayout
для достижения максимального значения либо wrap_content
либо match_parent
, в зависимости от того, что больше.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/parentView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="-2dp"
android:layout_marginBottom="-2dp"
android:paddingStart="4dp"
android:paddingEnd="4dp"
android:textSize="12sp"
android:textColor="?android:textColorHint"
tools:text="Label" />
<Spinner
android:id="@+id/spinner"
style="@style/Widget.AppCompat.Spinner.Underlined"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<!-- visible view width set to match_parent -->
<Spinner
android:id="@+id/spinnerHiddenSizer"
style="@style/Widget.AppCompat.Spinner.Underlined"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:visibility="invisible" />
<!-- invisible view width set to wrap_content -->
<!-- also set height to 0dp so it takes up no vertical space -->
<!-- in code, set this Spinner adapter to the same as -->
<!-- the visible spinner so that it sized the same -->
</LinearLayout>
Таким образом, если wrap_content
приведет к тому, что ширина Spinner
будет больше, чем match_parent
, скрытое представление приведет к LinearLayout
размера LinearLayout
до этого большего размера, а видимая ширина match_parent
увеличится до этой ширины.
Проблема, что ваш LinearLayout
является ширина wrap_content
. Это означает, что дети никогда не будут заполнять всю ширину, только если содержимое внутри изменит ширину.
Просто измените строку внутри LinearLayout
. От:
android:layout_width="wrap_content"
к
android:layout_width="match_parent"
LinearLayout
для заполнения его родителя. LinearLayout
должен обернуть свой детский контент.
попробуйте установить вес макета android:layout_weight
. Вот определение из SO: https://stackoverflow.com/a/3996104/8738574
. установите вес счетчика так, чтобы он был больше, чем у textView, а ширина - 0 (ноль).
TextView:
android:layout_weight="1"
android:layout_width="0px"
Spinner:
android:layout_weight="2"
android:layout_width="0px"
layout_weight
работает в направлении, в котором LinearLayout
свои дочерние представления. В случае моего вертикального LinearLayout
, это позволило бы детям увеличить свою высоту, чтобы заполнить оставшееся пространство. Мне нужно, чтобы они расширили свою ширину .
LinearLayout
, в отличие отFrameLayout
. Спасибо за чаевые!