Иметь представление обтекания содержимого, но соответствовать родительскому, если есть свободное место

1

У меня есть два представления в 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>
Теги:
layout

5 ответов

1
Лучший ответ

Есть хитрость, которую вы можете использовать для выполнения этого с 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>

Изображение 174551

Изображение 174551

(Я добавил цвет фона в LinearLayout, чтобы было легче увидеть, как он сам себя масштабирует.)

  • 0
    Это делает свое дело! Странно, как это поведение для LinearLayout , в отличие от FrameLayout . Спасибо за чаевые!
0

Обновление: ответ 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>
  • 0
    Я верю, что вы можете получить то, что вы хотите, используя LinearLayout и без дополнительного представления Space , хотя я не могу точно сказать, что он будет работать в вашем случае использования FlexboxLayout. Проверьте мой ответ ниже и дайте мне знать.
0

Обновление: см. Мой другой ответ для лучшего решения.

Хотелось бы, чтобы было более элегантное решение, но способ, которым я достиг этого, заключается в добавлении дополнительного скрытого дублирующего представления 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 увеличится до этой ширины.

0

Проблема, что ваш LinearLayout является ширина wrap_content. Это означает, что дети никогда не будут заполнять всю ширину, только если содержимое внутри изменит ширину.

Просто измените строку внутри LinearLayout. От:

android:layout_width="wrap_content"

к

android:layout_width="match_parent"
  • 0
    Это не то, что я ищу. Внесение этого изменения приведет к расширению LinearLayout для заполнения его родителя. LinearLayout должен обернуть свой детский контент.
0

попробуйте установить вес макета 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"
  • 0
    Это не будет работать, так как layout_weight работает в направлении, в котором LinearLayout свои дочерние представления. В случае моего вертикального LinearLayout , это позволило бы детям увеличить свою высоту, чтобы заполнить оставшееся пространство. Мне нужно, чтобы они расширили свою ширину .
  • 0
    хорошо, так что вам нужно определить, какой вид больше, и установить другой, попробуйте получить их ширину во время выполнения и проверить, какой из них больше, и установить их ширину.
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню