代码之家  ›  专栏  ›  技术社区  ›  Jeff Lockhart

具有视图环绕内容,但如果空间可用,则与父级匹配

  •  1
  • Jeff Lockhart  · 技术社区  · 6 年前

    我有两种观点 LinearLayout ,两者都应该 wrap_content 使它们最小限度地大到足以显示其内容。这个 线性布局 视图组应该 包装物含量 两个子组中的一个,其大小刚好足以显示两个子视图的内容。

    但在此之后,如果两个子视图中的一个较大,则另一个子视图应展开以匹配父视图,以填充其剩余可用空间。两个子视图的内容是动态的,未知的,在运行时会变大。

    两个孩子的观点是 TextView 和A Spinner . 这个 纺纱机 应该填充 线性布局 宽度。但是如果我改变 纺纱机 layout_width 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>
    
    5 回复  |  直到 6 年前
        1
  •  1
  •   Ben P.    6 年前

    你可以用一个技巧来完成这个任务 LinearLayout 没有额外的视图:使用 wrap_content 在父级线性布局和 match_parent 对于 二者都 孩子们。只要线性布局没有 任何 具有固定大小的子级,此组合将使整个父级与其最宽的子级一样宽。

    <LinearLayout
        android:layout_width="wrap_content"
        ...>
    
        <TextView
            android:layout_width="match_parent"
            .../>
    
        <Spinner
            android:layout_width="match_parent"
            .../>
    
    </LinearLayout>
    

    enter image description here

    enter image description here

    (我在LinearLayout中添加了背景色,以便更容易看到它的大小调整方式。)

        2
  •  0
  •   Dmytro Ivanov    6 年前

    你的问题是 LinearLayout 宽度是 wrap_content . 这意味着孩子们永远不会填满整个宽度,除非里面的内容会改变宽度。

    只需在里面换行就行了 线性布局 . 来自:

    android:layout_width="wrap_content"
    

    android:layout_width="match_parent"
    
        3
  •  0
  •   medyas Maksim Novikov    6 年前

    尝试设置布局权重 android:layout_weight . 以下是SO的定义: https://stackoverflow.com/a/3996104/8738574 . 将微调器的权重设置为大于textView,宽度设置为0(零)。

    TextView:

    android:layout_weight="1"
    android:layout_width="0px"
    

    斯平纳:

    android:layout_weight="2"
    android:layout_width="0px"
    
        4
  •  0
  •   Jeff Lockhart    6 年前

    更新: 请看我的另一个答案以获得更好的解决方案。

    我希望有一个更优雅的解决方案,但我实现这一点的方法是添加一个额外的隐藏副本 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's adapter to the same as -->
        <!-- the visible spinner so that it's sized the same -->
    
    </LinearLayout>
    

    这样,如果 包装物含量 会导致 纺纱机 的宽度大于 配对母体 ,隐藏视图将导致 线性布局 要调整到这个较大的尺寸和可见的 配对母体 宽度将扩展到此宽度。

        5
  •  0
  •   Jeff Lockhart    6 年前

    更新: Ben P的答案在使用 LinearLayout .

    在进一步测试了不同的解决方案之后,发现更好的解决方案是不使用 线性布局 作为父视图组。无论出于什么原因, FrameLayout 提供所需的包装子视图内容的行为,即使子视图设置为 match_parent ,以便使用两种尺寸的最大值。 线性布局 不提供相同的行为。

    但问题是如何让两个子视图垂直堆叠。这可以在 框架布局 结合了 layout_gravity 和A Space 查看。出于一些奇怪的原因,至少在我的用例中,将此布局用作 FlexboxLayout 父级,设置 框架布局 高度显然无法调整其高度。使用 wrap_content 用一个 空间 设置为所需高度的视图确实有效。

    这是一种有效的布局,不需要任何附加代码:

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